PageSourceSearch

https://www.scheduleanyone.com/cdn-schedule/js/cdn-staff-wizard.js?v=211

js scheduleanyone.com collected 2026-09-24 10:56:23 UTC 2,899,060 bytes, 66,898 lines download raw bytes

1if (typeof GLO === 'undefined') { GLO = {}; }
2if (GLO.Staff == undefined) { GLO.Staff = {}; }
3if (GLO.Communicate == undefined) { GLO.Communicate = {}; }
4
5if (typeof SA === 'undefined') { var SA = (function() { }); }
6if (SA.Profile === undefined) { SA.Profile = {}; }
7
8GLO.Staff = (function() {
9	function _conStaff() { }
10    
11    _conStaff.hasEmail = function(staffId) {
12    	var jsonStaff = _getStaffJson(staffId);
13    	
14    	if (jsonStaff && !UTIL.isEmpty(jsonStaff.email)) {
15    		return true;
16    	} else {
17    		var aProfile = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?open=staff=' + staffId + '\', this, event, true);">Profile -> Staff</a>';
18	    	var msg1 = '<p>To receive a text message please go to ' + aProfile + ' and add the <b>Email Address</b></p>';
19			var htm = '<div id="pop-warn-staff-missing-phone">' + msg1 + '</div>';
20			
21			GLO.Popup.Warning.open(htm, 'Unable to Send Email');
22	    	return false;
23    	}
24    }
25	
26	_conStaff.hasText = function(staffId, isUseSmsGateway) {
27    	var jsonStaff = _getStaffJson(staffId);
28    	var warnLabel = 'phone number';
29    	
30    	if (jsonStaff && !UTIL.isEmpty(jsonStaff.mobile_phone)) {
31    		if (isUseSmsGateway && !UTIL.isEmpty(jsonStaff.mobile_provider)) {
32    			warnLabel = 'phone company <i class="narrow-text">(to enable texts)</i>';
33    		} else {
34    			return true;
35    		}
36    	} else {
37    		
38    	}
39    	
40    	var aProfile = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?open=staff=' + staffId + '\', this, event, true);">Profile -> Staff</a>';
41    	var msg1 = '<p>To receive a text message please go to ' + aProfile + ' and add the <b>' + warnLabel + '</b></p>';
42		var htm = '<div id="pop-warn-staff-missing-phone">' + msg1 + '</div>';
43		
44		GLO.Popup.Warning.open(htm, 'Unable to Send Text')
45    	return false;
46    }
47    
48    function _displayMissingContactWarning(messageFormat, isMissingSmsGateway) {
49    	if (messageFormat == 3) {
50			if (isMissingSmsGateway) {
51				var h1 = 'Texting You Is Disabled';
52				var msg1 = '<p>To send yourself a sample text message please enable text messaging for yourself</p>';
53				var msg3 = '<p>Next to your phone number check the <b style="color: black;">Text Me</b> checkbox</p>';
54			} else {
55				var h1 = 'Your Mobile Phone Number is Empty';
56				var msg1 = '<p>To send yourself a sample text message please add your mobile phone to your profile</p>';
57				var msg3 = 'and add your mobile phone';
58			}
59		} else {
60			var h1 = 'Missing Your Email';
61			var msg1 = '<p>To send yourself a sample email please add your email to your profile</p>';
62			var msg3 = 'and add your email address';
63		}
64		
65		var astyle = 'display: inline-block; line-height: 100%; white-space: nowrap; border-bottom-width: 1px; border-bottom-style: solid;';
66		var a = '<a href="' + GLO.Link.WebsiteDomain + 'provider/profile/1" style="' + astyle + '">Profile ' + UI.arrow + ' Me</a>';
67		var msg2 = '<div style="margin-top: 12px; margin-bottom: 12px;">Go to ' + a + '</div>';
68		
69		msg1 = '<div style="font-size: 16px;">' + msg1 + '</div>';
70		var htm = '<div class="friendly-msg4"><h1 class="friendly-msg4">' + h1 + '</h1><div class="friendly-msg4">' + msg1 + msg2 + msg3 + '</div></div>';
71		new GLO.Popup.Warning(htm);
72    }
73    
74    function _getStaffJson(staffId) {
75    	if (SA.StaffContact && SA.StaffContact.length > 0) {
76    		for (var i=0; i < SA.StaffContact.length; i++) {
77    			if (staffId == SA.StaffContact[i].id) {
78    				return SA.StaffContact[i];
79    			}
80    		}
81    	}
82    	
83    	return null;
84    }
85	
86	return _conStaff;
87})();
88
89
90GLO.Staff.Filter = (function() {		//use to set staff filter --> GLO.Report.initStaffFilter()
91    function _constructor(name) { }
92    _constructor.isReportPortal = false;
93    _constructor.isReportFilterEasyQuery = false;
94    var _intervalCounter = 0, _sfilterInterval = null;
95    
96    _constructor.initOnPageLoad = function() {
97    	var jfilter = $('#top-staffName #staff-filter');
98    	
99    	if (GLO.Info.isMobile()) {
100    		var jfOpt = jfilter;
101    		_initMobile(jfilter);
102    	} else {
103    		var jfOpt = jfilter.find('optgroup#staff-filter-s');
104    	}
105    	
106    	if (jfOpt.find('option').length === 1) {
107    		if (GLO.Info.isMobile()) {
108    			jfilter.remove();
109    		} else {
110    			var jloc = jfilter.find('#location-filter-sg').find('option');
111    			
112    			if (jloc.length > 0) {
113    				var htm = _getLocationDropDown(jloc);
114    			} else {
115    				var htm = '<span style="padding-right: 6px; color: #999;">' + SA.Resource.Hi + ' ' + UTIL.maxString(GLO.Info.getStaffName(), 20, true) + '</span>';
116    			}
117    			
118    			jfilter.closest('#top-staffName').html(htm);
119    			jfilter.remove();
120    		}
121    	}
122    	
123    	var fGroupVal = GLO.Uri.query('sfiltergroup');
124    	
125    	if (!UTIL.isEmpty(fGroupVal)) {
126    		if (fGroupVal == '4') { fGroupVal = 'house'; }
127    		
128    		jfilter.val(fGroupVal);
129    	}
130    	
131    	_initHelloBar();
132    }
133    function _initMobile(jfilter) {
134    	if ($('#calendar').length === 0) { return; }
135    	GLO.Info.init();
136    	if (GLO.Info.isIndependentPackage()) { return; }
137    	if (GLO.Info.roleType < 100) { return ''; }
138    	
139    	var jopt = UserPortal.getStaffDropDown().find('option');
140    	var i = 0, staffCount = jopt.length, staffWidthMax = parseInt((innerWidth - 30)/36);
141    	
142    	if (jopt.eq(0).text() === 'Anyone' || UTIL.coalesceString(jopt.eq(0).attr('staff_ids')).indexOf(',') !== -1) {
143    		i = 1;
144    	}
145    	
146    	if (staffCount - i < 12 || staffCount - staffWidthMax - i < 5) { return; }
147    	
148    	if (GLO.Staff.Filter.getHouseStaff().split(',').length > staffWidthMax + 4) {
149    		jfilter.find('option[value="house"]').remove();
150    	}
151    	
152    	//jfilter.find('option[value="today"]').remove();
153    	jfilter.find('option[value="all"]').remove();
154    	jfilter.prepend('<optgroup id="staff-filter-staff-group"></optgroup>');
155    	var sids = '', name1 = jopt.eq(i).text();
156    	
157    	if (staffWidthMax > 12) {
158    		staffWidthMax = 12;
159    	} else if (staffWidthMax < 8) {
160    		staffWidthMax = 8;
161    	}
162    	
163    	for (; i < staffCount; i++) {
164    		if (i > 0 && i % staffWidthMax === 0) {
165    			if (i + 2 === staffCount) {
166    				sids += ',' + jopt.eq(i).attr('value');
167    				var name2 = _getName2(jopt, i);
168    				_addStaffGroup(jfilter, sids, name1, name2);
169    				return;
170    			} else {
171    				var name2 = _getName2(jopt, i-1);
172    				_addStaffGroup(jfilter, sids, name1, name2);
173    			}
174    			
175    			sids = '';
176    			name1 = jopt.eq(i).text();
177    		}
178    		
179    		if (sids !== '') { sids += ','; }
180    		sids += jopt.eq(i).attr('value');
181    	}
182    	
183    	var name2 = _getName2(jopt, i-1);
184    	_addStaffGroup(jfilter, sids, name1, name2);
185    }
186    function _getName2(jopt, iterator) {
187    	if (!UTIL.isEmpty(jopt.eq(iterator).attr('staff_ids'))) {			//= Anyone
188    		--iterator;
189    	}
190    	
191    	return jopt.eq(iterator).text();
192    }
193    function _addStaffGroup(jfilter, sids, name1, name2) {
194    	var option = '<option class="sfilter-staff-group" staff_ids="' + sids + '">' + name1 + ' - ' + name2 + '</option>';
195    	jfilter.find('#staff-filter-staff-group').append(option);
196    }
197    _constructor.init = function() {
198        var jdup = $('#sFilter-list .dup-viewProfile');
199        
200        if (GLO.Info.isIPad) {
201            var jHeader = $('#search-bar').css({ "margin-bottom": "25px" });
202            jHeader.find('#top-staffName').css({ "font-size": "77%" });
203            jHeader.find('#top-searchBox').css({ "width": "11em", "font-size": "85%" });
204            
205            GLO.UI.initAnimateLink(jdup, 2, GLO.UI.pinkify);
206        } else if (GLO.Info.isMobile()) {
207            var imgDirectory = GLO.Data.cdnDirectory + 'image/icon/arrow/aug2012/';
208            
209            GLO.UI.initAnimateLink(jdup, 2, GLO.UI.pinkify);
210        }
211
212        $("#sFilter-list").find("tr:odd").addClass('EveryOtherRow');
213        
214        var tbl = $('#sFilter-list');
215        if (tbl.height() < 450) { tbl.height(450); }
216        
217        var id = GLO.Uri.query('id');
218        var idType = GLO.Uri.query('type');
219
220        if (!UTIL.isEmpty(id) && !UTIL.isEmpty(idType)) {
221            if (idType == 's') {
222                $('#sFilter-list tr#trStaff' + id + ' .staffCheck').prop('checked', true);
223            } else if (idType == 'sg') {
224                var jDD = $('#ServicesOffered');
225                jDD.val(id);
226                GLO.Staff.Filter.changeServiceTypeDD(jDD[0]);
227            }
228        } else {
229            var strIDS = GLO.Uri.url('sfilter');
230
231            if (!UTIL.isEmpty(strIDS)) {
232                var ids = String(strIDS).split(',');
233                var tbl = $('#sFilter-list tr');
234                var rowCnt = tbl.length;
235
236                for (var row=0; row < rowCnt; row++) {
237                    for (var i=0; i < ids.length; i++) {
238                        if ( tbl.eq(row).attr('id').substr(7) == ids[i] ) {
239                            tbl.eq(row).find('>td input:checkbox.staffCheck').prop('checked', true);
240                        }
241                    }
242                }
243            }
244        }
245    }
246    
247    function _initHelloBar() {
248    	if ($('#staffFilter').length > 0) {
249			if ($('#create-appt-staff1 #Staff_id').find('option').length === 1) {
250				GLO.Staff.Filter.removeFilter();			//= remove staff filter hello bar if business package only has 1 staff member.
251			}
252		}
253    }
254    
255    function _getLocationDropDown(jloc) {
256    	var bgc = GLO.Data.provider.backgroundColor;
257		var pid = GLO.Data.provider.id;
258		var pname = GLO.Data.provider.name;
259		var htm = '<select id="location-filter" onchange="GLO.Staff.Filter.changeLocation(this, event)" style="color: rgb(' + bgc + ');">'
260					+ '<option value="' + pid + '" style="background-color: rgba(' + bgc + ',.4);" provider_color_vc="' + bgc + '" selected="selected">' + pname + '</option>';
261		
262		for (var i=0; i < jloc.length; i++) {
263			htm += jloc.eq(i).outerHTML();
264		}
265		
266		return htm + '</select>';
267    }
268    
269    _constructor.checkBox = function(element) {
270        var checkbox = $(element);
271        if (checkbox.attr('name') !== 'staffCheck') { checkbox = checkbox.find('input'); }
272
273        checkbox.prop('checked', !checkbox[0].checked);
274    }
275
276    _constructor.changeServiceTypeDD = function(element) {
277        var jStaffRows = $('#sFilter-list tr');
278        var arr;
279
280        for (var i=0; i < jStaffRows.length; i++) {
281            arr = jStaffRows.eq(i).attr('sg_ids').split(',');
282
283            if (arr.has(element.value) && element.value != '') {
284                jStaffRows.eq(i).find('.staffCheck').prop('checked', true);
285            } else {
286                jStaffRows.eq(i).find('.staffCheck').prop('checked', false);
287            }
288        }
289    }
290
291    _constructor.clickHeaderOption = function(element) {
292        //if (element.value == '') { document.location = GLO.Link.Page.Provider.StaffFilter + '?type=custom'; }
293    }
294
295    _constructor.displayQuickView = function(thisDD, ev) {
296        if ((ev.ctrlKey || ev.altKey) && $(thisDD).find('option:selected').parent().attr('id') == 'staff-filter-s') {
297            Wiz5.openStaffQuickView(thisDD.value);
298            ev.preventDefault();
299            return false;
300        }
301    }
302    
303    function _loadWorkingTodayOrCurrentDay() {
304    	var dt = GLO.Calendar.cal.fullCalendar('getView').start;
305    	var btnAdd = '<span class="btnAdd"><a style="padding: 8px 16px 6px;" onclick="GLO.Staff.Filter.reloadStaffWorking';
306    	var clearFilter, currDay = '', today = btnAdd + '()">Today</a></span>';
307    	
308    	if (!UTIL.isSameDay(new Date(GLO.Data.provider.now_dt), dt)) {
309    		var currDay = btnAdd + '(\'' + dt.toGloDate() + '\')">' + dt.getWeekDayString(GLO.Info.isMobile()) + ', ' + dt.toSADate(true) + '</a></span>';
310    	}
311    	
312    	var msg = '<div style="font-weight: bold;">Filter by staff working on which day?</div>';
313    	var htm = '<div id="pop-filter-staff-working-today">' + msg + '<div>' + today + currDay + '</div></div>';
314    	var h1 = 'Select Day';
315    	
316    	var jpop = GLO.Popup.Confirm.open(htm, h1).getPopup();
317    	jpop.find('h1').css({ "margin-bottom": 0 });
318    	jpop.find('.msg').css({ "margin-bottom": 0, "padding-top": 0 });
319    	jpop.find('.btnYes').remove();
320    	jpop.find('.btnNo').addClass('btnCancel').removeClass('btnNo').css({ "float": "none", "margin": "0", "padding": "0" }).find('>a').css({ "letter-spacing": "1px" }).text('Close');
321    }
322    
323    function _setFilterToUrl() {
324    	var sfilter = String(UTIL.coalesce(GLO.Uri.query('sfiltergroup'), GLO.Uri.query('sfilter'), 'all')).toLowerCase();
325    	$('#staff-filter').val(sfilter);
326    }
327    
328    function _loadWorkingToday(isDiffDay) {
329    	var isToday = GLO.Calendar.isToday();
330    	var dtLastUsed = new Date($('#staff-filter').find('#staff-filter-diffday').attr('date'));
331    	var dtCalendar = new Date(GLO.Calendar.cal.fullCalendar('getView').start);
332    	
333    	if (!isDiffDay && !isToday) {
334    		if (!UTIL.isSameDay(dtLastUsed, dtCalendar)) {
335    			_loadWorkingTodayOrCurrentDay();
336    			_setFilterToUrl();
337    			return;
338    		}
339    	} else if (isDiffDay && isToday) {
340    		_openSelectDayPopup();
341    		//_setSelectDiffDayWarning();
342    		_setFilterToUrl();
343    		return;
344    	}
345    	
346    	if (isDiffDay) {
347    		_constructor.reloadStaffWorking(dtCalendar);
348    	} else {
349    		_constructor.reloadStaffWorking();
350    	}
351    }
352    
353    function _openSelectDayPopup() {
354    	var msg = '<div id="pop-select-day">'
355    				+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
356    				+ '<label for="New_d" style="font-weight: bold;">Select Day</label>'
357    				+ '<input id="New_d" type="text" style="width: 100px; letter-spacing: 1px;"/>'
358    			+ '</div>';
359    	var jpop = GLO.Popup.Info.open(msg, 'Select Day').getPopup();
360		jpop.find('.msg').css({ "padding-top": "0" });
361		
362		jpop.find('#New_d').datepicker({
363				showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths()
364				, onSelect: GLO.Staff.Filter.staffWorkingOnDateSelect, minDate: "-6M", maxDate: "+6M"
365		});
366		jpop.find('#New_d').blur();
367    }
368    
369    _constructor.staffWorkingOnDateSelect = function() {
370    	var jpop = $('#pop-select-day').closest('.glopop');
371    	var jdt = jpop.find('#New_d').blur();
372    	var dt = new Date(jdt.val());
373    	var dtLabel = dt.getWeekDayString(true) + ' ' + dt.toSADate(true);
374    	var msg = 'Navigating Calendar to <b style="color: #4F81BD; white-space: nowrap;">' + dtLabel + '</b><br/>and only displaying staff that work that day';
375    	
376    	GLO.Popup.close(jpop);
377    	var ojProcessing = GLO.Popup.Processing.open(msg, 'Navigating Calendar');
378    	
379    	setTimeout(function() {
380    		ojProcessing.close();
381    		GLO.Staff.Filter.reloadStaffWorking(dt);
382    	}, 1200);
383    }
384    
385    function _setSelectDiffDayWarning() {
386    	var fn = function() { $('#staff-filter').focus(); };
387		var css = 'margin-bottom: 12px; text-align: left;';
388		var icss = 'white-space: nowrap; font-weight: bold;';
389		
390		var msg1 = '<div style="' + css + '">
390Use this option to only display the staff that work on a specific day</div>';
391		var msg2 = '<div style="' + css + '">Navigate to the desired day on the calendar, then in the staff filter select <i style="' + icss + '">"Working Different Day"</i></div>';
392		var msg3 = '<div style="' + css + 'margin-top: 6px; padding-top: 8px; border-top: 1px solid rgba(200,200,240,.8);text-align: center;">Select <i style="' + icss + '">"All"</i> in the staff filter to display all staff</div>';
393		
394		var jpop = GLO.Popup.Info.open(msg1 + msg2 + msg3, 'Navigate Calendar, then Filter Staff by Day', fn).getPopup();
395		jpop.find('.msg').css({ "padding-top": "0" });
396    }
397    
398    function _createStaffObject(sid, startTime, endTime, iStart, iEnd, color) {
399    	var order = 999, thumbnail = null;
400    	
401    	for (var i=0; i < GLO.staffResources.length; i++) {
402    		if (GLO.staffResources[i].id == sid) {
403    			thumbnail = GLO.staffResources[i].thumbnail;
404    			order = i;
405    			break;
406    		}
407    	}
408    	
409		return { "id": sid, "order": order, "thumbnail": $.trim(thumbnail)
410				, "start_tm": startTime, "end_tm": endTime, "start_sr": iStart, "end_sr": iEnd
411				, "color": color, "smids": [], "breaks": [], "clockInAndOut": [] };					//if have more than 1 clock-ins, other than most recent clock-in put in -> clockInAndOut
412    }
413    
414    //1. lookup staff normal off time 	-> GLO.resourceHours
415	//2. staff adjusted day				-> GLO.AdjustedHours
416	//3. business closed due to holiday -> GLO.Data.holidays (not needed: GLO.closedDates), only include staff that adjusted day to be open
417	//4. day marked off with off time	-> calEvents
418    _constructor.staffWorkingOnDay = function(dayDate, calEvents) {						//= this version does 
418NOT rely on data in calendar
419    	var dayOfWeek = dayDate.getDay();
420        var arrStaff = [];
421        
422        for (var i=0; i < GLO.resourceHours.length; i++) {
423            var role = UTIL.coalesceInt(GLO.resourceHours[i].role, 0);
424            
425            if (role > 99) {
426	            var sid = GLO.resourceHours[i].id;
427            	var hrs = GLO.Schedule.lookupStaffNormalHours(dayDate, sid);			//var hrs = GLO.resourceHours[i].normalHours[dayOfWeek];
428            	var isAdjusted = (hrs.length > 3 && UTIL.parseBool(hrs[3]));
429            	
430            	if (!UserPortal.Calendar.isHoliday(dayDate) || isAdjusted) {
431		            var tmStart = hrs[0], tmEnd = hrs[1];
432		            var iStart = UTIL.timeToInt(tmStart), iEnd = UTIL.timeToInt(tmEnd);
433		            
434		            if (GLO.isPOS && iEnd - iStart <= 15) {
435		            	var tmClockIn = _isClockedIn(sid, calEvents);
436		            	
437		            	if (UTIL.isValidTime(tmClockIn)) {
438		            		var tmStart = tmClockIn, tmEnd = _getProviderEndTimeToday();
439		            		var iStart = UTIL.timeToInt(tmStart), iEnd = UTIL.timeToInt(tmEnd);
440		            	}
441		            }
442		            
443		            if (iEnd - iStart > 15) {
444		            	if (UserPortal.staffPerformsClientService(sid)) {
445		            		var ojStaff = _createStaffObject(sid, tmStart, tmEnd, iStart, iEnd, GLO.resourceHours[i].color);
446		            		ojStaff.name = UserPortal.getStaffName(sid);			//for debugging
447		            		
448		            		if (GLO.resourceHours[i].walkin_signin_sr > 0) {
449		            			ojStaff.walkin_signin_sr = GLO.resourceHours[i].walkin_signin_sr;
450		            		}
451		            		
452		            		if (_isWorkingOnCurrentDay2(dayDate, ojStaff, calEvents)) {
453			            		ojStaff.is_first_available_fl = UserPortal.isFirstAvailable(sid);
454			            		arrStaff.push(ojStaff);
455			            	}
456			            }
457		            }
458	            }
459            }
460        }
461        
462        return arrStaff;
463    }
464    
465    function _getProviderEndTimeToday() {
466    	var hrType = new Date().getDay() + 1;
467    	var endTime;
468    	
469    	for (var i=0; i < GLO.ProviderHours.length; i++) {
470    		if (GLO.ProviderHours[i].hours_type_cd == hrType) {
471    			endTime = GLO.ProviderHours[i].end_tm;
472    			break;
473    		}
474    	}
475    	
476    	if (UTIL.isValidTime(endTime)) {
477    		return endTime;
478    	} else {
479    		return GLO.calendarMaxTime;
480    	}
481    }
482    function _isClockedIn(staffId, calEvents) {
483    	for (var i=0; i < calEvents.length; i++) {
484    		if (staffId == calEvents[i].staff_id) {
485    			if (calEvents[i].appt_status_cd == 201 && UTIL.isDate(calEvents[i].checkin_dt) && UTIL.isEmpty(calEvents[i].checkout_dt)) {
486    				return new Date(calEvents[i].checkin_dt).toGloTime();
487    			}
488    		}
489    	}
490    	
491    	return null;
492    }
493    
494    function _staffWorkingOn(dayDate, isCurrDay) {
495    	var dayOfWeek = dayDate.getDay();
496        var arrStaff = [];
497        //var intMinTime = UTIL.timeToInt(GLO.Calendar.minTime), intMaxTime = UTIL.timeToInt(GLO.Calendar.maxTime);
498        //var bizStart = UTIL.joinDateAndTime(dayDate, GLO.Calendar.minTime), bizEnd = UTIL.joinDateAndTime(dayDate, GLO.Calendar.maxTime);
499        
500        for (var i=0; i < GLO.resourceHours.length; i++) {
501            var sid = GLO.resourceHours[i].id;
502            var role = UTIL.coalesceInt(GLO.resourceHours[i].role, 0);
503            var hrs = GLO.Schedule.lookupStaffNormalHours(dayDate, sid);			//var hrs = GLO.resourceHours[i].normalHours[dayOfWeek];
504            var iStart = UTIL.timeToInt(hrs[0]);
505            var iEnd = UTIL.timeToInt(hrs[1]);
506
507            if (iEnd - iStart > 15 && role > 99) {
508            	if (!isCurrDay || _isWorkingOnCurrentDay(sid, dayDate, iStart, iEnd)) {
509	            	if (UserPortal.staffPerformsClientService(sid)) {
510	            		arrStaff.push({ "id": sid, "start_tm": hrs[0], "end_tm": hrs[1] });
511	            	}
512	            }
513            }
514        }
515        
516        return arrStaff;
517    }
518    
519    /* OVERVIEW of Label Appt-Status (Priority)
520    	21	Checked-In 			(1 or 21)			now >= svc time = BUSY | SVC ends in 15 min			YELLOW
521		 2	Sign-In				(2)					CLIENT WAITING										PINK
522		 5 	NOW					(5)					APPT NOW 		(starts within 15 minutes)			GRADIENT
523		
524		39	Break Time 			(10)				ON BREAK											DARK GREY
525		41	Upcoming Off Time 	(11)				BREAK in 5 min	(starts within 30 minutes)			LIGHT GREY
526		
527		42	UPCOMING			(29)				now - 1 hr <= 0 = FREE | APPT in 45 min				PURPLE
528		29	LATE				(42)				CLIENT LATE (15-30 minutes late)					LIGHT PURPLE			rgba(120, 0,200, .2)
529    */
530    
531    function _updateStaffStatusWithAnotherEvent(ojStaff, ev) {
532	    if (UTIL.isEmptyObject(ojStaff.status)) {					//= status empty if staff done working for the day
533	    	//var eventXml = UTIL.htmlEncode(UTIL.jsonToXml(ev));
534	    	//GLO.Log.insertSimple('_isWorkingOnCurrentDay2() No ojStaff', eventXml, 'warning');
535	    	return;
536	    } /* else if (ev.appt_status_cd != ojStaff.status.appt_status_cd) {				//these will often NOT match, for example appt status = 10 (new) + staff status = 42 (upcoming)
537	    	var eventXml = 'eventXml (' + ev.appt_status_cd + '):' + UTIL.htmlEncode(UTIL.jsonToXml(ev));
538	    	var staffXml = 'staffXml (' + ojStaff.status.appt_status_cd + '):' + UTIL.htmlEncode(UTIL.jsonToXml(ojStaff));
539	    	var logMsg = '_isWorkingOnCurrentDay2() Status: Staff Card vs Event \n\n' + staffXml + ' | ' + eventXml;
540	    	
541	    	GLO.Log.insertSimple('Staff Card vs Event', logMsg, 'warning');
542	    } */
543	    
544	    var now = new Date();
545	    
546	    if (now > new Date(ojStaff.status.event.start) && now < new Date(ojStaff.status.event.end)) {
547	    	ojStaff.status.otherServices.push(ev);
548	    } else if (now > new Date(ev.start) && now < new Date(ev.end)) {
549	    	ojStaff.status.otherServices.push(ojStaff.status.event);
550	    	ojStaff.status.event = ev;
551	    } else {
552	    	var ev1 = UTIL.coalesceInt( (new Date(ev.start) - new Date()) / (1000 * 60), 0);
553	    	var ev2 = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0);
554	    	var ev0 = Math.abs(ev1) < Math.abs(ev2) ? Math.abs(ev1) : Math.abs(ev2);
555	    	
556	    	var oj1 = UTIL.coalesceInt( (new Date(ojStaff.status.event.start) - new Date()) / (1000 * 60), 0);
557	    	var oj2 = UTIL.coalesceInt( (new Date(ojStaff.status.event.end) - new Date()) / (1000 * 60), 0);
558	    	var oj0 = Math.abs(oj1) < Math.abs(oj2) ? Math.abs(oj1) : Math.abs(oj2);
559	    	
560	    	if (ev0 < oj0) {
561	    		ojStaff.status.otherServices.push(ojStaff.status.event);
562	    		ojStaff.status.event = ev;
563	    	} else {
564	    		ojStaff.status.otherServices.push(ev);
565	    	}
566	    }
567    }
568    function _updateStaffStatusForCheckin(ojStaff, ev) {
569    	var endsIn = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0);
570    	
571    	//ojStaff.status.event.push(ev);		//for now this accepts just 1 event (is not an array), additional events for the staff on the same ticket go to: ojStaff.status.other
572    	
573		ojStaff.status.label = _getStaffStatusLabelForCheckin(ev, endsIn);
574		ojStaff.status.description = 'Staff has ' + (ojStaff.status.otherServices.length + 1) + ' services on this ticket';
575    }
576    function _getStaffStatusLabelForCheckin(ev, endsIn) {
577    	if (endsIn > 0 && endsIn < 60) {
578			return 'Service <i>ends in</i> ' + endsIn + ' <i>min</i>';
579		} else if (endsIn <= -240) {
580			ev.labelDescription = 'Checked-In Ticket Scheduled to End at ' + new Date(ev.end).toGloTime() + ' - ' + UTIL.timeLength(Math.abs(endsIn)) + ' ago';
581			return 'VERY OLD Check-In';
582		} else if (endsIn <= -60) {
583			ev.labelDescription = 'Checked-In Ticket Scheduled to End at ' + new Date(ev.end).toGloTime() + ' - ' + UTIL.timeLength(Math.abs(endsIn)) + ' ago';
584			return 'OLD Check-In';
585		} else if (endsIn <= 0) {
586			ev.labelDescription = 'Checked-In Ticket Scheduled to End at ' + new Date(ev.end).toGloTime() + ' - ' + UTIL.timeLength(Math.abs(endsIn)) + ' ago';
587			return 'Service Ends Soon';
588		} else {
589			return 'BUSY';
590		}
591    }
592    function _getStaffStatusLabel(ev, apptStatus) {
593    	var startsIn = UTIL.coalesceInt( (new Date(ev.start) - new Date()) / (1000 * 60), 0);
594    	var endsIn = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0);
595    	
596    	if (apptStatus == 21) {
597    		return _getStaffStatusLabelForCheckin(ev, endsIn);
598    	} else if (apptStatus == 5) {
599    		if (startsIn > 0) {
600    			return 'APPT <i>in</i> ' + startsIn + ' <i>min</i>';
601    		} else if (startsIn > -5) {
602    			return 'APPT NOW';
603    		} else {
604    			return 'APPT ' + Math.abs(startsIn) + ' <i>min late</i>';
605    		}
606    	} else if (apptStatus == 2) {
607    		var signinWait = UTIL.coalesceInt( (new Date() - new Date(ev.signin_dt)) / (1000 * 60), 0);
608    		return 'SIGN-IN ' + signinWait + ' <i>min ago</i>';
609    	} else if (apptStatus == 39) {
610    		if (endsIn < 60) {
611    			return 'BREAK <i>ends in</i> ' + endsIn + ' <i>min</i>';
612    		} else {
613    			return 'ON BREAK';
614    		}
615    	} else if (apptStatus == 41) {
616    		return 'BREAK <i>starts in</i> ' + startsIn + ' <i>min</i>';
617    	} else if (apptStatus == 42 && startsIn < 60) {
618    		return 'APPT <i>starts in</i> ' + startsIn + ' <i>min</i>';
619    	} else if (apptStatus == 29) {
620    		return 'CLIENT ' + Math.abs(startsIn) + ' <i>min</i> LATE';
621    	} else {
622    		return 'AVAILABLE';
623    	}
624    }
625    function _getStaffStatus(ev, apptStatus, priority) {
626    	var label = _getStaffStatusLabel(ev, apptStatus);
627    	var description = '';
628    	
629    	return { "label": label, "description": description, "appt_status_cd": apptStatus, "priority": priority, "event": ev, "otherServices": [] };
630    }
631    function _setStaffStatus(ojStaff, ev, apptStatus, priority) {
632    	var objStatus = _getStaffStatus(ev, apptStatus, priority);
633    	
634    	if (ojStaff.status && ojStaff.status.priority) {
635    		if (ojStaff.status.priority > priority) {
636    			_changeStaffStatus(ojStaff, objStatus);
637    		} else if (ojStaff.status.priority = priority) {
638    			if (objStatus.apptStatus == 21) {								//= use current.
639    				if (new Date(objStatus.event.start) < new Date() && new Date(objStatus.event.end) > new Date()) {
640    					_changeStaffStatus(ojStaff, objStatus);
641    				} else if (new Date(objStatus.event.start) > new Date() && objStatus.event.staff_id == ojStaff.status.event.staff_id) {
642    					_changeStaffStatus(ojStaff, objStatus);
643    				} else {
644    					ojStaff.status.other.push(objStatus);
645    				}
646    			} else if (objStatus.apptStatus == 39) {						//= use latest.
647    				if (new Date(objStatus.event.end) > new Date(ojStaff.status.event.end)) {
648    					_changeStaffStatus(ojStaff, objStatus);
649    				} else {
650    					ojStaff.status.other.push(objStatus);
651    				}
652    			} else {														//= use first.
653    				if (new Date(objStatus.event.start) < new Date(ojStaff.status.event.start)) {
654    					_changeStaffStatus(ojStaff, objStatus);
655    				} else {
656    					ojStaff.status.other.push(objStatus);
657    				}
658    			}
659    		} else {
660    			ojStaff.status.other.push(objStatus);
661    		}
662    	} else {
663    		objStatus.other = [];
664    		ojStaff.status = objStatus;
665    	}
666    }
667    function _changeStaffStatus(ojStaff, objStatus) {
668    	objStatus.other = ojStaff.status.other;
669		objStatus.other.push({ "label": ojStaff.status.label, "description": ojStaff.status.description, "appt_status_cd": ojStaff.status.apptStatus, "priority": ojStaff.status.priority });
670		
671		ojStaff.status = objStatus;
672    }
673    
674    function _isInCalendarStaffFilter(staffId) {					//= if on calendar: check staff in filter or staff who do client services (with accessType < 4)
675    	if (GLO.Calendar === undefined) {
676    		return true;
677    	}
678    	
679    	var arrStaff = GLO.staffResources;
680    	
681    	if (GLO.staffResourcesAll && GLO.staffResourcesAll.length) {
682    		arrStaff = GLO.staffResourcesAll;
683    	}
684    	
685    	for (var i=0; i < arrStaff.length; i++) {
686    		if (arrStaff[i].id == staffId) {
687    			return true;
688    		}
689    	}
690    	
691    	return false
692    }
693    
694    function _isWorkingOnCurrentDay2(dayDate, ojStaff, calEvents) {
695    	var offHourSGID = UserPortal.getOffTimeServiceGroupId();
696    	var internalSGID = UserPortal.getInternalServiceGroupId();
697    	var day = new Date(dayDate.toGloDate());
698    	var faId = UserPortal.getFirstAvailableStaffId();
699    	
700    	ojStaff.now_count_sr = ojStaff.service_count_sr = ojStaff.upcoming_count_sr = ojStaff.past_count_sr = ojStaff.checkin_count_sr = ojStaff.checkout_count_sr = ojStaff.cancel_count_sr = 0;
701    	ojStaff.signin_count_sr = ojStaff.late_count_sr = 0;
702    	
703    	if (calEvents) {
704	    	for (var i=0; i < calEvents.length; i++) {
705	    		var ev = calEvents[i];
706	    		var evStaffId = UTIL.coalesceInt(ev.staff_id, faId);
707	    		
708	    		if (evStaffId == ojStaff.id) {
709	    			if (ev.service_group_id == offHourSGID) {
710	    				if (ojStaff.end_sr > 0) {					//= day NOT already blocked off.
711		    				var eventStart = new Date(ev.start), eventEnd = new Date(ev.end);
712		    				var istart = UTIL.timeToInt(eventStart.toGloTime()), iend = UTIL.timeToInt(eventEnd.toGloTime());
713		    				var isEventStartsOnPrevDay = (new Date(eventStart.toGloDate()) < day);
714		    				var isEventEndsOnLaterDay = (new Date(eventEnd.toGloDate()) > day);
715		    				
716		    				if (isEventStartsOnPrevDay || istart <= ojStaff.start_sr) {		//= personal time event: starts on previous day OR starts before/on day's start
717		    					ojStaff.start_sr = iend;
718		    					ojStaff.start_tm = eventEnd.toGloTime();
719		    				}
720		    				
721		    				if (isEventEndsOnLaterDay || iend >= ojStaff.end_sr) {
722	    						ojStaff.end_sr = istart;
723	    						ojStaff.end_tm = eventStart.toGloTime();
724	    					}
725		    				
726		    				if ((isEventStartsOnPrevDay && isEventEndsOnLaterDay) || ojStaff.end_sr - ojStaff.start_sr < 15) {
727		    					ojStaff.start_sr = ojStaff.end_sr = 0;
728		    					ojStaff.start_tm = ojStaff.end_tm = null;
729		    				}
730		    				
731		    				if (istart > ojStaff.start_sr && ojStaff.end_sr > iend && !isEventStartsOnPrevDay && !isEventEndsOnLaterDay) {		//= is mid day break
732		    					ojStaff.breaks.push({ "start_tm": eventStart.toGloTime(), "end_tm": eventEnd.toGloTime(), "service_vc": ev.service_name_vc, "start_sr": istart, "end_sr": iend });
733		    					
734		    					if (eventEnd > new Date()) {
735			    					if (new Date() > eventStart) {
736			    						_setStaffStatus(ojStaff, ev, 39, 10);
737			    					} else if (new Date().addMinutes(30) > eventStart) {
738			    						_setStaffStatus(ojStaff, ev, 41, 11);
739		    						}
740		    					}
741		    				}
742	    				}
743	    			} else if (ev.service_group_id == internalSGID) {
744	    				if (UTIL.isDate(ev.checkin_dt) && (!UTIL.isDate(ojStaff.clockin_dt) || new Date(ev.checkin_dt) > ojStaff.clockin_dt)	//= get day's last clock-in
745	    						&& UTIL.isToday(ev.checkin_dt)) {			//= verify checkin is not from previous day (probably because staff forgot to clock-out)
746	    					ojStaff.clockin_dt = new Date(ev.checkin_dt);
747	    					
748	    					if (ojStaff.clockin_dt > ojStaff.clockout_dt) {
749	    						ojStaff.clockInAndOut.push({ "clockin_dt": new Date(ojStaff.clockin_dt), "clockout_dt": new Date(ojStaff.clockout_dt) });
750	    						ojStaff.clockout_dt = null;
751	    					}
752	    				}
753	    				
754	    				if (UTIL.isDate(ev.checkout_dt) && (!UTIL.isDate(ojStaff.clockout_dt) || new Date(ev.checkout_dt) > ojStaff.clockout_dt)		//= get day's last clock-out
755	    						&& UTIL.isToday(ev.checkin_dt)) {			//= verify checkin is not from previous day (probably because staff forgot to clock-out)
756	    					ojStaff.clockout_dt = new Date(ev.checkout_dt);
757	    				}
758	    			} else {
759	    				++ojStaff.service_count_sr;
760	    				var dtStart = new Date(ev.start);
761	    				
762	    				if (ojStaff.smids.has(ev.schedule_multi_id)) {
763	    					_updateStaffStatusWithAnotherEvent(ojStaff, ev);
764	    					
765	    					if (ev.appt_status_cd == 21 && ojStaff.status && ojStaff.status.appt_status_cd == 21) {
766		    					_updateStaffStatusForCheckin(ojStaff, ev);
767	    					}
768	    				} else {
769		    				ojStaff.smids.push(ev.schedule_multi_id);
770		    				
771		    				if (ev.appt_status_cd == 22) {																				//CHECK-OUT: UTIL.isDate(ev.checkout_dt) || ev.appt_status_cd == 120
772		    					++ojStaff.checkout_count_sr;
773		    				} else if (ev.appt_status_cd == 21 || ev.appt_status_cd == 25) {											//CHECK-IN, READY-To-PAY: UTIL.isDate(ev.checkin_dt)
774		    					++ojStaff.checkin_count_sr;
775		    					
776		    					if (ev.appt_status_cd == 21) {
777		    						var priority = 1, endsIn = UTIL.coalesceInt( (new Date(ev.end) - new Date()) / (1000 * 60), 0);
778		    						
779		    						if (endsIn <= -60) {
780		    							priority = 21;
781		    						}
782		    						
783		    						_setStaffStatus(ojStaff, ev, 21, priority);
784		    					}
785		    				} else if (ev.appt_status_cd == 13 || ev.appt_status_cd == 14) {											//NO-SHOW or LATE-CANCEL
786		    					++ojStaff.cancel_count_sr;
787		    				} else if (UTIL.isDate(ev.signin_dt) && new Date(ev.signin_dt).toGloDate() == new Date().toGloDate()) {		//SIGN-IN: ev.appt_status_cd == 2
788		    					++ojStaff.signin_count_sr;
789		    					_setStaffStatus(ojStaff, ev, 2, 2);
790		    				
791		    				} else if (dtStart > new Date().addMinutes(-15) && dtStart < new Date().addMinutes(15)) {					//NOW: ev.appt_status_cd == 5
792		    					++ojStaff.now_count_sr;
793		    					_setStaffStatus(ojStaff, ev, 5, 5);
794		    				} else if (new Date() > dtStart && dtStart > new Date().addMinutes(-90)) {									//LATE: ev.appt_status_cd == 29
795		    					++ojStaff.late_count_sr;
796		    					
797		    					if (dtStart > new Date().addMinutes(-30)) {
798		    						_setStaffStatus(ojStaff, ev, 29, 29);
799		    					}
800		    				} else if (dtStart > new Date()) {																			//UPCOMING: ev.appt_status_cd >= 40 && ev.appt_status_cd <= 49
801		    					++ojStaff.upcoming_count_sr;
802		    					_setStaffStatus(ojStaff, ev, 42, 42);
803		    				} else {																									//PAST: ev.appt_status_cd >= 90 && ev.appt_status_cd <= 99
804		    					++ojStaff.past_count_sr;
805		    				}
806	    				}
807	    			}
808	    		}
809	    	}
810    	}
811    	
812    	if (!_isInCalendarStaffFilter(ojStaff.id)) {
813    		return false;
814    	} else if (ojStaff.start_sr + 15 > ojStaff.end_sr) {
815    		return false;
816    	} else {
817    		return true;
818    	}
819    }
820    function _isWorkingOnCurrentDay(sid, dayDate, iStart, iEnd) {				//= checks to see if staff has marked day off with personal time event(s)
821    	var isFoundStaff = false, calEvents = GLO.Calendar.cal.fullCalendar('clientEvents');
822    	
823    	for (var i=0; i < calEvents.length; i++) {
824    		var calEvent = calEvents[i];
825    		
826    		if (calEvent.staff_id == sid) {
827    			isFoundStaff = true;
828    			
829    			if (calEvent.className.has('cal-monthDayPersonal')) {
830    				var day = new Date(dayDate.toGloDate());
831    				
832    				if (new Date(calEvent.start.toGloDate()) < day) {		//= personal time event starts on previous day.
833    					var begin = 0;
834    				} else {
835    					var begin = UTIL.timeToInt(calEvent.start.toGloTime());
836    				}
837    				
838    				if (new Date(calEvent.end.toGloDate()) > day) {		//= personal time event ends on day afterwards.
839    					var end = 60 * 24;
840    				} else {
841    					var end = UTIL.timeToInt(calEvent.end.toGloTime());
842    				}
843    				
844    				if (begin <= iStart && end >= iEnd) {
845    					iStart = end;
846    				}
847    			}
848    		} else if (isFoundStaff) {
849    			break;
850    		}
851    	}
852    	
853    	if (iStart + 15 > iEnd) {
854    		return false;
855    	} else {
856    		return true;
857    	}
858    }
859    
860    function _isCurrentDayOnCalendar(dt) {
861    	if (GLO.Calendar === undefined) { return false; }
862    	
863    	var dtCalendar = new Date(GLO.Calendar.cal.fullCalendar('getView').start).toGloDate();
864    	var dt = new Date(dt).toGloDate();
865    	
866    	if (dtCalendar === dt) {
867    		return true;
868    	} else {
869    		return false;
870    	}
871    }
872    
873    _constructor.reloadStaffWorking = function(dt) {
874    	if (UTIL.isDate(dt)) {
875    		dt = new Date(dt);
876    	} else {
877    		dt = new Date();
878    	}
879    	
880    	var isCurrDay = _isCurrentDayOnCalendar(dt);
881    	var arrStaff = _staffWorkingOn(dt, isCurrDay);
882    	
883    	if (arrStaff.length === 0) {
884    		var msg = '<div id="pop-warn-no-staff-working">No Staff Work are working on <b>' + dt.getWeekDayString() + ' ' + dt.toSADate(true) + '</b></div>';
885    		GLO.Popup.Warning.open(msg, 'No Staff Working');
886    		_setFilterToUrl();
887    		return;
888    	}
889    	
890    	var url = _getStaffWorkingOnUrl(arrStaff, dt);
891    	
892    	GLO.Popup.close($('#pop-filter-staff-working-today').closest('.glopop'));
893    	
894    	if (_mustReloadPage(arrStaff, dt, url)) { return; }
895    	
896    	_setStaffWorking(arrStaff);
897    	_constructor.reloadStaffCalendar(dt, url, true);
898    }
899    
900    _constructor.reloadStaffCalendar = function(dt, url, isWorkingOnly) {
901    	var dtLabel = dt.getWeekDayString(true) + ' ' + dt.toSADate(true);
902    	
903    	_changeUrl(url, dtLabel);
904    	_reorderCalendar_WorkoutOnDay(dtLabel, isWorkingOnly);
905    	_updateStaffFilter_DiffDay(dt, dtLabel, isWorkingOnly);
906    	
907    	if (GLO.Info.isMobile()) {
908			setTimeout(function() {
909				GLO.Calendar.cal.fullCalendar('resize_sa');
910			}, 280);
911		}
912    }
913    
914    function _updateStaffFilter_DiffDay(dt, dtLabel, isWorkingOnly) {
915    	var sfiltergroup = GLO.Uri.query('sfiltergroup');
916    	if (sfiltergroup !== 'today' && sfiltergroup !== 'diffday' && sfiltergroup !== 'workingonly') { return; }
917    	
918    	var jfilter = $('#staff-filter');
919    	var jtoday = jfilter.find('#staff-filter-today');
920    	var jdiffday = jfilter.find('#staff-filter-diffday');
921    	
922    	if (!isWorkingOnly) {
923    		jtoday.prop('selected', true);
924    		jdiffday.remove();
925    	} else if (GLO.Calendar.isToday()) {
926    		jtoday.prop('selected', true);
927    		
928    		if (jdiffday.length > 0) {
929    			jdiffday.text('Working Different Day');
930    		} else {
931    			jtoday.after('<option value="diffday" id="staff-filter-diffday">Working Different Day</option>');
932    		}
933    	} else {
934    		if (jdiffday.length > 0) {
935    			jdiffday.text('Working ' + dtLabel).attr('date', dt.toGloDate()).prop('selected', true);
936    		} else {
937    			jtoday.after('<option value="diffday" id="staff-filter-diffday" date="' + dt.toGloDate() + '" selected="selected">Working ' + dtLabel + '</option>');
938    		}
939    	}
940    }
941    
942    _constructor.loadStaffWorkingOnly = function() {
943    	if (GLO.Calendar !== undefined) {
944    		var dtDay = GLO.Calendar.cal.fullCalendar('getView').visStart;
945    	} else {
946    		var dtDay = new Date();
947    	}
948    	
949    	var url = _getStaffWorkingOnlyUrl(dtDay);
950    	
951    	if (String(UTIL.coalesce(GLO.Uri.query('sfilter'), 'all')).toLowerCase() != 'all') {
952    		var msg = 'Re-loading Calendar to include all staff working on ' + dtDay.toGloDateString(true, true);
953	    	GLO.Popup.Processing.open(msg, 'Re-loading Calendar');
954	    	
955	    	setTimeout(function() {
956	    		document.location = url;
957	    	}, 100);
958    	} else {
959	    	_changeUrl(url, 'Only Staff Working');
960	    	GLO.Calendar.refreshEvents(true, true);
961    	}
962    }
963    
964    function _changeUrl(url, label, forceUrl) {
965    	try {
966            window.history.pushState('', label, url);
967        } catch (e) {
968            if (forceUrl) {
969            	document.location = url;
970            }
971        }
972        
973        //GLO.Calendar.displayHomeButton();
974    }
975    
976    function _reorderCalendar_WorkoutOnDay(dtLabel, isWorkingOnly) {				//= similar to: _reorderCalendar
977    	if (isWorkingOnly) {
978    		var msg = 'Re-loading Calendar for staff working on ' + dtLabel + '...';
979    	} else {
980    		var msg = 'Updating Calendar...';
981    	}
982    	
983    	var ojProcessing = GLO.Popup.Processing.open(msg, 'Re-loading Calendar');
984		GLO.Schedule.Calendar.reloadCalendar(null, ojProcessing);
985    }
986    
987    function _setStaffWorking(arrStaff) {
988    	var arrResource = GLO.staffResourcesAll.slice();
989	    
990    	for (var a = arrResource.length - 1; a >= 0; a--) {
991    		var found = false;
992    		
993    		for (var b=0; b < arrStaff.length; b++) {
994    			if (arrResource[a].id == arrStaff[b].id) {
995    				found = true;
996    				break;
997    			}
998    		}
999    		
1000    		if (!found) {
1001    			arrResource.splice(a, 1);
1002    		}
1003    	}
1004    	
1005    	GLO.staffResources = arrResource;
1006    }
1007    
1008    _constructor.hasStaffInList = function(arrStaff, arrResourceList) {
1009    	for (var a=0; a < arrStaff.length; a++) {
1010    		var hasStaff = false, sid = arrStaff[a].id;
1011    		
1012	    	for (var r=0; r < arrResourceList.length; r++) {
1013	    		if (sid == arrResourceList[r].id) {
1014	    			hasStaff = true;
1015	    			break;
1016	    		}
1017	    	}
1018	    	
1019	    	if (!hasStaff) {
1020	    		return false;
1021	    	}
1022	    }
1023	    
1024	    return true;
1025    }
1026    function _mustReloadPage(arrStaff, dt, url, isCheckOnly) {
1027    	if (GLO.isFrontDeskCalendar) {
1028	    	//var sfilter = String(UTIL.coalesce(GLO.Uri.query('sfilter'), 'all')).toLowerCase();
1029	    	
1030	    	if (isCheckOnly && arrStaff.length === 1) {			//= must redirect to individual calendar.
1031	    		return true;
1032	    	} else if (GLO.Staff.Filter.hasStaffInList(arrStaff, GLO.staffResourcesAll)) {
1033    			return false;
1034    		} else if (isCheckOnly) {
1035    			return true;
1036    		}
1037	    }
1038	    
1039	    if (!isCheckOnly && url !== document.location.href) {
1040		    var msg = 'Re-loading Calendar for staff working on ' + dt.getWeekDayString() + ' ' + dt.toSADate(true);
1041	    	GLO.Popup.Processing.open(msg, 'Re-loading Calendar');
1042	    	
1043	    	setTimeout(function() {
1044	    		document.location = url;
1045	    	}, 100);
1046    	}
1047    	
1048    	return true;
1049    }
1050    
1051    function _staffArrayToString(arrStaff) {
1052    	var str = '';
1053    	
1054    	for (var a=0; a < arrStaff.length; a++) {
1055	    	if (a > 0) { str += ','; }
1056	    	str += arrStaff[a].id;
1057    	}
1058    	
1059    	return str;
1060    }
1061    
1062    function _getStaffWorkingOnlyUrl(dtDay) {
1063    	var url = GLO.Link.WebsiteDomain + 'provider/calendar?sfilter=all&sfiltergroup=workingonly';
1064    	var hash = '#vw=resourceDay&dt=';
1065    	
1066    	if (UTIL.isToday(dtDay)) {
1067    		hash += 'today';
1068    	} else {
1069    		hash += dtDay.toGloDate();
1070    	}
1071    	
1072    	return url + hash;
1073    }
1074    
1075    function _getStaffWorkingOnUrl(arrStaff, dt) {
1076    	var url = GLO.Link.WebsiteDomain + 'provider/calendar?sfilter=' + _staffArrayToString(arrStaff) + '&sfiltergroup=';
1077    	var mid = '#vw=resourceDay&dt=';
1078    	
1079    	if (UTIL.isSameDay(dt, new Date(GLO.Data.provider.now_dt))) {
1080    		url += 'today' + mid + 'today';
1081    	} else {
1082    		url += 'diffday' + mid + dt.toGloDate();
1083    	}
1084    	
1085    	return url;
1086    }
1087    
1088    _constructor.loadOnlyStaffWorking = function(dtDay) {
1089    	if (!UTIL.isDate(dtDay)) {
1090    		var dtDay = GLO.Calendar.cal.fullCalendar('getView').start;
1091    	}
1092    	
1093    	/*_staffWorkingOn(dtDay, isCurrDay)
1094		_setDaysOff_resourceDay(dtSt, dtEnd)
1095		
1096		lookup days off based on 
1097			GLO.Data.holidays + GLO.closedDates -> biz level
1098			GLO.resourceHours + GLO.AdjustedHours -> staff level
1099		*/
1100    }
1101    
1102    function _changeUrlFromHeader(queryString) {
1103    	$('#top-staffName #staff-filter #only-staff-working').text('Only Staff Working');
1104    	
1105    	document.location = document.location.origin + document.location.pathname + '?' + queryString;
1106    	//GLO.Calendar.displayHomeButton();
1107    }
1108    
1109    _constructor.changeHeader = function(element) {
1110        var jOption = $(element).find(':selected');
1111        var id = jOption.attr('value');
1112        
1113        if (jOption.attr('value') === 'inventory') {
1114            document.location = GLO.Link.Page.Provider.Home + 'Inventory/';
1115        } else if (id === 'workingonly') {
1116        	GLO.Staff.Filter.loadStaffWorkingOnly();
1117        
1118        } else if (id === 'today') {					//depreciated in favor of workingonly
1119        	_loadWorkingToday(false);
1120        } else if (id === 'diffday') {					//depreciated in favor of workingonly
1121        	_loadWorkingToday(true);
1122        
1123        } else if (jOption.parent().attr('id') == 'location-filter-sg') {
1124        	_changeLocation(jOption);
1125        } else if (jOption.attr('value') == '' || jOption.attr('value') == '-99') {
1126            _constructor.open();
1127        } else if (jOption.val() === 'house') {
1128        	if (_constructor.isReportPortal) {
1129        		GLO.Report.changeStaffFilter(jOption);
1130        	} else {
1131	        	var sfilter = _constructor.getHouseStaff();
1132	        	_changeUrlFromHeader('sfiltergroup=4&sfilter=' + sfilter);		//document.location = document.location.origin + document.location.pathname + '?sfiltergroup=4&sfilter=' + sfilter;
1133        	}
1134        } else if (jOption.val() === 'not-house') {
1135        	if (_constructor.isReportPortal) {
1136        		GLO.Report.changeStaffFilter(jOption);
1137        	} else {
1138	        	var sfilter = _constructor.getNotHouseStaff();
1139	        	_changeUrlFromHeader('sfiltergroup=5&sfilter=' + sfilter);		//document.location = document.location.origin + document.location.pathname + '?sfiltergroup=5&sfilter=' + sfilter;
1140        	}
1141        } else if ($('#report-main').length === 1 || $('.report-search-header:visible').length === 1) {
1142        	GLO.Report.changeStaffFilter(jOption);						//$('.report-search-header:visible').find('.btnSearch a').click();
1143        } else if (GLO.MyAppts.isActivityView) {
1144        	_changeFilterOnActivityView(jOption);
1145        } else if (jOption.parent().attr('id') == 'staff-filter-sg') {
1146            var dt = UTIL.cleanString(GLO.Uri.hash('dt'));
1147            document.location = GLO.Link.Page.Provider.SetFilter + '?type=sg&id=' + id + '&dt=' + dt;
1148        } else if (jOption.parent().attr('id') == 'staff-filter-staff-group') {
1149            //document.location = GLO.Info.http + document.location.host + '/calendar?dt=' + UTIL.cleanString(GLO.Uri.hash('dt')) + '&sfilter=' + jOption.attr('staff_ids');
1150            _changeUrlFromHeader('dt=' + UTIL.cleanString(GLO.Uri.hash('dt')) + '&sfilter=' + jOption.attr('staff_ids'));
1151        } else if (_constructor.isReportFilterEasyQuery) {
1152        	document.location = document.location.origin + document.location.pathname + '?sfilter=' + element.value;
1153        } else if (jOption.attr('value') == 'all') {
1154            _constructor.gotoSchedule(id, 'all');
1155        } else {            //if (jOption.parent().attr('id') == 'staff-filter-s')
1156            _constructor.gotoSchedule(id);
1157        }
1158    }
1159    
1160    function _changeFilterOnActivityView(jOption) {
1161    	GLO.Report.changeStaffFilter(jOption);
1162    	
1163    	if ($('#myAppointments-wait').length > 0) {
1164    		GLO.WaitList.refreshActivityView();
1165    	}
1166    	
1167    	$('#staffPortal-main').find('.appt-list-search:visible').find('.btnSearch > a:visible').click();
1168    }
1169    
1170    function _changeLocation(joption) {
1171    	var pid = joption.attr('value');
1172    	var pnm = joption.text();
1173    	var pc = joption.css('background-color').replace('.2', '.6');
1174    	
1175    	_constructor.switchLocation(pid, pnm, pc);
1176    }
1177    
1178    _constructor.changeLocation = function(select, event) {
1179    	var joption = $(select).find(':selected');
1180        var pid = joption.attr('value');
1181        var pnm = joption.text();
1182        var pc = 'rgba(' + joption.attr('provider_color_vc') + ',.6)';
1183        
1184        _constructor.switchLocation(pid, pnm, pc);
1185    }
1186    
1187    _constructor.switchLocation = function(providerId, providerName, providerColor, urlGoTo) {
1188    	urlGoTo = UTIL.coalesceString(urlGoTo, document.location.pathname + document.location.search + document.location.hash);
1189    	var url = GLO.Link.WebsiteDomain + 'provider/SwitchProvider?newpid=' + providerId + '&url=' + encodeURIComponent(urlGoTo);
1190    	
1191    	var msg = '<div> <h1 class="friendly-msg4">Loading New Location</h1> <div class="friendly-msg4">Changing Location to ' + providerName + '...</div> </div>';
1192    	var ojProcessing = new GLO.Popup.Processing(msg);
1193    	var jprocessing = ojProcessing.getPopup();
1194    	jprocessing.css({ "background-color": providerColor, "color": "White" });
1195    	
1196    	setTimeout(function() {
1197    		document.location = url;
1198    	}, 200);
1199    }
1200    
1201    _constructor.switchLocationTo = function(providerId, warningMessage) {
1202    	var jdd = $('#staff-filter').find('#location-filter-sg');
1203    	
1204    	if (jdd.length === 0) { jdd = $('#location-filter'); }
1205    	
1206    	var jopt = jdd.find('option[value="' + providerId + '"]');
1207    	
1208    	if (jopt.length === 0) {
1209    		htm = '<div class="friendly-responsive">' + warningMessage + '</div>';
1210    		new GLO.Popup.Warning(htm);
1211    	} else {
1212    		_changeLocation(jopt);
1213    	}
1214    }
1215    
1216    _constructor.getHouseStaff = function() {
1217    	var dt = UTIL.cleanString(GLO.Uri.hash('dt'));
1218        var jstaff = UserPortal.getStaffDropDown().find('option');
1219        var sfilter = '';
1220        
1221        for (var i=0; i < jstaff.length; i++) {
1222        	var js = jstaff.eq(i);
1223        	
1224        	if (UTIL.coalesceInt(js.attr('merchant_type_cd'), 99) < 20) {
1225        		if (sfilter !== '') { sfilter += ','; }
1226        		sfilter += js.attr('value');
1227        	}
1228        }
1229        
1230        return sfilter + ',-9';
1231    }
1232    _constructor.getNotHouseStaff = function() {
1233    	var dt = UTIL.cleanString(GLO.Uri.hash('dt'));
1234        var jstaff = UserPortal.getStaffDropDown().find('option');
1235        var sfilter = '';
1236        
1237        for (var i=0; i < jstaff.length; i++) {
1238        	var js = jstaff.eq(i), sid = js.attr('value');
1239        	
1240        	if (!UTIL.isEmpty(sid) && UTIL.coalesceInt(js.attr('merchant_type_cd'), 99) > 19) {
1241        		if (sfilter !== '') { sfilter += ','; }
1242        		sfilter += sid;
1243        	}
1244        }
1245        
1246        return sfilter + ',-5';
1247    }
1248    
1249    _constructor.staffHasClientService = function(js) {
1250    
1251    }
1252    
1253    function _revertBackToAllStaff(staffIds, groupType, dt, uri, qs) {
1254    	if (staffIds === 'all' && groupType === 'all' && GLO.staffResourcesAll && GLO.staffResourcesAll.length) {
1255        	GLO.staffResources = GLO.staffResourcesAll;
1256        	//GLO.staffResourcesAll = undefined;
1257        	
1258        	_constructor.reloadStaffCalendar(new Date(dt), uri + 'calendar' + qs);
1259        	return true;
1260        }
1261        
1262        return false;
1263    }
1264    
1265    function _getGoToScheduleUri(uri, staffIds, groupType) {
1266    	if ($('#staffPortal-main:visible').length === 1) {
1267            uri += 'apptportal';
1268        } else if ($('#reminder-day-view:visible').length === 1) {
1269            uri += 'reminders';
1270        } else {            //if (GLO.Calendar !== undefined) {         //if ($('#calendar .fc-view:visible').length === 1 || $('.fc-view-resourceDay:visible').length === 1) {
1271            if (GLO.Info.providerPackage === 1) {
1272                uri += 'calendar';
1273            } else if (groupType === 'all' || staffIds === '' || String(staffIds).indexOf(",") != -1) {
1274                uri += 'calendar';
1275            } else {
1276                uri += 'calendarOne';
1277            }
1278        }
1279        
1280        return uri;
1281    }
1282    
1283    function _getStaffIdArray(sids) {
1284    	var arrStaff = [], arrTemp = String(sids).split(',');
1285    	
1286    	for (var i=0; i < arrTemp.length; i++) {
1287    		arrStaff.push({ "id": arrTemp[i] });
1288    	}
1289    	
1290    	return arrStaff;
1291    }
1292    
1293    function _getDateFromUriHashKey(hashKey) {
1294    	var dt = GLO.Uri.hash(hashKey).toLowerCase();
1295        
1296        if (dt === 'tomorrow') {
1297        	dt = new Date();
1298        	dt = new Date(dt.setDate(dt.getDate() + 1));
1299        } else if (!UTIL.isDate(dt)) {
1300        	dt = new Date();
1301        } else {
1302        	dt = new Date(UTIL.replaceAll(dt, '-', '/'));				//if do NOT replace '-' with '/', then this actually subtracts 1 day from date
1303        }
1304        
1305        return dt;
1306    }
1307    
1308    _constructor.gotoSchedule = function(staffIds, groupType, jbtn, isAllowInactive) {
1309        $('#top-staffName #staff-filter #only-staff-working').text('Only Staff Working');
1310        
1311        if (staffIds === undefined) {
1312        	staffIds = UTIL.cleanString($('#staff-filter').val());
1313        	
1314        	if (staffIds === '' && GLO.Info.isMobile()) {
1315        		staffIds = UTIL.cleanString($('#staff-filter').find('option:first').val());
1316        	}
1317        }
1318        
1319        var dt = _getDateFromUriHashKey('dt');
1320        var qs = '?sfilter=' + staffIds + '#dt=' + dt.toGloDate(true), uri = GLO.Link.Page.Provider.Home;
1321        var arrStaff = _getStaffIdArray(staffIds);
1322        
1323        if (_revertBackToAllStaff(staffIds, groupType, dt, uri, qs)) {
1324        	return;
1325        }
1326        
1327        var uri = _getGoToScheduleUri(uri, staffIds, groupType);
1328        var currURI = document.location.origin + document.location.pathname + document.location.search;
1329        var newURI = uri + qs.substring(0, qs.indexOf('#'));
1330        
1331        if (GLO.Calendar !== undefined) {
1332        	qs += '&vw=' + GLO.Uri.hash('vw');
1333        }
1334        
1335        if (!_mustReloadPage(arrStaff, dt, uri + qs, true)) {
1336    		_setStaffWorking(arrStaff);
1337			_constructor.reloadStaffCalendar(dt, uri + qs, true);
1338			
1339			$.modal.close();
1340			return;
1341    	}
1342        
1343        if (currURI == newURI) {
1344            GLO.Popup.Info.open('You did not change the current filter', 'Schedule Filter');
1345            GLO.Log.insert('You did not change the current filter');
1346        } else {
1347            if (jbtn) {
1348            	GLO.UI.Form.beginProcessing(jbtn);
1349            } else if (GLO.Info.isMobile(true)) {
1350            	GLO.UI.animate(2);
1351            }
1352            
1353            setTimeout(function() {
1354            	document.location = uri + qs;           //document.location = GLO.Link.Page.Provider.SetFilter + qs;
1355            }, 100);
1356        }
1357    }
1358    
1359    _constructor.open = function(message, fnOnLoadComplete) {
1360        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"});
1361        var uri = GLO.Link.Page.Provider.StaffFilter + '?type=custom&ispartial=1&dt=' + UTIL.getDateString();
1362        var pop = $('#pop-temp');
1363
1364        pop.html(throbber).load(uri, function() {
1365            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
1366            
1367            var modalHeight = 640, jmodal = $('#simplemodal-container');
1368            var staffCount = jmodal.find('#sFilter-list > tbody > tr').length;
1369            
1370            $('#simplemodal-container, .simplemodal-data, #simplemodal-container .shadow-content0').css({ "padding": "0" });
1371            jmodal.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
1372            
1373            if (innerWidth < 780) {
1374            	var popWidth = innerWidth * .9;
1375            	
1376            	if (popWidth < 320) { popWidth = 320; }
1377            } else {
1378            	var popWidth = 760;
1379            }
1380            
1381            if (GLO.Info.isMobile()) {
1382            	modalHeight = jmodal.find('#sfilter-container').outerHeight() - 60;
1383            } else if (innerHeight > 900 && staffCount > 10) {
1384            	modalHeight = 840;
1385            	
1386            	var jtbl = jmodal.find('#sFilter-list-container');
1387            	jtbl.height(jtbl.height() + 200);
1388            } else if (modalHeight < innerHeight) {
1389            	modalHeight += 48;			//need space for buttons at bottom of popup.
1390            }
1391            
1392            if (modalHeight > innerHeight) {
1393            	jmodal.find('#sfilter-instructions').remove();
1394            	jmodal.find('#sfilter-container .sFilter-buttons').css({ "bottom": "-2px" });
1395            	modalHeight = innerHeight - 20;
1396            	
1397            	var tblHeight = modalHeight - (jmodal.find('h2').height() + jmodal.find('#sfilter-staff-table thead').height() + jmodal.find('.sFilter-buttons').height());
1398            	jmodal.find('#sFilter-list-container').css({ "height": tblHeight + "px" });
1399            }
1400            
1401            jmodal.css({ "max-height": modalHeight + "px" });
1402            $.modal.update(modalHeight, popWidth);
1403            GLO.Staff.Filter.init(message);
1404            
1405            if (fnOnLoadComplete) { fnOnLoadComplete(jmodal, message); }
1406            _addResizeCalendarToFitScreen(jmodal);
1407        });
1408
1409        pop.modal();
1410        $.modal.update(300, 300);
1411        
1412        var jfilter = $('select#staff-filter');
1413        
1414        if (jfilter.find('option#staff-filter-change').length === 0) {
1415            jfilter.find('#staff-filter-custom-group').prepend('<option value="-99" id="staff-filter-change" title="' + SA.Resource.ClickToChangeFilter + '">' + SA.Resource.ChangeFilter + '</option>');
1416        }
1417        
1418        _initDisplayMessage(message);
1419    }
1420    
1421    function _addResizeCalendarToFitScreen(jmodal) {
1422    	var mode = _constructor.getFitScreenMode();
1423    	
1424    	if (mode === 0 || innerWidth < 800) { return; }
1425		
1426		if (mode === 1) {
1427			var btnText = 'Wide Calendar', btnTitle = 'Makes the staff columns on the calendar normal width';
1428		} else {
1429			var btnText = 'Fit All Staff', btnTitle = 'Shrinks the staff columns on the calendar so there is no need to scroll left/right';
1430		}
1431		
1432		var left = 8, h2 = jmodal.find('h2');
1433		
1434		if (h2.find('#select-language-icon-globe:visible').length > 0) { left = 50; }
1435		
1436		var btn = '<span id="btnFitCalendar" class="btnAdd" style="left: ' + left + 'px;" title="' + btnTitle + '"><a onclick="GLO.Staff.Filter.fitCalendarToScreen()">' + btnText + '</a></span>';
1437		h2.prepend(btn);
1438    }
1439    
1440    _constructor.displayFitScreenIcon = function() {
1441    	var mode = _constructor.getFitScreenMode();
1442    	
1443    	if (mode === 0 || innerWidth < 600) { return; }
1444		
1445		if (mode === 1) {
1446			var icon = '&#10565;';				//&#8621;
1447			var btnTitle = 'Wide Calendar: Revert the staff columns on the calendar to normal width';
1448		} else {
1449			var icon = '&#10566;';
1450			var btnTitle = 'Fit to Screen: Shrinks the staff columns on the calendar so there is no need to scroll left/right';
1451		}
1452		
1453		icon = '<b id="fit-screen-icon" onclick="GLO.Staff.Filter.fitCalendarToScreen()" title="' + btnTitle + '">' + icon + '</b>';
1454    	$('.fc-header-right').prepend(icon);
1455    }
1456    
1457    _constructor.getFitScreenMode = function() {
1458    	if (!GLO.isFrontDeskCalendar || !GLO.staffResources || GLO.staffResources.length === 0) { return 0; }
1459		if (GLO.Info.isIPad || GLO.Mobile.isTablet) { return 0; }
1460	
1461		var minWidth = GLO.staffResources.length * 100;
1462		var avgColWidth = parseInt((innerWidth - 43)/GLO.staffResources.length);
1463		var fitCookie = $.cookies.get('fit-calendar');
1464		var isFitCalendar = UTIL.parseBool(fitCookie);
1465		
1466		if (isFitCalendar) {			//= is in fit to screen mode
1467			return 1;
1468		} else if (UTIL.isEmpty(fitCookie) && UserPortal.Calendar.isWorkingOnly()) {
1469			return 1;
1470		} else if (UTIL.isEmpty(fitCookie) && minWidth > innerWidth && avgColWidth > 40) {			//= is default (staff columns on calendar have min width)
1471			return 1;
1472		} else if (minWidth > innerWidth && avgColWidth > 28) {			//= is default (staff columns on calendar have min width)
1473			return -1;
1474		} else {
1475			return 0;
1476		}
1477    }
1478    
1479    _constructor.fitCalendarToScreen = function() {
1480    	var isFitCalendar = UTIL.parseBool($.cookies.get('fit-calendar'));
1481    	
1482    	if (isFitCalendar) {
1483    		var msg = 'Resetting Calendar to Wide View...';
1484    		isFitCalendar = '0';
1485    	} else {
1486    		var msg = 'Setting Calendar to Fit Screen...';
1487    		isFitCalendar = '1';
1488    	}
1489    	
1490    	//var expireDate = new Date();
1491		//expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 1));
1492    	UTIL.setCookie('fit-calendar', isFitCalendar);							//$.cookies.set('fit-calendar', isFitCalendar, { "expiresAt": expireDate });
1493    	
1494    	GLO.Popup.Processing.open(msg, 'Reseting Calendar');
1495    	
1496    	setTimeout(function() {
1497    		location.reload();
1498    	}, 100);
1499    }
1500    
1501    _constructor.initAutoLoadForCalendar = function(jmodal, message) {
1502    	var btnClose = '<span class="btnClose btnOk"> <a class="ignore-animate" onclick="$.modal.close()">Close</a> </span>';
1503    	var modalHeight = jmodal.height();
1504    	
1505    	var jh2 = jmodal.find('h2').css({ "margin-bottom": 0, "background-color": "rgb(0, 160, 220)" });
1506    	var h2Height = jh2.height();
1507    	
1508    	var jinfo = jmodal.find('#sfilter-instructions').html(message);
1509    	var jh1 = jinfo.find('h1');
1510    	
1511    	jh2.text(jh1.text());
1512    	jh1.remove();
1513    	jmodal.find('#wiz5-SendText').replaceWith(btnClose);
1514    	
1515    	var msgHeight = jmodal.find('#staff-filter-message').height();
1516    	var j = jmodal.find('#sFilter-list-container');
1517    	
1518    	if (modalHeight + msgHeight < innerHeight) {
1519    		$.modal.update(modalHeight + msgHeight, null);	
1520    	} else {
1521    		j.height(j.height() - msgHeight);
1522    	}
1523    	
1524    	var trs = j.find('tbody').find('tr');
1525    	
1526    	for (var i=0; i < trs.length; i++) {
1527    		if (trs.eq(i).hasClass('has-appt')) {
1528    			trs.eq(i).find('.sfilter-column-checkbox .staffCheck').prop('checked', true);
1529    		}
1530    	}
1531    	
1532    	_sfilterInterval = setInterval(GLO.Staff.Filter.closeFilterOnRotateToLandscape);
1533    }
1534    
1535    _constructor.closeFilterOnRotateToLandscape = function() {
1536    	++_intervalCounter;
1537    	
1538    	if (GLO.Info.isLandscape()) {
1539    		$.modal.close();
1540    		clearInterval(_sfilterInterval);
1541    	} else if (_intervalCounter > 9) {
1542    		clearInterval(_sfilterInterval);
1543    	}
1544    }
1545    
1546    function _initDisplayMessage(message) {
1547    	if (message) {
1548        	var jmodal = $('#simplemodal-container');
1549        	jmodal.find('#imgThrobber').css({ "margin-top": "40px", "margin-bottom": "0" }).before(message);
1550        	jmodal.css({ "padding": 0 }).find('.simplemodal-data').css({ "padding": 0 });
1551        	
1552        	var w = parseInt(innerWidth * .9), h = 300;
1553        	
1554        	if (w < 550) {
1555        		h = 400;
1556        	}
1557        	
1558        	$.modal.update(h, w);
1559        }
1560    }
1561
1562     _constructor.filterStaff = function(isAllowInactive) {
1563        /* SUMMARY:
1564        1. filters staff portal to only these staff member(s)
1565        2. displays "Filter" tab, indicating that a filter is in effect - can click on filter to (view filter / update filter / remove filter)
1566        */
1567        
1568        var radioList = $('.staffCheck:checked');
1569        var radioCount = radioList.size();
1570        var staff_ids = '';
1571
1572        if (radioCount === 0) {
1573            GLO.Popup.Warning(SA.Resource.PleaseSelectBox);
1574            return;
1575        } else {
1576            radioList.each(function() {
1577                staff_ids += $(this).parent().parent().attr('id').substr(7) + ',';
1578            });
1579        }
1580
1581        if (GLO.Uri.url('inactive') == '1') {
1582            staff_ids = GLO.Uri.url('activestaff') + staff_ids;
1583        }
1584
1585        staff_ids = staff_ids.substr(0, staff_ids.length - 1);
1586
1587        if (_constructor.isReportPortal) {
1588            GLO.Report.setStaffFilter(staff_ids);
1589            $.modal.close();
1590
1591            var dd = $('#staff-filter').val('');
1592            
1593            if (dd.find('option#staff-filter-change').length === 0) {
1594                dd.find('#staff-filter-custom-group').prepend('<option value="-99" id="staff-filter-change" title="' + SA.Resource.ClickToChangeFilter + '">' + SA.Resource.ChangeFilter + '</option>');
1595            }
1596            
1597            setTimeout(function() {
1598            	var jsearch = $('.report-search-header:visible').find('.btnSearch > a');
1599            	
1600            	if (GLO.Report.portalName == 'payroll-days') {
1601            		$('#payroll-report-date-period .btnAdd.selected > a').click();				//GLO.Report.Payroll.search();
1602            		return;
1603            	} else if (jsearch.length === 0) {
1604            		jsearch = $('#bd-page .fa-refresh');			//= Incorrect Payment report
1605            	}
1606            	
1607            	jsearch.click();
1608            }, 100);
1609        } else if (GLO.MyAppts.isActivityView) {
1610        	GLO.Uri.query('sfilter', staff_ids);
1611        	$('#staffPortal-main').find('.appt-list-search:visible').find('.btnSearch > a:visible').click();
1612        } else {
1613            var jbtn = $('#wiz5-SeeAppointments');
1614            _constructor.gotoSchedule(staff_ids, null, jbtn, isAllowInactive);
1615        }
1616    }
1617
1618    _constructor.unDeleteStaff = function() {
1619        var radioList = $('.staffCheck:checked');
1620        var radioCount = radioList.size();
1621        var staffList = '';
1622
1623        if (radioCount === 0) {
1624            GLO.Popup.Warning(SA.Resource.PleaseSelectBox2);
1625            return;
1626        } else {
1627            radioList.each(function() {
1628                staffList += '<li style="margin-left: 16px; text-indent: 0; letter-spacing: 1px; line-height: 140%; font-size: large;">' + $(this).closest('tr').find('td').eq(1).find('a').text() + '</li>';
1629            });
1630            
1631            var msg = '<div id="msg-undo-delete-staff"><p>' + SA.Resource.ReActivateConfirm + '</p>';
1632            msg += '<ol>' + staffList + '</ol> </div>';
1633
1634            GLO.Popup.Confirm(msg, GLO.Staff.Filter.unDeleteStaffConfirmed);
1635        }
1636    }
1637
1638    _constructor.unDeleteStaffConfirmed = function(staffId) {
1639        var radioList = $('.staffCheck:checked');
1640        var radioCount = radioList.size();
1641        var staffIds = '';
1642        
1643        radioList.each(function() {
1644            staffIds += $(this).parent().parent().attr('id').substr(7) + ',';
1645        });
1646        
1647        var uri = GLO.Link.Object.Provider.Ajax + 'unDeleteStaff';
1648        var btnSave = $('.wiz5-UndoDelete').parent();
1649        
1650        GLO.UI.Form.beginProcessing(btnSave);
1651        
1652        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { staff_ids: staffIds } })
1653            .success(function(data, textStatus, jqXHR) {
1654                var msg = '<div> <h1 class="friendly-msg4">Staff Successfully Un-Deleted</h1> <div class="friendly-msg4">' + SA.Resource.StaffReActivateSuccess + '</div> </div>';
1655                new GLO.Popup.Info(msg, function() { location.reload(); });
1656            })
1657            .error(function(jqXHR, textStatus, errorThrown) {
1658                new GLO.Popup.Error('Unable to re-active these staff members at this time');
1659                GLO.UI.Form.resetProcessing();
1660            });
1661    }
1662
1663    _constructor.removeFilter = function() {
1664        if ($('#report-main').length === 1) {
1665            $('#staffFilter').remove();
1666            
1667            var sdd = $('#staff-filter');
1668            sdd.val(sdd.find('option:first').attr('value'));
1669            
1670            GLO.Report.changeStaffFilter();
1671        } else {
1672            var url = GLO.Link.Page.Provider.ClearFilter;
1673        
1674            var dt = GLO.Uri.url('dt');
1675            if (!UTIL.isEmpty(dt)) { url += '?dt=' + dt; }
1676        
1677            document.location = url;
1678        }
1679        
1680        $('#doc3').css({ "margin-top": "0" });
1681    }
1682
1683    _constructor.viewDeleted = function(btn) {
1684        if (GLO.Info.displayPaidPackageRequired()) { return; }
1685        
1686        var radioList = $('.staffCheck:checked');
1687        var staff_ids = '';
1688
1689        radioList.each(function() {
1690            staff_ids += $(this).parent().parent().attr('id').substr(7) + ',';
1691        });
1692        
1693        if (btn && btn.text) {
1694        	GLO.Uri.gotoUriWithSpinner('provider/staffFilter?inactive=1&activestaff=' + staff_ids, btn, event, true);
1695        } else {
1696        	document.location = '/provider/staffFilter?inactive=1&activestaff=' + staff_ids;
1697        }
1698    }
1699
1700    return _constructor;
1701})();
1702
1703
1704GLO.Schedule = (function() {
1705    function _conSchedule() { }
1706    
1707    _conSchedule.gotoMonthView = function(ev) {
1708        var calPage = _getCalendarPage();
1709        _gotoView(ev, 'provider/' + calPage, false, 'vw=month');
1710    }
1711
1712    _conSchedule.gotoWeekView = function(ev) {
1713        var calPage = _getCalendarPage();
1714        _gotoView(ev, 'provider/' + calPage, false, 'vw=agendaWeek');
1715    }
1716    
1717    _conSchedule.gotoDayView = function(ev) {
1718        var calPage = _getCalendarPage();
1719        _gotoView(ev, 'provider/' + calPage, false, 'vw=agendaDay');
1720    }
1721    
1722    _conSchedule.gotoListView = function(ev) {
1723        _gotoView(ev, 'provider/apptportal', true);
1724    }
1725
1726    _conSchedule.gotoReminderView = function(ev) {
1727        _gotoView(ev, 'provider/reminders', true);
1728    }
1729
1730    _conSchedule.gotoCalendarAdminView = function(ev) {
1731        _gotoView(ev, 'provider/calendar', true);
1732    }
1733
1734    function _getCalendarPage() {
1735        var sfilter = GLO.Uri.query('sfilter');
1736        var calPage = 'calendar';
1737
1738        if (GLO.Info.providerPackage !== 1) {
1739            if (parseInt(GLO.Info.providerPackage) > 200) {
1740                if (sfilter.indexOf(",") === -1 || sfilter.toLowerCase() === 'all') {
1741                    calPage = 'CalendarOne'
1742                }
1743            }
1744        }
1745
1746        if (!UTIL.isEmpty(sfilter)) { calPage += '?sfilter=' + sfilter; }
1747        return calPage;
1748    }
1749
1750    function _gotoView(ev, url, mustGetStaffFilter, hash) {
1751        url = GLO.Link.WebsiteDomain + url;
1752        if (url.indexOf("?") === -1) { url += '?'; } else { url += '&'; }
1753
1754        if (mustGetStaffFilter) { 
1755            var sfilter = GLO.Uri.query('sfilter');
1756            
1757            if (!UTIL.isEmpty(sfilter)) { url += 'sfilter=' + sfilter; }
1758        }
1759        
1760        var sg = GLO.Uri.url('sfiltergroup');
1761        if (!UTIL.isEmpty(sg)) { 
1762            if (url.indexOf("?") === -1) { url += '?'; } else { url += '&'; }
1763            url += 'sfiltergroup=' + sg; 
1764        }
1765        
1766        url += '#';
1767        if (!UTIL.isEmpty(hash)) { url += hash; }
1768
1769        var dt = GLO.Uri.url('dt');
1770        if (!UTIL.isEmpty(dt)) { url += '&dt=' + dt; }
1771
1772        if (ev && ev.ctrlKey) {
1773            window.open(url);
1774        } else {
1775            document.location = url;
1776        }
1777    }
1778
1779    _conSchedule.lookupStaffNormalHours = function(dt, resourceId, ignoreAdjust) {
1780        var tmStart, tmEnd, id = null, isAdjust = false, day = dt.getDay();
1781        
1782        if (resourceId && GLO.resourceHours) {
1783            var rNormalHrArr = _getResourceNormalHoursArray(resourceId);
1784
1785            if (rNormalHrArr) {
1786                tmStart = rNormalHrArr[day][0];
1787                tmEnd = rNormalHrArr[day][1];
1788            } else if (GLO.Calendar !== undefined) {                                    // = if is deleted staff there time isn't in the JS array.
1789                tmStart = GLO.Calendar.minTime;
1790                tmEnd = GLO.Calendar.maxTime;
1791            }
1792        } else {
1793            if (UTIL.isEmpty(resourceId)) { resourceId = UserPortal.getStaffFilterString(); }
1794
1795            tmStart = GLO.StaffWeekHours[day][0];
1796            tmEnd = GLO.StaffWeekHours[day][1];
1797        }
1798        
1799        if (!ignoreAdjust) {
1800	        var arr = UTIL.findObjectInArray(GLO.AdjustedHours, resourceId);
1801	        
1802	        if (arr) {
1803	            arr = arr["hrs"];
1804	            var sdt = (dt.getMonth() + 1) + '/' + dt.getDate() + '/' + dt.getFullYear();
1805	            
1806	            for (var i=0; i < arr.length; i++) {
1807	                if (sdt === arr[i][1]) {
1808	                    if (arr[i][0]) {
1809	                    	id = arr[i][0];
1810	                    }
1811	                    
1812	                    if (arr[i][2]) {
1813	                    	tmStart = arr[i][2];
1814	                    	isAdjust = true;
1815	                    }
1816	                    
1817	                    if (arr[i][3]) {
1818	                    	tmEnd = arr[i][3];
1819	                    	isAdjust = true;
1820	                    }
1821	                    
1822	                    break;
1823	                }
1824	            }
1825	        }
1826        }
1827        
1828        return [tmStart, tmEnd, id, isAdjust];
1829    }
1830    
1831    function _getResourceNormalHoursArray(resourceId) {
1832        var i = 0;
1833        var len = GLO.resourceHours.length;
1834        
1835        for (; i < len; i++) {
1836            if (resourceId == GLO.resourceHours[i].id) {
1837                return GLO.resourceHours[i].normalHours;
1838            }
1839        }
1840    }
1841
1842    _conSchedule.Calendar = (function() {          //functions shared by individual calendar + admin calendar.
1843        function _conCalendar() { }
1844        
1845        _conCalendar.reloadCalendar = function(fn, ojProcessing) {
1846        	$('#calTemporary').append($('#calCustom-buttons'));
1847			$('#calendar').fullCalendar('destroy');
1848			$('#calendar').find('#cal-fixed-header').remove();
1849			
1850			if (fn) {
1851				fn();
1852			}
1853			
1854			if (ojProcessing && ojProcessing.close) { ojProcessing.close(); }
1855			UI.closeAllPopups();
1856			
1857			UserPortal.Calendar.createFrontDeskCalendar();
1858			$("table.fc-agenda-days > thead > tr > th").click(GLO.Calendar.resourceHeaderClick);
1859			
1860			if (GLO.Info.isMobile(true)) {
1861				setTimeout(function() {
1862					GLO.Mobile.setupHeader(GLO.Info.isMobile());
1863					//$('#calendar').find('.fc-view-resourceDay thead:first').css({ "position": "relative" });		//.find('th.fc-agenda-gutter.fc-last').addClass('hideX');
1864					$(window).scroll();
1865				}, 500);
1866			}
1867        }
1868        
1869        _conCalendar.getInactiveAttributes = function(calEv) {
1870            var inactiveCode = UTIL.cleanString(calEv.inactive_cd);
1871            var retval = ' inactive_cd="' + inactiveCode + '"';
1872
1873            if (!UTIL.isEmpty(inactiveCode)) {
1874                if (inactiveCode == '1') {
1875                    var staffName = $('#inactiveStaffBar .hello-bar-label a#inactive-staff' + calEv.staff_id).text();
1876                    retval += ' inactive_vc="' + staffName + '"';
1877                } else if (inactiveCode == '2') {
1878                    retval += ' inactive_vc="' + calEv.service_group_name_vc + '"';
1879                } else if (inactiveCode == '4') {
1880                    retval += ' inactive_vc="' + calEv.staff_vc + '"';
1881                } else if (inactiveCode == '5') {
1882                    retval += ' inactive_vc="Resource"';
1883                }
1884            }
1885
1886            return retval;
1887        }
1888        
1889        _conCalendar.getOtherAttributes = function(calEv) {
1890        	var attributes = '', signin = calEv.signin_dt;
1891        	
1892        	if (UTIL.isDate(signin)) {
1893        		attributes += ' signin_dt="' + signin + '"';
1894        	}
1895        	
1896        	if (calEv.phone_message_status_cd) {
1897        		attributes += ' confirm_status_cd="' + calEv.phone_message_status_cd + '"';
1898        	}
1899        	
1900        	if (!UTIL.isEmpty(calEv.multi_ticket_id)) {
1901        		attributes += ' multi_ticket_id="' + calEv.multi_ticket_id + '"';
1902        	}
1903        	
1904        	if (!UTIL.isEmpty(calEv.form_provider_id)) {
1905        		attributes += ' form_provider_id="' + calEv.form_provider_id + '"';
1906        	}
1907        	
1908        	return attributes;
1909        }
1910
1911        return _conCalendar;
1912    })();
1913    
1914    return _conSchedule;
1915})();
1916
1917GLO.Communicate.Message = (function() {
1918    function _conMsg() { }
1919    
1920    _conMsg.open = function() {
1921        var oj = $('.staffCheck:checked');
1922        var ij = oj.size();
1923        
1924        if (ij === 0) {
1925            oj = $('#staffCheck');
1926
1927            if (oj.size() === 1) {
1928                oj.prop('checked', true);
1929                ij = 1;
1930            } else {
1931                GLO.Popup.Warning(SA.Resource.PleaseSelectBox3);
1932                return;
1933            }
1934        }
1935        
1936        if (ij > 0) {
1937            var phone = '', staffName = '', staffId = '', noPhoneCount = 0, noPhoneList = '';
1938            
1939            for (var i=0; i < ij; i++) {
1940                var tmp = oj.eq(i).parent().parent().find('td').eq(1);
1941                var phoneOrEmail = tmp.attr('phone');
1942                
1943                if (UTIL.isEmpty(phoneOrEmail) || UTIL.isEmpty(tmp.attr('mobileProvider'))) {
1944                	phoneOrEmail = tmp.attr('email');
1945                }
1946                
1947                if (UTIL.isEmpty(phoneOrEmail)) { 
1948                    if (noPhoneCount !== 0) { noPhoneList += ', '; }
1949                    noPhoneList += tmp.text(); 
1950                    
1951                    oj.eq(i).prop('checked', false);
1952                    noPhoneCount++;
1953                } else {
1954                	if (!UTIL.isEmpty(phone)) {
1955                		phone += ',';
1956                		staffName += ',';
1957                		staffId += ',';
1958                	}
1959                	
1960                	phone += phoneOrEmail;
1961                	staffName += tmp.text();
1962                	staffId += tmp.closest('tr').attr('id').replace('trStaff', '');
1963                }
1964            }
1965
1966            var yesPhoneCount = ij - noPhoneCount;
1967            
1968            if (yesPhoneCount > 0) {
1969            	_open2(staffName, staffId, phone);
1970            }
1971
1972            if (noPhoneCount > 0) {
1973                var header = 'Staff Missing Phone / Email'
1974                var msgOptin = '<span class="narrow-text" style="display: inline;">(or have not opted in by selecting their phone company)</span>';
1975                var msgBad = ' do not have a mobile phone number ' + msgOptin + ' and do not have an email';
1976                var msgGood = 'This message will be sent to the other ';
1977                var words = SA.Resource.Members.toLowerCase();
1978                var p1 = '<p style="margin-bottom: 16px; line-height: 1.4;">';
1979                
1980                if ((ij - noPhoneCount) === 1) { var words = SA.Resource.Member.toLowerCase(); }
1981                
1982                if (noPhoneCount === 1 && ij > 1) {
1983                    GLO.Popup.Warning.open(p1 + noPhoneList + msgBad + '</p>' + p1 + msgGood + yesPhoneCount + ' ' + SA.Resource.Staff.toLowerCase() + ' ' + words + '</p>', header);
1984                } else if (yesPhoneCount > 0) {
1985                    noPhoneList = ' <span class="narrow-text" style="display: inline; font-weight: bold;">(' + noPhoneList + ')</span>';
1986                    var htmNoPhone = p1 + noPhoneCount + ' ' + SA.Resource.SelectedStaffMembers.toLowerCase() + noPhoneList + msgBad + '</p>';
1987                    var htmYesPhone = p1 + msgGood + yesPhoneCount + ' ' + SA.Resource.Staff.toLowerCase() + ' ' + words + '</p>';
1988                    
1989                    GLO.Popup.Warning.open(htmNoPhone + htmYesPhone, header);
1990                } else if (ij === 1) {
1991                	var msgOptin = ' <span class="narrow-text" style="display: inline;">(and opt-in by selecting their phone company)</span>';
1992                	
1993                	var msg1 = p1 + SA.Resource.StaffMissingPhone + msgOptin + ' and does not have an email</p>';
1994                	var msg2 = p1 + SA.Resource.ToSendTextTo + ' ' + staffName + ' ' + SA.Resource.PleaseAddPhone + msgOptin + '</p>';
1995                	var msg3 = p1 + 'Or add an email address for the staff</p>';
1996                	var htm = '<div id="pop-warn-staff-missing-contact-info">' + msg1 + msg2 + msg3 + '</div>';
1997                	
1998                	GLO.Popup.Warning.open(htm, header);
1999                } else {
2000                    var msg1 = p1 + SA.Resource.NoneOfSelectedStaff + ' ' + msgOptin + ' and has no email</p>';
2001                    var msg2 = p1 + SA.Resource.ToSendTextToStaff + '</p>';
2002                    var msg3 = p1 + 'To send an email please add an email for the staff</p>';
2003                    var htm = '<div id="pop-warn-staff-missing-contact-info">' + msg1 + msg2 + msg3 + '</div>';
2004                    
2005                    GLO.Popup.Warning.open(htm, header);
2006                }
2007
2008                ij = ij - noPhoneCount;
2009            }
2010        }
2011    }
2012
2013    function _open2(names, ids, phones) {
2014    	var jpop = $('#pop-sendtext');
2015    	var ojpop = new GLO.Popup.Custom(jpop);
2016        jpop = ojpop.getPopup();            //.addClass('no-persist');
2017    	
2018    	if (false && GLO.Info.isMobile(false)) {
2019    		jpop.find('.pop-buttons-parent').prepend('<a id="send-sms" href="sms:+' + phones + '">SMS</a>');
2020    		jpop.find('#send-sms').click();
2021    		ojpop.close();
2022    	} else {
2023    		jpop.find('.pop-buttons-parent').remove();
2024    		
2025	    	jpop.find('#TextMsg-Person').text(names);
2026		    jpop.find('#TextMsg-PersonId').val(ids);
2027		    jpop.find('#TextMsg-Phone').text(phones);
2028		}
2029    }
2030
2031    _conMsg.sendText = function() {
2032        var url = GLO.Link.WebsiteDomain + 'message/send';
2033        
2034        var jpop = $('#pop-sendtext:visible');
2035        var jsave = jpop.find('.btnSave');
2036        GLO.UI.Form.beginProcessing(jsave);
2037        
2038        var msg = jpop.find('textarea').val();
2039        var staffIds = jpop.find('#TextMsg-PersonId').val();
2040
2041        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { msgFormat: 3, message: msg, staff_ids: staffIds } })
2042            .success(function(data, textStatus, jqXHR) {
2043                _processSendMessageResponse(jpop, jsave, data);
2044            })
2045            .error(function(jqXHR, textStatus, errorThrown) {
2046                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2047            });
2048
2049	    $.modal.close();
2050    }
2051    
2052    _conMsg.openGeneric = function(label, msg, sid, sname, isSaveAppt, mtype, action) {
2053    	var htmRadio = '', style = 'width: 460px; text-align: center;';
2054    	
2055    	if (GLO.Data.provider.staff_text_alert_format_cd > 19 && GLO.Data.provider.staff_text_alert_format_cd < 40) {
2056	    	var inAppChecked = '', textChecked = '';
2057	    	
2058	    	if (GLO.Data.provider.staff_text_alert_format_cd == 20) {
2059	    		inAppChecked = ' checked="checked"';
2060	    	} else if (GLO.Data.provider.staff_text_alert_format_cd == 30) {
2061	    		textChecked = ' checked="checked"';
2062	    	}
2063	    	
2064	    	var rdoInApp = '<input type="radio" id="Send_InApp_Format_cd" name="Staff_Text_Alert_cd" value="5"' + inAppChecked + '/> <label for="Send_InApp_Format_cd">In-App Notification</label>';
2065	    	var rdoText =  '<input type="radio" id="Send_Text_Format_cd"  name="Staff_Text_Alert_cd" value="3"' + textChecked  + '/> <label for="Send_Text_Format_cd">Text Message</label>';
2066	    	
2067	    	var inApp = '<span id="generic-format-inapp" class="generic-format">' + rdoInApp + '</span>';
2068	    	var text = '<span id="generic-format-text" class="generic-format">' + rdoText + '</span>';
2069	    	var htmRadio = '<div id="generic-message-format">' + inApp + text + '</div>';
2070    	}
2071    	
2072    	if ($(window).width() < 480) {
2073    		style = 'width: 310px; text-align: center;';
2074    	}
2075    	
2076    	var msg = $('<div staff_id="' + sid + '" message_type_cd="' + UTIL.cleanString(mtype) + '" id="pop-send-generic-text" style="' + style + '">'
2077					    + htmRadio
2078					    + '<input type="hidden" id="Text_Staff_id" value="' + sname + '"/>'
2079					    + '<h2 style="padding: 6px 0; letter-spacing: 1px;">' + label + '</h2>'
2080					    + '<textarea id="generic-message" rows="4" maxlength="140">' + msg + '</textarea>'
2081    			+ '</div>');
2082    	
2083    	var fnSave = function() { GLO.Communicate.Message.sendTextGeneric(isSaveAppt, action); };
2084    	
2085    	var ojpop = new GLO.Popup.Custom(msg, fnSave);
2086        jpop = ojpop.getPopup().addClass('no-persist');
2087    	
2088    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
2089    	jbtns.find('.btnSave').find('a').text('Send');
2090    	
2091    	_checkStaffAlertSetting(sname, sid);
2092    }
2093    function _checkStaffAlertSetting(sname, sid) {
2094    	if (!UTIL.isNumber(sid)) {
2095    		return;
2096    	}
2097    	
2098    	var url = GLO.Link.WebsiteDomain + 'wizard2/GetStaffConfigData?staff=' + sid;
2099    	var jpop = $('#pop-send-generic-text').closest('.glopop');
2100        
2101    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
2102            .success(function(data, textStatus, jqXHR) {
2103                var jdata = $(data);
2104                var hasPushEnabled = UTIL.parseBool(jdata.attr('push_enabled_fl'));
2105                
2106                if (jdata.hasClass('success')) {
2107                	if (!UTIL.Validate.phone(jdata.attr('phone'))) {
2108                		var msg = '<p style="margin: 8px 0; letter-spacing: 1px; text-align: center;">' + sname + ' profile has no phone number</p>';
2109                		jpop.find('#generic-message-format').html(msg);
2110                		return;
2111                	}
2112                	
2113                	if (GLO.Data.provider.staff_text_alert_format_cd == 10) {
2114                		jpop.find('#generic-format-text').remove();
2115                	} else if (UTIL.parseBool(jdata.attr('text_on_checkin_fl'))) {
2116                		jpop.find('#Send_Text_Format_cd').prop('checked', true);
2117                	}
2118                	
2119                	if (!hasPushEnabled) {
2120                		var link = '<a onclick="GLO.Uri.gotoUri2(\'help#tab=message&id=faq-message-staff-in-app-notifications\')">In-App Notifications Not Enabled</a>';
2121                		var htmText = '<div style="margin: 8px 0; letter-spacing: 1px;">' + link + '</div>';
2122                		
2123                		jpop.find('#generic-format-inapp').remove();
2124                		jpop.find('#generic-message-format').after(htmText);
2125                	} else if (UTIL.parseBool(jdata.attr('inapp_on_checkin_fl'))) {
2126                		jpop.find('#Send_InApp_Format_cd').prop('checked', true);
2127                	}
2128                }
2129            })
2130            .error(function(jqXHR, textStatus, errorThrown) {
2131                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2132            });
2133    }
2134    _conMsg.sendTextGeneric = function(isSaveAppt, action) {
2135    	var j = $('#pop-send-generic-text');
2136    	var msg = j.find('#generic-message').val();
2137    	var msgType = j.attr('message_type_cd');
2138    	
2139    	var staffId = j.attr('staff_id');
2140    	var staffName = j.find('#Text_Staff_id').val();
2141    	var staffTextAlertFormat = UTIL.coalesceInt(j.find('#Staff_Text_Alert_cd').val(), 3);
2142    	
2143    	var url = GLO.Link.WebsiteDomain + 'message/send';
2144    	var jpop = j.closest('.glopop');
2145    	var jsave = jpop.find('.btnSave');
2146    	
2147    	GLO.UI.Form.beginProcessing(jsave);
2148    	
2149    	if (isSaveAppt) {
2150    		UserPortal.getEditAppt().find('#ba-SaveEdit > a').click();
2151    	}
2152    	
2153        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "msgFormat": staffTextAlertFormat, "mtype": msgType, "message": msg, "staff_ids": staffId, "label": action } })
2154            .success(function(data, textStatus, jqXHR) {
2155                _processSendMessageResponse(jpop, jsave, data, staffName);
2156            })
2157            .error(function(jqXHR, textStatus, errorThrown) {
2158                GLO.Popup.close($('#pop-send-generic-text').closest('.glopop'));
2159                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2160            });
2161    }
2162    
2163    function _processSendMessageResponse(jpop, jsave, data, staffNames) {
2164    	var msg = '', jdata = $(data);			//GLO.UI.Form.resetProcessing();
2165        var isSuccess = false, header = 'Message Not Sent';
2166        var isWarning = jdata.hasClass('warning') || jdata.find('li[warning_cd]').length;
2167        
2168        if (jdata.hasClass('success')) {
2169        	isSuccess = true;
2170        	header = 'Message Sent';
2171        	
2172        	if (!UTIL.isEmpty(staffNames)) {
2173        		msg = '<p>' + staffNames + ' Notified</p>';
2174        	}
2175        }
2176        
2177        if (jdata.find('li[error_cd]').length || isWarning) {
2178        	var htm = '<div id="pop-success-send-custom-message">' + msg + data + '</div>';
2179        	var jpop = GLO.Popup.Custom.openSimple(htm, header);
2180        	
2181        	GLO.Popup.Custom.singleButton(jpop, 'Close');
2182        	//GLO.Popup.Error.open(msg + jdata.outerHTML(), header);
2183        	//GLO.Popup.Warning.open(msg + jdata.outerHTML(), header);
2184        } else if (isWarning && jdata.find('#bulk-deliverability-score').length) {
2185        	var ojpop = new GLO.Popup.Custom(jdata);
2186			var jpop = ojpop.getPopup().addClass('no-persist').attr('id', 'pop-bulk-deliverability-score');
2187			
2188			GLO.Popup.Custom.singleButton(jpop, 'Close');
2189			ojpop.realign(); ojpop.realign();
2190			
2191			GLO.UI.Form.resetProcessing(jsave);
2192			return;
2193        } else if (isSuccess) {
2194        	GLO.Popup.Success.open(msg, header);
2195        } else {
2196        	var htm = '<div id="pop-warning-send-custom-message"><p>Unable to send message</p><p>Please try again later</p></div>';
2197        	GLO.Popup.Warning.open(htm, header);
2198        	GLO.UI.Form.resetProcessing(jsave);
2199        	return;
2200        }
2201        
2202        GLO.Popup.closeIfExist($('#pop-send-generic-text').closest('.glopop'));
2203        GLO.Popup.closeIfExist($('#pop-sendtext').closest('.glopop'));
2204    }
2205
2206    _conMsg.view = function(msgId, isText) {			//= used for viewing reminders from Reminder View
2207        var url = GLO.Link.WebsiteDomain + 'message/' + msgId + '?ispartial=1&dt=' + UTIL.getDateString();
2208        
2209        GLO.Popup.closeIfExist( $('#report-message-sent-history').closest('.glopop') );
2210        
2211        GLO.Popup.Processing.open('Opening Reminder Sent To Client...');
2212        viewTemplate(url);
2213    }
2214
2215    function viewTemplate(uri, isText) {
2216        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "110px auto"});
2217        var pop = $('#pop-temp');
2218        
2219        pop.html(throbber).load(uri, function() {
2220            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
2221            GLO.Popup.closeIfExist($('.pop-processing').closest('.glopop'));
2222            
2223            var jModal = $('#simplemodal-container').addClass('view-message');
2224            jModal.draggable({ "handle": "#msg-header" }).find('#msg-header').css({ "cursor": "move", "min-width": "640px" });
2225            
2226            jModal.css({ "height": "auto", "width": "auto", "padding": "0" });
2227            jModal.find('.simplemodal-data').css({ "padding": "0" });
2228            
2229            jModal.find('.sdiff-appt, #view-appt-link').css({ "margin": "auto" });
2230            jModal.find('#msg-header-left').css({ "text-align": "left" });
2231
2232            jModal.find('#body_style.text-reminder').css({ "color": "#222" });
2233            jModal.find('a').css({ "text-decoration": "none" });
2234            var mh = jModal.height() + 50, mw = (jModal.width() + 15);
2235            
2236            if (innerWidth < mw) {
2237            	mw = parseInt(innerWidth * .99);
2238            }
2239            
2240            if (mh < 240) {
2241            	mh = 240;
2242            } else if (mh > innerHeight && !GLO.Info.isMobile()) {
2243            	mh = parseInt(innerHeight * .9);
2244            }
2245            
2246            $.modal.update(mh, mw);
2247            
2248            jModal.find('.simplemodal-wrap').addClass('scrollable-for-mac').css({ "overflow": "auto" });
2249            $(window).trigger('resize.simplemodal');
2250            
2251            jModal.find('#msg-header').css({ "border-top-left-radius": "5px" });
2252        });
2253
2254        pop.modal();
2255        $.modal.update(300, 300);
2256    }
2257
2258    return _conMsg;
2259})();
2260
2261GLO.Hours = (function() {              //?? Should this be WIZ.Hours and go in wizard.js ??
2262    var hourChangeInProgress = false;
2263    function _constructor(name) { }
2264    _constructor.loading = true;
2265	
2266	_constructor.openViewAdjustedTimes = function(btn) {
2267		var htm = '<div id="pop-time-adjust-summary">' + $('#time-adjust-summary-container').html() + '</div>';
2268		var jpop = GLO.Popup.Custom.openSimple(htm, 'Open / Close Time Adjusted');
2269		var jtbl = jpop.find('#time-adjust-summary-table');
2270		
2271		UI.initTableSorter(jtbl);
2272		GLO.Popup.Custom.singleButton(jpop, 'Close');
2273	}
2274    _constructor.openEditAdjustedTime = function(btn) {
2275    	var tr = $(btn).closest('tr');
2276    	var staffId = tr.closest('table').attr('staff');
2277    	var staffName = $.trim($('#wiz5-popupHours #wiz5-staffName').text());
2278    	
2279    	var day = tr.attr('day');
2280    	var tmOpen = $.trim(tr.find('.time-adjust-open').text()).replace('normal', '');
2281    	var tmClose = $.trim(tr.find('.time-adjust-close').text()).replace('normal', '');
2282    	
2283    	_constructor.openEditAdjustedTimePopup(staffId, staffName, day, tmOpen, tmClose);
2284    }
2285    _constructor.openEditAdjustedTimePopup = function(staffId, staffName, day, tmOpen, tmClose) {
2286    	var openEdit = '<input type="text" id="Adjust_Open_tm" name="Adjust_Open_tm" class="is-time-picker" value="' + tmOpen + '" pattern="[0-9]*">';
2287    	var closeEdit = '<input type="text" id="Adjust_Close_tm" name="Adjust_Close_tm" class="is-time-picker" value="' + tmClose + '" pattern="[0-9]*">';
2288    	
2289    	var labelOpen = '<label for="Adjust_Open_tm">Open</label>';
2290    	var labelClose = '<label for="Adjust_Close_tm">Close</label>';
2291    	
2292    	var htmOpen = '<div class="adjust-time-edit-row">' + labelOpen + openEdit + '</div>';
2293    	var htmClose = '<div class="adjust-time-edit-row">' + labelClose + closeEdit + '</div>';
2294    	
2295    	var header = staffName + ' ' + new Date(day).toGloDateString(true, true);			//Open/Close Time Adjusted on 
2296    	var htm = '<div id="pop-edit-adjusted-day" staff="' + staffId + '" day="' + day + '">' + htmOpen + htmClose + '</div>';
2297    	var jpop = GLO.Popup.Custom.openSimple(htm, header, GLO.Hours.saveAdjustedTime);
2298    	
2299    	var btnReset = '<span class="btnDelete btnReset" style="margin: 0;"><a onclick="GLO.Hours.resetAdjustedTime()" style="position: absolute; left: 6px;">Reset</a></span>';
2300    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "8px" });
2301    	
2302    	jbtns.find('.btnCancel').css({ "float": "none", "position": "relative", "display": "inline-block", "width": "80px", "margin": 0, "padding": 0, "font-weight": "bold" });
2303    	jbtns.find('.btnSave').css({ "width": "80px", "margin": 0 }).after(btnReset);
2304    	
2305    	UI.timeMask('#Adjust_Open_tm');
2306    	UI.timeMask('#Adjust_Close_tm', '11:59 am');
2307    	
2308    	UI.setTimeMaskValue(jpop.find('#Adjust_Open_tm'), tmOpen);
2309        UI.setTimeMaskValue(jpop.find('#Adjust_Close_tm'), tmClose);
2310    }
2311    _constructor.saveAdjustedTime = function() {
2312    	var jpop = $('#pop-edit-adjusted-day');
2313    	var staffId = jpop.attr('staff');
2314    	var day = jpop.attr('day');
2315    	var open = UI.getTimeMaskValue(jpop.find('#Adjust_Open_tm'));
2316    	var close = UI.getTimeMaskValue(jpop.find('#Adjust_Close_tm'));
2317    	
2318    	var url = GLO.Link.Object.AppointmentAjax + 'AdjustDaysNormalHoursPopup?day=' + day + '&staff=' + staffId + '&open=' + open + '&close=' + close;
2319    	jpop = jpop.closest('.glopop');
2320        GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
2321        
2322        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
2323            .success(function(data, textStatus, jqXHR) {
2324                GLO.UI.Form.resetProcessing();
2325                
2326                if ($(data).hasClass('warning') || $(data).hasClass('error')) {
2327                	GLO.Popup.Warning.open(data, 'Unable to Change Open / Close');
2328                	return;
2329                }
2330                
2331                GLO.Popup.closeIfExist(jpop);
2332                GLO.Popup.closeIfExist( $('#pop-time-adjust-summary').closest('.glopop') );
2333                GLO.Popup.closeIfExist( $('#wiz5-popupHours').closest('.glopop') );
2334                
2335                if (GLO.Calendar !== undefined) {
2336                	GLO.Popup.Processing.open('Loading New Open / Close Time...', 'Day Adjusted');
2337                	
2338                	setTimeout(function() {
2339                		location.reload();
2340                	}, 400);
2341                } else if ($('#wiz5-popupHours').length) {
2342                	$.modal.close();
2343                }
2344            })
2345            .error(function(jqXHR, textStatus, errorThrown) {
2346                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2347            });
2348    }
2349    _constructor.resetAdjustedTime = function(btn) {
2350    	var jpop = $('#pop-edit-adjusted-day');
2351    	var staffId = jpop.attr('staff');
2352    	var day = jpop.attr('day');
2353    	
2354    	var url = GLO.Link.Object.AppointmentAjax + 'AdjustDaysNormalHoursReset?day=' + day + '&staff=' + staffId;
2355    	jpop = jpop.closest('.glopop');
2356        GLO.UI.Form.beginProcessing(jpop.find('.btnReset'));
2357        
2358        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
2359            .success(function(data, textStatus, jqXHR) {
2360                GLO.UI.Form.resetProcessing();
2361                
2362                if ($(data).hasClass('warning') || $(data).hasClass('error')) {
2363                	GLO.Popup.Warning.open(data, 'Unable to Change Open / Close');
2364                	return;
2365                }
2366                
2367                GLO.Popup.closeIfExist(jpop);
2368                GLO.Popup.closeIfExist( $('#pop-time-adjust-summary').closest('.glopop') );
2369                GLO.Popup.closeIfExist( $('#wiz5-popupHours').closest('.glopop') );
2370                
2371                if (GLO.Calendar !== undefined) {
2372                	GLO.Popup.Processing.open('Open / Close Time Reset to Default, Loading Changes ...', 'Open / Close Time Reset');
2373                	
2374                	setTimeout(function() {
2375                		location.reload();
2376                	}, 400);
2377                } else if ($('#wiz5-popupHours').length) {
2378                	$.modal.close();
2379                }
2380            })
2381            .error(function(jqXHR, textStatus, errorThrown) {
2382                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2383            });
2384    }
2385	
2386    _constructor.isClosed = function(checkbox, isInit) {
2387        hourChangeInProgress = true;
2388        if (_constructor.loading) { isInit = true; }
2389
2390        var jClosed = $(checkbox);
2391        var jHide = jClosed.parent().parent().find('>td.HideOnCalendar');
2392        var timeParent = jClosed.parent().parent().find('.wizHoursTime');
2393
2394        var row = jClosed.attr('id');
2395        row = row.substr(row.length-1);
2396            
2397        if (jClosed.is(':checked')) {
2398            jHide.removeClass('hide');
2399            if (!isInit) { jHide.find('>input').prop('checked', true); }
2400            timeParent.css('text-decoration', 'line-through');
2401            timeParent.css('opacity', '.5');
2402            timeParent.closest('tr').addClass('row-off');
2403
2404            $('#Start_tm' + row).attr('title', '').blur();
2405            //$('#Start_tm' + row + 'b').attr('title', '').blur();
2406            $('#End_tm' + row).attr('title', '').blur();
2407            //$('#End_tm' + row + 'b').attr('title', '').blur();
2408        } else {
2409            jHide.addClass('hide');
2410            jHide.find('>input').removeAttr('checked');
2411            timeParent.css('text-decoration', '');
2412            timeParent.css('opacity', '');
2413            timeParent.closest('tr').removeClass('row-off');
2414            
2415            $('#Start_tm' + row).blur();
2416            //$('#Start_tm' + row + 'b').blur();
2417            $('#End_tm' + row).blur();
2418            //$('#End_tm' + row + 'b').blur();
2419        }
2420
2421        hourChangeInProgress = false;
2422    }
2423    
2424    _constructor.init = function() {
2425        var tm, jContainer = $('#wizHours');
2426            
2427        $.each(jContainer.find("input.bizClosed"), function() {
2428			GLO.Hours.isClosed(this, true);
2429		});
2430            
2431        for (var i=1; i < 8; i++) {
2432            if ($('#Closed_fl' + i).is(':checked')) {
2433                _constructor.isClosed($('#Closed_fl' + i)[0]);
2434            }
2435                
2436            UI.timeMask('#Start_tm' + i, '5:00 am');
2437            UI.timeMask('#End_tm' + i, '11:59 am');
2438        }
2439        
2440        UI.timeMask('#CalendarMinTime', '4:00 am');
2441        UI.timeMask('#CalendarMaxTime', '11:59 am');
2442        
2443        if ($.cookies.get('pstatus') == 2) {
2444            var jHolidayContainer = $('#wizHolidays');
2445            jHolidayContainer.find('#New_Years_fl').prop('checked', true);
2446            jHolidayContainer.find('#Thanksgiving_fl').prop('checked', true);
2447            jHolidayContainer.find('#Christmas_fl').prop('checked', true);
2448
2449            var d = new Date();
2450	        var isDaylightSavings = false;
2451	        var gmt = -d.getTimezoneOffset() / 60;
2452	        if (isDaylightSavings) { gmt -= 1; }
2453
2454            var optList = $('#Time_Zone_cd option');
2455            var optLen = optList.length;
2456
2457            for (var i=0; i < optLen; i++) {
2458	            if (optList.eq(i).attr('offset') == gmt) {
2459                    $('#Time_Zone_cd').val(optList.eq(i).attr('value'));
2460                }
2461            }
2462            
2463            if (GLO.Info.isIPhone) {
2464            	jContainer.find('.open-time:not(#Start_tm1)').val('09:00:00');
2465            	jContainer.find('.close-time:not(#End_tm1)').val('18:00:00');
2466            }
2467        }
2468    }
2469    
2470    _constructor.initAdjustedDays = function(staffId) {
2471    	var jwiz = $('#wizNormalHours');
2472    	var cnt = UTIL.coalesceInt(jwiz.attr('startOrEndTimeAdjustCount'), 0);
2473    	var firstDay = jwiz.attr('firstDayAdjusted');
2474    	
2475    	if (cnt > 0) {
2476    		//var sid = UTIL.coalesceInt($('#wiz3-form').attr('edit_staff_id'), GLO.Info.StaffId);
2477    		
2478    		//var url1 = 'provider/CalendarOne?sfilter=' + staffId + '#vw=agendaDay&dt=' + firstDay;
2479    		//var a1 = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url1 + '\', this, event, true)"> ' + UTIL.pluralLabel(cnt, 'Day') + '</a>';
2480    		//var a2 = '<a id="wiz3-adjusted-days-faq" onclick="GLO.Uri.gotoUriWithSpinner(\'' + url2 + '\', this, event, true)">(different than listed below)</a>';
2481    		
2482    		var btn1 = '<span class="btnAdd">
2482<a onclick="GLO.Hours.openViewAdjustedTimes()">View ' + UTIL.pluralLabel(cnt, 'Day') + '</a></span>';
2483    		var note1 = '<span class="narrow-text" style="padding-left: 4px;"><i>with custom hours</i> different than listed below</span>'
2484    		
2485    		var helpIcon = '<b class="question-icon" onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=calendar&id=calendar-change-days-work-time\', this, event, true)">?</b>';
2486    		var htm = '<p id="wiz3-adjusted-days">' + btn1 + note1 + helpIcon + '</p>';
2487    		jwiz.before(htm);
2488    	}
2489    }
2490    
2491    _constructor.hourChange = function(element) {
2492        if (hourChangeInProgress) { return; }       //necessary to avoid infinite recursion.
2493        hourChangeInProgress = true;
2494
2495        var jElement = $(element);
2496        
2497        if (!UTIL.isEmpty(jElement.val())) {
2498            jElement.parent().css('text-decoration', '');
2499            var checkbox = jElement.parent().parent().find('input.bizClosed');
2500            checkbox.removeAttr('checked');
2501            _constructor.isClosed(checkbox[0], false);
2502        }
2503
2504        hourChangeInProgress = false;
2505    }
2506
2507    return _constructor;
2508})();
2509
2510var ClientProfile = (function() {
2511    function _constructor(name) { }
2512    var _unlockPassword = null, _unlockTimeout = null;
2513    
2514    _constructor.cancel = function() { history.back(1); }
2515    
2516    _constructor.clearUnlockPassword = function() {
2517    	clearTimeout(_unlockTimeout);
2518    	_unlockPassword = null;
2519    	//$('form#client-form').find('#Unlock_Password_vc').val('');
2520    }
2521    _constructor.setUnlockPassword = function(pass, timeout) {
2522    	_unlockPassword = pass;
2523    	clearTimeout(_unlockTimeout);
2524    	timeout = UTIL.coalesceInt(timeout, 5000);
2525    	
2526    	_unlockTimeout = setTimeout(function() {
2527    		_unlockPassword = null;
2528    	}, timeout);
2529    }
2530    _constructor.getUnlockPassword = function() {
2531    	return _unlockPassword;
2532    }
2533    
2534    _constructor.changeBalance = function(el) {
2535        if (el.value != '') {
2536            //$('#trBalance_Change_Reason').removeClass('hide');
2537            //$('#Balance_Change_Reason_vc').focus();
2538        }
2539    }
2540
2541    _constructor.save = function() {
2542        WIZ.save();
2543    }
2544    
2545    _constructor.addBackToWailList = function() {
2546    	if (innerWidth > 599) {
2547    		var jmodal = $('#simplemodal-container');
2548    		jmodal.find('#client-purchased-products-link').remove();
2549    		
2550    		var htm = '<a id="linkbackToWaitList" class="back-to-appointment" onclick="GLO.WaitList.reopen()">&lt; Back To Wait List</a>';
2551    		jmodal.find('h2#clientName').prepend(htm);
2552    	}
2553    }
2554    
2555    _constructor.goto = function(Client_id, IsPartial, clientName, fnAfterOpen) {
2556        var url = GLO.Link.Page.Provider.ClientProfile + '?cid=' + Client_id;
2557        
2558        if (UTIL.isEmpty(clientName) && this && event) {
2559        	clientName = event.target.innerText;
2560        }
2561        
2562        if (GLO.Data.Staff.hideClientContact) {
2563        	url = GLO.Link.Page.Provider.Home + 'NoteHistory?clientId=' + Client_id;
2564        }
2565        
2566        if (IsPartial) {
2567        	if ($('#simplemodal-container').is(':visible')) {
2568        		_constructor.open(url, true, clientName, fnAfterOpen);
2569        	} else {
2570            	_constructor.open(url, false, clientName, fnAfterOpen);
2571            }
2572        } else {
2573            document.location = url;
2574        }
2575    }
2576    
2577    _constructor.openAddCard = function() {
2578    	var jpop = $('#pop-member-pay-summary').closest('.glopop');
2579	    GLO.Popup.close(jpop);
2580	    $('#client-form #btnAddCardOnFile').find('a').click();
2581    }
2582    
2583    _constructor.switchPopup = function(cid, cparentid, cname) {
2584        //$.modal.close();
2585        var loadPage = GLO.Link.Page.Provider.ClientProfile + '?cid=' + cid + '&cparentid=' + UTIL.cleanString(cparentid);
2586        _constructor.open(loadPage, true);
2587    }
2588    
2589    _constructor.isFullPageProfile = function() {
2590    	var currUrl = document.location.pathname.toLowerCase();
2591        
2592        var openAsFullPage1 = (currUrl.indexOf("/provider/clientprofile") !== -1 || currUrl.indexOf("/provider/profile") !== -1 || currUrl.indexOf("/provider/appointment/history/client/") !== -1);
2593        var openAsFullPage2 = ($('.shadow-content0 #sale-keyboard:visible').length > 0 || currUrl.indexOf("/provider/apptsummary") !== -1);
2594        
2595        if (!openAsFullPage1) {
2596        	openAsFullPage1 = (currUrl.indexOf("/schedule/recur") !== -1 || currUrl.indexOf("/provider/notehistory") !== -1);
2597        }
2598        
2599        return (openAsFullPage1 || openAsFullPage2);
2600    }
2601    
2602    _constructor.open = function(url, modalAlreadyOpen, clientName, fnAfterOpen) {				//= ClientProfile.open()
2603        if (_constructor.isFullPageProfile()) {
2604            if (GLO.Info.isMobile(true)) { GLO.UI.animate(10); }
2605            document.location = url;
2606        } else {
2607            url += '&IsPartial=1&dt=' + UTIL.getDateString();
2608            
2609            var throbber = $('.loadingDiv').clone().find('img').css({"margin": "150px auto"});
2610            var pop = $('#pop-temp');
2611            
2612            if (modalAlreadyOpen) {
2613                $('#simplemodal-container .simplemodal-wrap #pop-temp').html(throbber);
2614                _addCloseIcon();
2615            }
2616            
2617            _constructor.openCompleted(url, modalAlreadyOpen, clientName, null, fnAfterOpen);
2618        }
2619    }
2620    
2621    function _addCloseIcon() {						//if open client profile from wait list popup + screen is < 990 -> no close button/icon
2622    	var jmodal = $('#simplemodal-container');
2623    	
2624    	if (jmodal.find('.simplemodal-close').length === 0) {
2625    		var icon = '<a class="modalCloseImg sa-sprite simplemodal-close" style="right: -2px;"></a>';
2626    		jmodal.prepend(icon);
2627    	}
2628    }
2629    
2630    _constructor.openCompleted = function(url, modalAlreadyOpen, clientName, smid, fnPostProcess) {
2631    	if (UTIL.isEmpty(fnPostProcess)) {
2632    		GLO.Popup.closeIfExist($('.appt-list-sheet, .popup-report').closest('.glopop'));
2633    	}
2634    	
2635    	var htm = '<div id="pop-processing-open-client-profile">' + SA.Resource.LookingUp + ' ' + UTIL.cleanString(clientName) + '...' + '</div>';
2636    	var ojProcessing = GLO.Popup.Processing.open(htm, 'Opening Client Profile');
2637    	
2638    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
2639            .success(function(data, textStatus, jqXHR) {
2640            	if (ojProcessing) {
2641            		ojProcessing.close();
2642            	} else {
2643            		var jpop = $('#pop-help-cell-summary').closest('.glopop');
2644            		GLO.Popup.closeIfExist(jpop);
2645            		
2646            		$('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove();
2647            	}
2648            	
2649            	_loadClientProfile(modalAlreadyOpen, smid, data);
2650                
2651                if (fnPostProcess) { fnPostProcess(smid); }
2652        	})
2653            .error(function(jqXHR, textStatus, errorThrown) {
2654                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2655            });
2656    }
2657    
2658    function _openDirections(modalAlreadyOpen, smid, clientId, clientName, url) {
2659    	var h1 = '<h1 class="friendly-msg2">' + SA.Resource.Address + ' ' + SA.Resource.Lookup + '</h1>';
2660        var msg = '<div>' + h1 + '<div class="friendly-msg2">' + SA.Resource.LookingUp + ' ' + UTIL.cleanString(clientName) + ' ' + SA.Resource.Address + '...</div> </div>';
2661    	var ojProcessing = new GLO.Popup.Processing(msg);
2662    	
2663    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
2664            .success(function(data, textStatus, jqXHR) {
2665            	if (ojProcessing) { ojProcessing.close(); }
2666            	
2667            	if (_lookupDirections(data)) {
2668            		$('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove();
2669            	} else {
2670            		_loadClientProfile(modalAlreadyOpen, smid, data);
2671            		ClientProfile.openProfileOnlyCompleted(smid);
2672            		
2673            		var h1 = '<h1 class="friendly-msg2">Address Missing</h1>';
2674            		var msg = '<div>' + h1 + '<div class="friendly-msg2">' + clientName + ' has no Street Address<br/><br/>Please Enter a Street Address</div> </div>';
2675            		var fnOk = function() { $('#displayProfile-Client Street_vc').focus(); }
2676            		new GLO.Popup.Warning(msg, fnOk);
2677            	}
2678        	})
2679            .error(function(jqXHR, textStatus, errorThrown) {
2680                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
2681            });
2682    }
2683    
2684    function _lookupDirections(data) {
2685    	var jd = $(data);
2686    	var street = encodeURIComponent($.trim(jd.find('#Street_vc').val()));
2687    	
2688    	if (UTIL.isEmpty(street)) {
2689    		return false;
2690    	}
2691    	
2692    	var city = encodeURIComponent($.trim(UTIL.coalesce(jd.find('#City_vc').val(), GLO.Data.provider.city)).replace(' ', ' ').replace(' ', '+'));
2693    	var state = encodeURIComponent($.trim(UTIL.coalesce(jd.find('#State_cc').val(), GLO.Data.provider.state)));
2694    	var zip = encodeURIComponent($.trim(jd.find('#Zip_vc').val()).replace(' ', ' ').replace(' ', '+'));
2695    	
2696    	street += '+' + city + ',' + state;
2697    	if (UTIL.isEmpty(zip)) { street += '+' + zip; }
2698    	
2699    	var url = 'https://maps.google.com?saddr=My+Location&daddr=' + street;		//var url = 'https://maps.google.com/?q=' + addressLongLat;
2700    	SA.App.openLinkInBrowser(url, true);										//window.open(url, '_system');
2701    	
2702    	return true;
2703    }
2704    
2705    function _loadClientProfile(modalAlreadyOpen, smid, data) {
2706    	if (ClientProfile.isFullPageProfile()) {
2707        	UI.closeAllPopups();
2708        	var jcontainer = $('.shadow-content0').html(data);
2709        } else if (modalAlreadyOpen) {
2710    		var throbber = $('.loading-client-quick-view').remove();
2711    		var jcontainer = $('#simplemodal-container');
2712    		
2713    		if ($('.shadow-content0 .client-name-header').length > 0) {
2714    			if (jcontainer.length > 0) { $.modal.close(); }
2715    			
2716    			jcontainer = $('.shadow-content0').html(data);
2717    		} else if (jcontainer.length === 1) {
2718    			jcontainer.find('> .simplemodal-wrap').html(data);
2719    		} else if (throbber.length === 1) {
2720    			jcontainer = $('.shadow-content0').html(data);
2721    		}
2722    	} else {
2723    		$(data).modal();
2724    		var jcontainer = $('#simplemodal-container');
2725    	}
2726    	
2727    	if (jcontainer.find('#note-history').length > 0) {
2728    		SA.Note.postOpen(smid);
2729    		return;
2730    	} else if (jcontainer.find('#displayProfile-Client.appt-summary-only').length > 0) {
2731    		GLO.ClientProfile.initApptSummary();
2732    		return;
2733    	}
2734    	
2735    	if (!GLO.Info.isMobile()) { $.modal.update(620, 670); }
2736        
2737        var pop = $('#simplemodal-container');
2738        
2739        if (pop.length === 1) {
2740        	pop.css({ "padding": "0", "background-color": "" });
2741        	
2742        	pop.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
2743        	pop.find('#displayProfile-Client').css({ "padding": 0 });
2744        	//_openCompleted(pop, smid);
2745        }
2746        
2747        GLO.ClientProfile.init();
2748    }
2749    
2750    function _cleanClientName(cname) {
2751    	if (cname && cname.length > 1 && cname.substring(0,2) === '* ') {
2752    		cname = cname.substring(2);
2753    	}
2754    	
2755    	return cname;
2756    }
2757    
2758    _constructor.getClientObject = function(isProfile) {
2759    	var j = UserPortal.getEditAppt();
2760    	
2761    	if (j.length === 1) {
2762    		var cname = _cleanClientName(j.find('h4 > a').text());
2763    		var json = { "id": UserPortal.Edit.clientId, "name": cname, "ismodal": true, "smid": UserPortal.Edit.scheduleMultiId, "bkg": UserPortal.Edit.booking_nr };
2764    	} else {
2765    		j = $('#simplemodal-container');
2766    		
2767    		if (j.length === 1) {
2768    			var isModal = true;
2769    		} else {
2770    			var isModal = false;
2771    			
2772    			if (j.length === 0) {
2773    				j = $('.shadow-content0');
2774    				j.addClass('loading-profile');
2775    			}
2776    			
2777    			//if (j.length === 0) { j = $('body'); }
2778    		}
2779    		
2780    		var bkg = null, smid = null, clientId = null, cname = '';
2781    		var jclient = j.find('.client-name-header:visible');						//var jclient = j.find('#clientName');
2782    		
2783    		if (jclient.length === 0) {
2784    			jclient = j.find('.client-name-header');
2785    		}
2786    		
2787    		if (jclient.length) {
2788    			cname = jclient.find('span').eq(0);
2789	    		
2790	    		if (cname.length === 1) {
2791	    			cname = cname.text();
2792	    		} else {
2793	    			cname = jclient.text();
2794	    		}
2795    			
2796    			if (jclient.closest('#note-history').length === 1) {
2797    				cname = cname.replace(' Notes', '');
2798    			}
2799    			
2800    			clientId = jclient.attr('client_id');
2801    			smid = UTIL.cleanString(jclient.find('.back-to-appointment').attr('smid'));
2802    		} else if (GLO.isPOS) {
2803    			jclient = $('#pos-ticket-client .client-lookup');
2804    			cname = jclient.val();
2805    			clientId = SA.Ticket.clientId;
2806    			bkg = SA.Ticket.bookingNumber;
2807    			smid = $('#pos-ticket').attr('schedule_multi_id');
2808    		}
2809    		
2810    		cname = _cleanClientName(cname);
2811    		var json = { "id": clientId, "name": cname, "ismodal": isModal, "smid": smid, "bkg": bkg };
2812    	}
2813    	
2814    	if (UTIL.isEmpty(json.id) && UTIL.isEmpty(json.name)) {
2815    		var json = GLO.ClientProfile.getClientFromProfile();
2816    	}
2817    	
2818    	var jmenu = j.find('.sa-easy-menu');
2819    	
2820    	if (jmenu.hasClass('menu-is-open')) {
2821    		jmenu.find('.drop-icon').click();
2822    	}
2823    	
2824    	_displayThrobberOverlay(j);
2825    	
2826    	if (isProfile) {
2827    		json.url = GLO.Link.Page.Provider.ClientProfile + '?IsPartial=1&cid=' + json.id + '&dt=' + UTIL.getDateString();			//if (json.ismodal) { json.url += '&IsPartial=1'; }
2828    	}
2829    	
2830    	return json;
2831    }
2832    
2833    function _displayThrobberOverlay(jContainer) {
2834    	var throbber = $('.loadingDiv').clone().find('img').addClass('loading-client-quick-view');
2835    	var jsonCSS = { "position": "absolute", "top": "0", "height": "100px", "margin-top": "60px", "z-index": "9999" };
2836    	
2837    	if (jContainer.attr('id') === 'simplemodal-container' || jContainer.closest('#simplemodal-container').length === 1) {
2838    		jsonCSS["margin-left"] = "-40px";
2839    	} else {
2840    		jsonCSS["margin-left"] = (jContainer.width() - 100)/2 + 'px';
2841    	}
2842    	
2843    	throbber.css(jsonCSS);
2844    	jContainer.prepend(throbber);
2845    }
2846    
2847    function _getProfileModal(hideSaveBtn) {
2848    	var jmodal = $('#simplemodal-container').css({ "background-color": "" });
2849    	
2850    	if (jmodal.length === 0) {
2851    		jmodal = $('.shadow-content0.loading-profile').removeClass('loading-profile');
2852    		//$('#doc3').css({ "width": "750px", "margin": "0px auto", "padding-top": "9px", "text-align": "left" });
2853    		$('#doc3').css({ "margin": "0px auto", "padding-top": "8px", "text-align": "left" });
2854    	}
2855    	
2856    	jmodal.find('.client-name-header').css({ "padding-top": "6px", "padding-bottom": "2px", "letter-spacing": "1px" }).find('>a').remove();
2857    	
2858    	if (hideSaveBtn) {
2859    		jmodal.find('#clientProfile-buttons .btnSave').addClass('hide');
2860    		jmodal.find('#basicUserInfo').addClass('hide');
2861    		jmodal.find('#client-staff').removeClass('hide').find('td').css({ "padding-top": "8px", "padding-bottom": "8px" });
2862    	} else {
2863    		jmodal.find('#clientProfile-buttons .btnSave').removeClass('hide');
2864    		jmodal.find('#client-staff').addClass('hide');
2865    		jmodal.find('#basicUserInfo').removeClass('hide');
2866    	}
2867    	
2868    	return jmodal;
2869    }
2870    
2871    function _cleanupEditModal() {
2872    	var jedit = $('#ba-EditAppointment').closest('#simplemodal-container');
2873    	
2874    	if (jedit.length === 1) {
2875    		UserPortal.Edit.cleanupModal(jedit, false);
2876    	}
2877    }
2878    
2879    _constructor.getDirections = function() {
2880    	var jsonClient = _constructor.getClientObject(true);
2881    	_cleanupEditModal();
2882    	_openDirections(true, jsonClient.smid, jsonClient.id, jsonClient.name, jsonClient.url);
2883    }
2884    
2885    _constructor.openApptSummary = function() {
2886    	var jsonClient = _constructor.getClientObject(true);
2887    	_cleanupEditModal();
2888    	_constructor.openCompleted(jsonClient.url, true, jsonClient.name, jsonClient.smid, ClientProfile.openApptSummaryCompleted);
2889    }
2890    
2891    _constructor.openProductHistory = function() {
2892    	var jsonClient = _constructor.getClientObject(true);
2893    	_cleanupEditModal();
2894    	_constructor.openCompleted(jsonClient.url, true, jsonClient.name, jsonClient.smid, ClientProfile.openProductHistoryCompleted);
2895    }
2896    
2897    _constructor.openProductHistoryByClient = function(btn, cid, cname, smid) {
2898		var jsonClient = { "id": cid, "name": cname, "ismodal": false };
2899		
2900		if (smid) {
2901			jsonClient.smid = smid;
2902		}
2903		
2904		jsonClient.url = GLO.Link.Page.Provider.ClientProfile + '?IsPartial=1&cid=' + jsonClient.id + '&dt=' + UTIL.getDateString() + '#view=product-history';
2905    	
2906    	if (btn) {
2907    		GLO.UI.Form.beginProcessing(btn);
2908    	}
2909    	
2910    	_constructor.openCompleted(jsonClient.url, false, jsonClient.name, jsonClient.smid, ClientProfile.openProductHistoryCompleted);
2911    }
2912    
2913    _constructor.openApptHistoryByClient = function(btn, cid, smid, start, end) {
2914		if (btn) {
2915    		GLO.UI.Form.beginProcessing(btn);
2916    	}
2917    	
2918		GLO.ClientHistory.open(cid, true, smid, start, end);
2919    }
2920    
2921    _constructor.openProfileVerifyPassword = function(cid, isSave) {
2922    	if (!isSave && !UTIL.isEmpty(_unlockPassword)) {
2923    		_constructor.verifyUnlockPassword(cid, _unlockPassword);
2924    		return;
2925    	}
2926    	
2927    	if (isSave) {
2928    		var msgLabel = 'Enter password to save client profile';
2929    	} else {
2930    		var msgLabel = 'Enter password to unlock client profile';
2931    	}
2932    	
2933    	var msg = '<label for="Unlock_Password_vc" style="font-weight: bold; color: white;">' + msgLabel + '</label>';
2934    	var input = '<input type="password" id="Unlock_Password_vc" style="width: 200px; letter-spacing: 2px;"/>';
2935    	var htm = '<div id="pop-unlock-client-profile" style="margin-bottom: 16px;">' + msg + input + '</div>';
2936		
2937		if (isSave) {
2938			var fnYes = function() {
2939				var jpop = $('#pop-unlock-client-profile').closest('.glopop');
2940				var pass = jpop.find('#Unlock_Password_vc').val();
2941				
2942				_constructor.setUnlockPassword(pass);
2943				GLO.Popup.close(jpop);
2944				
2945				var jclient = $('#displayProfile-Client');
2946				
2947				if (jclient.find('#Unlock_Password_vc').length === 0) {
2948					jclient.find('#basicUserInfo').prepend('<input type="password" id="Unlock_Password_vc" name="Unlock_Password_vc" class="hideX" value="' + pass + '"/>');
2949				}
2950				
2951				jclient.find('#clientProfile-save > a').click();
2952			};
2953		} else {
2954			var fnYes = function() {
2955				var jpop = $('#pop-unlock-client-profile').closest('.glopop');
2956				var pass = jpop.find('#Unlock_Password_vc').val();
2957				GLO.UI.Form.beginProcessing(jpop.find('.btnYes'));
2958				_constructor.verifyUnlockPassword(cid, pass);
2959			};
2960		}
2961		
2962		//var fnNo = function() { $('#ba-EditAppointment').find('#imgThrobber').remove(); };			//= for some reason this was not being called.
2963		
2964		var ojpop = GLO.Popup.Prompt.open(htm, 'Unlock Client Profile', fnYes);							//, fnNo
2965		var jpop = ojpop.getPopup();
2966		jpop.find('#val').remove();
2967		
2968		var jbtns = jpop.find('.pop-buttons');
2969		//jbtns.prepend('<span class="btnNo btn"> <a onclick="ClientProfile.openNoteHistory">View Notes</a> </span>');
2970		jbtns.find('.btnCancel').find('>a').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" });
2971		jbtns.find('.btnYes').css({ "width": "160px", "margin-right": "16px" }).find('> a').css({ "font-size": "16px", "font-weight": "bold" }).text('Unlock + View');
2972		
2973		setTimeout(function() {
2974			$('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove();
2975		}, 800);
2976		
2977		ojpop.saveOnEnter();
2978		jpop.find('#Unlock_Password_vc').focus();
2979    }
2980    
2981    _constructor.verifyUnlockPassword = function(cid, pass) {
2982    	var url = GLO.Link.Page.Provider.Home + 'ClientProfileWithPassword?cid=' + cid;
2983        var jd = { "unlockpassword": pass };
2984        
2985        if (ClientProfile.isFullPageProfile() || $('#simplemodal-container:visible').length) { url += '&IsPartial=1'; }
2986        
2987        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
2988            .success(function(data, textStatus, jqXHR) {
2989                var jmodal = $('#simplemodal-container');
2990                $('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove();
2991                
2992                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
2993                	_constructor.clearUnlockPassword();
2994                	GLO.UI.Form.resetProcessing();
2995                	GLO.Popup.Warning.open(data, 'Unlock Client Profile');
2996                } else {
2997                    GLO.Popup.close($('#pop-unlock-client-profile').closest('.glopop'));
2998                    GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
2999                    
3000                    _constructor.setUnlockPassword(pass);
3001                    
3002					var modalAlreadyOpen = (jmodal.length > 0);
3003					var smid = UTIL.coalesceInt(jmodal.find('.back-to-appointment').attr('smid'), UserPortal.Edit.scheduleMultiId);
3004					
3005					_loadClientProfile(modalAlreadyOpen, smid, data);
3006					$('form#client-form #Unlock_Password_vc').val(pass);
3007                }
3008            })
3009            .error(function(jqXHR, textStatus, errorThrown) {
3010                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3011            });
3012    }
3013    
3014    _constructor.openProfileOnly = function(isViewTags) {
3015    	if (GLO.Data.Staff.hideClientContact) {
3016    		var jsonClient = _constructor.getClientObject(true);
3017    		_constructor.openProfileVerifyPassword(jsonClient.id);
3018    		return;
3019    	}
3020    	
3021    	_constructor.openProfileOnly2(isViewTags);
3022    }
3023    
3024    _constructor.openProfileOnly2 = function(isViewTags) {
3025    	var jsonClient = _constructor.getClientObject(true);
3026    	var url = jsonClient.url;
3027    	var fn = function() {
3028    		ClientProfile.openProfileOnlyCompleted(null, isViewTags);
3029    	}
3030    	
3031    	_cleanupEditModal();
3032    	_constructor.openCompleted(url, true, jsonClient.name, jsonClient.smid, fn);
3033    }
3034    function _addDateRangeToUrl(url, fallbackStart, fallbackEnd) {
3035    	var start = null, end = null;
3036    	var jtbl = $('#client-appt-history').find('.appt-list-result tbody');
3037        
3038        if (jtbl.length) {
3039        	var dt1 = new Date(jtbl.find('tr:first').attr('appt_dt')), dt2 = new Date(jtbl.find('tr:last').attr('appt_dt'));
3040        	
3041        	if (!UTIL.isDate(start)) {
3042	        	if (dt1 < dt2) {
3043	        		start = dt1.toGloDate(true);
3044	        	} else {
3045	        		start = dt2.toGloDate(true);
3046	        	}
3047	        }
3048	        
3049	        if (!UTIL.isDate(end)) {
3050	        	if (dt1 > dt2) {
3051	        		end = dt1.toGloDate(true);
3052	        	} else {
3053	        		end = dt2.toGloDate(true);
3054	        	}
3055	        }
3056        } else {
3057        	var trs = $('#clientProfile-staff').find('tbody > tr');
3058        	
3059        	for (var i=0; i < trs.length; i++) {
3060        		var dtRecent = trs.eq(i).find('.appt-summary-recent-date').attr('recent_dt');
3061        		var dtUpcoming = trs.eq(i).find('.appt-summary-upcoming-date').attr('upcoming_dt');
3062        		
3063        		if (UTIL.isDate(dtRecent) || UTIL.isDate(dtUpcoming)) {
3064        			if (UTIL.isDate(dtRecent) && UTIL.isDate(dtUpcoming)) {
3065        				if (new Date(dtRecent) > new Date(dtUpcoming)) {
3066        					var dtEnd = dtRecent;
3067        				} else {
3068        					var dtEnd = dtUpcoming;
3069        				}
3070        			} else if (UTIL.isDate(dtRecent)) {
3071        				var dtEnd = dtRecent;
3072        			} else {
3073        				var dtEnd = dtUpcoming;
3074        			}
3075        			
3076        			end = new Date(dtEnd).toGloDate(true);
3077        			start = new Date(end).addDays(-365).toGloDate(true);
3078        			break;
3079        		}
3080        	}
3081        }
3082        
3083        if (UTIL.isDate(start) && UTIL.isDate(end)) {
3084        	if (url.indexOf('?') === -1 && url.indexOf('#') === -1) { url += '?'; }
3085        	url += '&start=' + start + '&end=' + end;
3086        } else if (UTIL.isDate(fallbackStart) && UTIL.isDate(fallbackEnd)) {
3087        	if (url.indexOf('?') === -1 && url.indexOf('#') === -1) { url += '?'; }
3088        	url += '&start=' + new Date(fallbackStart).toGloDate(true) + '&end=' + new Date(fallbackEnd).toGloDate(true);
3089        }
3090        
3091        return url
3092    }
3093    _constructor.gotoClientTicketHistory = function() {
3094    	var jsonClient = _constructor.getClientObject(true);
3095    	var h1 = jsonClient.name + ' ' + SA.Resource.TicketHistory;
3096    	var uri = 'reports/TicketHistory?client=' + jsonClient.id;
3097    	uri = _addDateRangeToUrl(uri, new Date().addDays(-365), new Date());
3098    	
3099    	var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML() + '</div>';
3100    	var jpop = GLO.Popup.Custom.openSimple(throbber, h1);
3101        GLO.Popup.Custom.singleButton(jpop, 'Close');
3102    	GLO.Uri.gotoUri(uri);
3103    }
3104    
3105    _constructor.openMessagesSent = function() {
3106    	var jsonClient = _constructor.getClientObject(true);
3107    	_constructor.openMessagesSentById(jsonClient.id, jsonClient.smid, jsonClient.bkg);
3108    }
3109    _constructor.openMessagesSentById = function(clientId, smid, bookingNumber) {
3110    	var url = GLO.Link.WebsiteDomain + 'message/history?ispartial=1&client=' + clientId + '&smid=' + smid;
3111		
3112		var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML() + '</div>';
3113		var h1 = 'Loading Messages sent to Client...';
3114        
3115    	if (!UTIL.isEmpty(bookingNumber)) {
3116    		h1 += ' for appointment P' + bookingNumber;
3117        }
3118        
3119        var ojpop = GLO.Popup.Custom.openSimple(throbber, h1, null, null, true);
3120        var jpop = ojpop.getPopup();
3121        GLO.Popup.Custom.singleButton(jpop, 'Close');
3122        
3123    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
3124            .success(function(data, textStatus, jqXHR) {
3125                jpop.addClass('quick-report').find('.msg').html(data); 		//jpop.css({ "z-index": "501" }).addClass('quick-report').find('.msg').html(data);
3126                var jh = jpop.find('#report-message-sent-history-header');
3127                var jrpt = jpop.find('table.tablesorter:visible');
3128                
3129                jpop.find('.pop-header h1').html(jh.html());
3130                jh.remove();
3131                
3132                UI.initTableSorter(jrpt);
3133				GLO.Report.CellSummary.initReport(jrpt, false, false);
3134				
3135                ojpop.realign();
3136                ojpop.realign();
3137                
3138                $('#simplemodal-container').find('#imgThrobber').remove();
3139                $('.loading-client-quick-view').remove();
3140                $('.shadow-content0.loading-profile').removeClass('loading-profile').find('#imgThrobber').remove();
3141                
3142                setTimeout(function() {
3143                	ojpop.realign();
3144                	ojpop.realign();
3145                }, 500);
3146            })
3147            .error(function(jqXHR, textStatus, errorThrown) {
3148                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3149                $('.shadow-content0.loading-profile').removeClass('loading-profile').find('#imgThrobber').remove();
3150                
3151                if (ojpop && ojpop.close) {
3152                	ojpop.close();
3153                }
3154            });
3155    }
3156    
3157    _constructor.openAppointmentActivity = function(event) {
3158    	var jsonClient = _constructor.getClientObject(true);
3159    	
3160    	if (UTIL.isNumber(UserPortal.Edit.apptId) && UserPortal.getEditAppt().find('tr.editServiceRow').length === 1) {
3161			GLO.MyAppts.openHistory2(UserPortal.Edit.apptId);
3162			return;
3163		}
3164		
3165    	_constructor.openAppointmentActivityById(jsonClient.id, jsonClient.smid);
3166    }
3167    _constructor.openAppointmentActivityById = function(clientId, smid, bookingNumber) {
3168    	var url = GLO.Link.WebsiteDomain + 'reports/RecentActivity?client=' + clientId + '&smid=' 
3168+ smid;
3169		
3170		var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML() + '</div>';
3171		var bkg = UTIL.coalesceString(bookingNumber, UserPortal.Edit.booking_nr, '');
3172    	var h1 = SA.Resource.AppointmentEditHistory;			//SA.Resource.RecentAppointmentUpdates;
3173        
3174    	if (!UTIL.isEmpty(bkg)) {
3175    		h1 = 'P' + bkg + ': ' + h1;
3176        }
3177        
3178        var ojpop = GLO.Popup.Custom.openSimple(throbber, h1, null, null, true);
3179        var jpop = ojpop.getPopup();
3180        GLO.Popup.Custom.singleButton(jpop, 'Close');
3181        
3182    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
3183            .success(function(data, textStatus, jqXHR) {
3184                jpop.addClass('quick-report').find('.msg').html(data); 		//jpop.css({ "z-index": "501" }).addClass('quick-report').find('.msg').html(data);
3185                jpop.find('.appt-list-search, .appt-list-line').remove();
3186                
3187                UI.initTableSorter( jpop.find('table.tablesorter:visible') );
3188                ojpop.realign();
3189                
3190                $('#simplemodal-container').find('#imgThrobber').remove();
3191                $('.loading-client-quick-view').remove();
3192            })
3193            .error(function(jqXHR, textStatus, errorThrown) {
3194                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3195            });
3196    }
3197    
3198    _constructor.openPaymentHistory = function(event) {
3199    	var jsonClient = _constructor.getClientObject(true);
3200    	var start = new Date(new Date().setMonth(new Date().getMonth() - 6)).toGloDate();
3201    	var url = 'reports/saleshistory?isfullpage=1&paymethod=0&client=' + jsonClient.id + '&start=' + start;
3202		
3203    	GLO.Report.CellSummary.gotoReport(url, null, event);
3204    }
3205    _constructor.openSalesDetail = function(event) {
3206    	var jsonClient = _constructor.getClientObject(true);
3207    	var start = new Date(new Date().setMonth(new Date().getMonth() - 6)).toGloDate();
3208    	var url = 'reports/saleshistory?isfullpage=1&client=' + jsonClient.id + '&start=' + start;
3209		
3210    	GLO.Report.CellSummary.gotoReport(url, null, event);
3211    }
3212    
3213    _constructor.openApptHistory = function() {
3214    	var jsonClient = _constructor.getClientObject();
3215    	_cleanupEditModal();
3216    	GLO.ClientHistory.open(jsonClient.id, true, jsonClient.smid);
3217    }
3218    
3219    _constructor.openNoteHistory = function() {
3220    	var jsonClient = _constructor.getClientObject();
3221    	_cleanupEditModal();
3222    	SA.Note.open(jsonClient.id, true, jsonClient.smid);
3223    }
3224    
3225    function _openCompleted(jmodal, smid) {
3226    	var h2 = jmodal.find('.client-name-header');
3227    	
3228    	if (jmodal.attr('id') == 'simplemodal-container') {
3229    		jmodal.find('.modalCloseImg').css({ "top": "4px", "right": "4px" });
3230    	}
3231    	
3232    	if (jmodal.length && UTIL.isNumber(smid)) { _addBackToEditAppt(h2, smid); }
3233    	
3234    	GLO.Mobile.simpleModalLoadComplete();
3235    	
3236    	if (GLO.Info.isMobile() && jmodal.hasClass('simplemodal-container')) {
3237    		jmodal.find('#clientProfile-buttons').removeClass('hide');
3238    		var height = jmodal.find('.simplemodal-wrap > div').height();
3239    		$.modal.update(height, innerWidth - 4);
3240    	}
3241    }
3242    
3243    function _addBackToEditAppt(h2, smid) {
3244    	if (innerWidth > 600) { var text = SA.Resource.BackToAppointment; } else { var text = SA.Resource.Back; }
3245    	
3246    	h2.prepend('<a class="back-to-appointment" smid="' + smid + '" onclick="UserPortal.Edit.get(null, ' + smid + ', true, ' + UserPortal.Edit.isCalendar + ', null, null, event)">< ' + text + '</a>');
3247    }
3248    
3249    _constructor.openApptSummaryCompleted = function(smid) {
3250    	var jmodal = _getProfileModal(true);
3251    	_openCompleted(jmodal, smid);
3252    }
3253    
3254    _constructor.openProductHistoryCompleted = function(smid) {
3255    	GLO.ClientProfile.displayProductHistory();
3256    	
3257    	var jmodal = _getProfileModal(true);
3258    	jmodal.find('#basicUserInfo').addClass('hide');
3259    	
3260    	_openCompleted(jmodal, smid);
3261    }
3262    
3263    _constructor.openProfileOnlyCompleted = function(smid, isViewTags) {
3264    	var jmodal = _getProfileModal(false);
3265    	_openCompleted(jmodal, smid);
3266    	_displayCreateDate(jmodal);
3267    	
3268    	if (isViewTags) {
3269    		GLO.Popup.closeIfExist($('#pop-edit-client-tag').closest('.glopop'));
3270    		
3271    		var jScrollableDiv = $('#simplemodal-container #extraUserInfo');
3272    		var jt = jmodal.find('#row-client-tag-manager');
3273    		
3274    		if (jScrollableDiv.length) {
3275    			jScrollableDiv[0].scrollTop += 350;		//scroll within popup
3276    		}
3277    		
3278    		UI.highlight(jt);
3279    	}
3280    }
3281    
3282    function _displayCreateDate(jmodal) {
3283    	var cdt = jmodal.find('#Create_dt').val();
3284    	
3285    	if (UTIL.isDate(cdt)) {
3286    		var createByStaffId = jmodal.find('#Create_By_Staff_id').val();
3287    		var createCode = jmodal.find('#Client_Create_cd').val();
3288    		var createDescription = UTIL.coalesceString(jmodal.find('#Client_Create_vc').val(), 'Created');
3289    		var createByLabel = '', htmLastLogin = '';
3290    		var dtLastLogin = jmodal.find('#Last_Login_dt').val();
3291    		
3292    		if (!UTIL.isEmpty(createByStaffId)) {
3293    			var createByStaffName = UTIL.cleanString(UserPortal.getStaffName(createByStaffId));
3294    			
3295    			if (UTIL.coalesceString(createByStaffName, 'Anyone') == 'Anyone') {
3296    				createByLabel = 'Profile ' + createDescription.replace('Create ', 'Created ').replace('By Staff', 'By Staff using').replace(' Web ', ' Website from ');
3297    			} else {
3298    				createByLabel = '<span style="font-size: inherit;" title="' + createDescription + '">Profile Created by ' + createByStaffName + '</span>';
3299    			}
3300    		} else if (createCode < 30 || createCode > 299) {
3301    			createByLabel = 'Profile ' + createDescription.replace('Create ', 'Created ').replace('By Client', 'By Client using').replace(' Web ', ' Website from ');
3302    		}
3303    		
3304    		var htm = '<div id="client-profile-create-date-row"><i>' + createByLabel + ' on </i><b>' + new Date(cdt).toGloDateString(false, true) + '</b></div>';
3305    		
3306    		if (UTIL.isDate(dtLastLogin)) {
3307    			htmLastLogin = '<div id="client-profile-last-login-row"><span>Last Login</span> <b>' + new Date(dtLastLogin).toGloDateString(false, true) + '</b></div>';
3308    		}
3309    		
3310    		jmodal.find('#client-body').append(htm + htmLastLogin);
3311    	}
3312    }
3313    
3314    _constructor.openApptHistoryCompleted = function(smid) {
3315    	var jmodal = $('#client-appt-history').closest('#simplemodal-container, .shadow-content0');
3316    	
3317    	setTimeout(function() {
3318    		$('#ui-datepicker-div:visible').css('display', 'none');
3319    	}, 400);
3320    	
3321    	_openCompleted(jmodal, smid);
3322    }
3323    
3324    _constructor.openNoteHistoryCompleted = function(smid) {
3325    	var jmodal = $('#note-history').closest('#simplemodal-container, .shadow-content0');
3326    	_openCompleted(jmodal, smid);
3327    }
3328    
3329    _constructor.getDropIcon = function(isEditAppt) {
3330    	if (GLO.Info.roleType === undefined) { GLO.Info.init(); }
3331    	if (GLO.Info.roleType < 100) { return ''; }
3332    	//if (GLO.Info.isMobile()) { return ''; }			//= disabled TEMPORARILY!!!
3333    	
3334    	var dropIcon = '<li style="display: inline; float: none;"> <i class="drop-icon" onclick="UserPortal.Edit.openClientMenu()">&#9660;</i> </li>';
3335    	var menu = '<ul>';
3336    	
3337    	if (GLO.Info.roleType > 159) { menu += '<li><a class="no-animate" onclick="ClientProfile.openApptSummary()" title="' + SA.Resource.GroupServicesByStaff + '">' + SA.Resource.AppointmentSummary + '</a></li>'; }
3338    	if (GLO.Info.roleType != 200) { menu += '<li><a class="no-animate" onclick="ClientProfile.openApptHistory()" title="' + SA.Resource.AppointmentsByDateRange + '">' + SA.Resource.AppointmentHistory + '</a></li>'; }
3339    	if (GLO.Info.roleType > 159 && GLO.Info.providerPackage !== 1) { menu += '<li><a class="no-animate" onclick="ClientProfile.openProductHistory()" title="' + SA.Resource.ProductPurchases + '">' + SA.Resource.ProductHistory + '</a></li>'; }
3340    	
3341    	if (GLO.Data.Staff.clientNoteAccess < 400) {
3342    		menu += '<li><a class="no-animate" onclick="ClientProfile.openNoteHistory()" title="' + SA.Resource.DisplayAllClientNotes + '">' + SA.Resource.NoteHistory + '</a></li>';
3343    	}
3344    	
3345    	if (GLO.Info.roleType > 159 && GLO.Info.roleType != 200) {
3346    		menu += '<li><a class="no-animate" onclick="ClientProfile.openPaymentHistory()" title="">' + SA.Resource.PaymentHistory + '</a></li>';
3347    		menu += '<li><a class="no-animate" onclick="ClientProfile.openSalesDetail()" title="">' + SA.Resource.SalesDetail + '</a></li>';
3348    		menu += '<li><a class="no-animate" onclick="ClientProfile.gotoClientTicketHistory()" title="">' + SA.Resource.TicketHistory + '</a></li>';
3349    		menu += '<li><a class="no-animate" onclick="ClientProfile.openProfileOnly()" title="">' + SA.Resource.Client + ' ' + SA.Resource.Profile + '</a></li>';
3350    		
3351    		if (GLO.Info.roleType > 219 && !isEditAppt) {
3352	    		menu += '<li><a class="no-animate" onclick="GLO.ClientProfile.deleteClient()" title="">' + SA.Resource.DeleteOrMerge + ' ' + SA.Resource.Profile + '</a></li>';
3353	    	}
3354    		
3355    		if (GLO.Data && GLO.Data.Staff && !GLO.Data.Staff.hideClientContact && GLO.Data.Staff.clientNoteAccess < 10) {
3356    			menu += '<li><a class="no-animate" onclick="ClientProfile.openMessagesSent()">' + SA.Resource.MessagesSent + '</a></li>';
3357    		}
3358    		
3359    		menu += '<li><a class="no-animate" onclick="ClientProfile.openAppointmentActivity(true)" title="" style="color: deeppink;">' + SA.Resource.AppointmentUpdates + '</a></li>';
3360    	}
3361    	
3362    	if (isEditAppt) {
3363    		if (!GLO.Info.isMobile(true)) {
3364    			menu += '<li><a class="no-animate" onclick="UserPortal.Edit.print()" style="color: rgba(255, 20, 140,.6);">' + SA.Resource.Print + ' ' + SA.Resource.Appointment + '</a></li>';
3365    		}
3366    		
3367    		if (GLO.Info.roleType > 209 && !UTIL.isEmpty(UserPortal.Edit.clientId)) {
3368    			menu += '<li><a class="no-animate" onclick="UserPortal.Edit.removeClient()" title="Remove client from this appointment" style="color: rgba(255, 20, 140,.6);">' + SA.Resource.Remove + ' ' + SA.Resource.Client + '</a></li>';
3369    		}
3370    		
3371    		if (GLO.Provider.isValidNextBillDate() && GLO.Info.providerPackage != 4) {			//GLO.Info.isMobile() && 
3372	    		menu += '<li><a class="no-animate" onclick="UserPortal.StaffNote.open(false)" style="color: rgba(255, 20, 140,.6);">Add Note/Images</a></li>';
3373	    	}
3374    	}
3375    	
3376    	if (GLO.Popup.Profile.isDisplayNewClientForm(GLO.Data.provider.new_client_address_cd) || GLO.Data.provider.outcall_type_cd > 0) {
3377    		menu += '<li><a class="no-animate" onclick="ClientProfile.getDirections()">' + SA.Resource.GetDirections + '</a></li>';
3378    	}
3379		
3380		return '<ul class="sa-easy-menu" style="display: inline;">' + dropIcon + menu + '</ul> </ul>';
3381    }
3382	
3383    return _constructor;
3384})();
3385
3386GLO.ReputationReport = (function() {
3387    function _constructor(name) { }
3388
3389    _constructor.init = function() { 
3390        GLO.Info.init();
3391        
3392        var j = $('#client-appt-history');
3393        var jtbl = j.find('table.tablesorter');
3394        // var sortOrder = _getSortOrder(jtbl);
3395        
3396        // _setHeader(j);
3397        
3398        // UI.initTableSorter(jtbl, sortOrder);
3399        // UI.setAccessKey('#client-appt-history', GLO.ClientHistory.search);
3400        
3401        var jhead = j.find('.appt-list-search');
3402        GLO.Report.Template.initDateRange(jhead, true);
3403
3404		const urlParams = new URLSearchParams(window.location.search);
3405		var staff_id = urlParams.get('staff');
3406		var service_id = urlParams.get('service');
3407
3408		if (staff_id != null) {
3409			$('#Staff_id').val(staff_id).attr('selected','selected');
3410		}
3411		if (service_id != null) {
3412			$('.Service_Filter').val(service_id).attr('selected','selected');
3413		}
3414        // GLO.Report.enableFullPageCheck();
3415        // GLO.Report.CellSummary.initReport(jtbl, true);
3416    }
3417
3418    _constructor.search = function(thisBtn) {
3419        var j = $('#client-appt-history');
3420        var begin = UTIL.fromSADate(j.find('#report-start').val(), true, true);
3421        var end = UTIL.fromSADate(j.find('#report-end').val(), true, true);
3422        
3423        if (new Date(begin).getTime() > new Date(end).getTime() ) {
3424            new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>');
3425            return;
3426        }
3427
3428        var svc = j.find('.Service_Filter').val();
3429        var staff = j.find('#Staff_id').val();
3430
3431        if (!UTIL.isDate(begin)) { begin = ''; }
3432        if (!UTIL.isDate(end)) { end = ''; }
3433        if (UTIL.isEmpty(svc)) { svc = ''; }
3434        if (UTIL.isEmpty(staff)) { staff = ''; }
3435        
3436        var qs = 'id=' + '&begin=' + begin + '&end=' + end + '&service=' + svc + '&staff=' + staff;
3437        var url = GLO.Link.Page.Provider.Home + 'ReputationReviewReport?' + qs;
3438        thisBtn = $(thisBtn).parent().css({ "top":"1px" });
3439        // GLO.UI.Form.beginProcessing(thisBtn);
3440        
3441        setTimeout(function() { window.location.href = url; },50 );
3442
3443    }
3444    
3445	_constructor.setOverallRatings = function(positivePercentage) {
3446		// Clamp values between 0 and 100
3447		if (positivePercentage < 0) positivePercentage = 0;
3448		if (positivePercentage > 100) positivePercentage = 100;
3449
3450		const negativePercentage = 100 - positivePercentage;
3451
3452		const positiveDiv = document.getElementById('positive-div');
3453		const negativeDiv = document.getElementById('negative-div');
3454
3455		// Set Widths
3456		positiveDiv.style.width = positivePercentage + '%';
3457		negativeDiv.style.width = negativePercentage + '%';
3458
3459		// Function to generate the HTML content
3460		const getContent = (percent, label) => {
3461			// If the percentage is very small (e.g. < 15%), hide text to prevent ugliness
3462			if (percent < 15) return ''; 
3463			return `
3464				<span class="percent-text">${percent}%</span>
3465				<span class="label-text">${label}</span>
3466			`;
3467		};
3468
3469		// Inject HTML using innerHTML
3470		positiveDiv.innerHTML = getContent(positivePercentage, "Positive");
3471		negativeDiv.innerHTML = getContent(negativePercentage, "Negative");
3472	}
3473
3474	return _constructor;
3475})();
3476
3477GLO.ClientHistory = (function() {
3478    function _constructor(name) { }
3479    var _clientId;
3480
3481    _constructor.init = function() { 
3482        GLO.Info.init();
3483        
3484        var j = $('#client-appt-history');
3485        var jtbl = j.find('table.tablesorter');
3486        var sortOrder = _getSortOrder(jtbl);
3487        
3488        _setHeader(j);
3489        
3490        UI.initTableSorter(jtbl, sortOrder);
3491        UI.setAccessKey('#client-appt-history', GLO.ClientHistory.search);
3492        
3493        var jhead = j.find('.appt-list-search');
3494        GLO.Report.Template.initDateRange(jhead, true);
3495        GLO.Report.enableFullPageCheck();
3496        GLO.Report.CellSummary.initReport(jtbl, true);
3497    }
3498    
3499    function _getSortOrder(jtbl) {
3500    	var arr = [1,2];
3501    	
3502    	if (jtbl.find('.column-location:visible').length > 0) {
3503    		++arr[0];
3504    		++arr[1];
3505    	}
3506    	
3507    	if (jtbl.find('.column-staff:visible').length > 0) {
3508    		++arr[0];
3509    		++arr[1];
3510    	}
3511    	
3512    	return arr;
3513    }
3514	
3515	function _setHeader(jClient) {
3516        var rows = jClient.find('table.tablesorter tbody tr');
3517        
3518        if (rows.length === 0) {
3519        	var ctext = SA.Resource.NoAppointments;
3520        	_clientId = jClient.find('h2#clientName').attr('client_id');
3521        } else {
3522        	var ctext = rows.eq(0).attr('client_vc');
3523        	_clientId = rows.eq(0).attr('client_id');
3524        }
3525        
3526        var clientHeader = '<span id="inner-client-name">' + ctext + '</span>';
3527        var Total_Appt_nr = rows.length;
3528
3529        if (!UTIL.isEmpty(Total_Appt_nr)) { 
3530            if (Total_Appt_nr == 1) {
3531                var appt_str = ' ' + SA.Resource.Appointment.toLowerCase();
3532            } else {
3533                var appt_str = ' ' + SA.Resource.Appointments.toLowerCase();
3534            }
3535        }
3536        
3537        clientHeader += ClientProfile.getDropIcon();
3538        //clientHeader += '<a href="/provider/clientProfile?cid=' + _clientId + '" class="quietest">' + SA.Resource.SeeProfile + '</a>';
3539        clientHeader += '<a onclick="GLO.Uri.gotoUri(\'provider/clientProfile?cid=' + _clientId + '\', this, event, true)" class="quietest">' + SA.Resource.SeeProfile + '</a>';
3540        
3541        if (GLO.Info.roleType > 159 && GLO.Info.roleType != 200) {
3542        	clientHeader += '<a onclick="GLO.ClientHistory.gotoClientTicketHistory(this, event)" class="quietest ticket-history-client-link">' + SA.Resource.TicketHistory + '</a>';
3543        }
3544        
3545        $('h2#clientName').html(clientHeader);
3546        _constructor.loadDataComplete();
3547    }
3548    _constructor.gotoClientTicketHistory = function(element, event) {
3549    	var jfilter = $('#client-appt-history').find('.appt-list-search');
3550        var sid = UTIL.cleanString(jfilter.find('#Staff_id').val()), sgid = UTIL.cleanString(jfilter.find('.Service_Filter').val());
3551        var start = UTIL.fromSADate(jfilter.find('#report-start').val(), true, true);
3552        var end = UTIL.fromSADate(jfilter.find('#report-end').val(), true, true);
3553        var uri = 'reports/TicketHistory?client=' + _clientId + '&sfilter=' + sid;
3554        
3555        var jtbl = $('#client-appt-history').find('.appt-list-result tbody');
3556        var dt1 = new Date(jtbl.find('tr:first').attr('appt_dt')), dt2 = new Date(jtbl.find('tr:last').attr('appt_dt'));
3557        
3558        if (!UTIL.isDate(start)) {
3559        	if (dt1 < dt2) {
3560        		start = dt1.toGloDate(true);
3561        	} else {
3562        		start = dt2.toGloDate(true);
3563        	}
3564        }
3565        
3566        if (!UTIL.isDate(end)) {
3567        	if (dt1 > dt2) {
3568        		end = dt1.toGloDate(true);
3569        	} else {
3570        		end = dt2.toGloDate(true);
3571        	}
3572        }
3573        
3574        if (sgid.length > 2 && sgid.substring(0,2) == 'sg') { uri += '&service-group=' + sgid.substring(2); }
3575        if (UTIL.isDate(start)) { uri += '&start=' + start; }
3576        if (UTIL.isDate(end)) { uri += '&end=' + end; }
3577        
3578    	GLO.Uri.gotoUri(uri, element, event);
3579    }
3580    
3581	_constructor.open = function(cid, useCurrentModal, openFromSmid, start, end) {
3582		var url = location.protocol + '//' + location.host + '/provider/appointment/history/client/' + cid;
3583		
3584		if (useCurrentModal) { url = GLO.Uri.addQueryKeyAndValue(url, 'ispartial=1&isload=1'); }
3585		if (UTIL.isDate(start)) { url = GLO.Uri.addQueryKeyAndValue(url, 'start=' + start); }
3586        if (UTIL.isDate(end)) { url = GLO.Uri.addQueryKeyAndValue(url, 'end=' + end); }
3587		
3588		var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
3589            .success(function(data, textStatus, jqXHR) {
3590            	var jpop = $('#pop-help-cell-summary, #member-period-report').closest('.glopop');
3591            	
3592            	if (jpop.length > 0) {
3593            		GLO.Popup.close(jpop);
3594            	}
3595            	
3596            	if (useCurrentModal) {
3597            		var throbber = $('.loading-client-quick-view').remove();
3598            		var jcontainer = $('#simplemodal-container');
3599            		
3600            		if ($('.shadow-content0 .client-name-header').length > 0) {
3601            			if (jcontainer.length > 0) { $.modal.close(); }
3602            			
3603            			jcontainer = $('.shadow-content0').html(data);
3604            			useCurrentModal = false;
3605            		} else if (jcontainer.length === 1) {
3606            			jcontainer.find('> .simplemodal-wrap').html(data);
3607            		} else if (throbber.length === 1) {
3608            			jcontainer = $('.shadow-content0').html(data);
3609            			useCurrentModal = false;
3610            		} else if (jcontainer.length === 0) {
3611            			$(data).modal();
3612		    			$('#simplemodal-container').find('.simplemodal-data').css({ "padding": "0" });
3613            		}
3614		    	}
3615            	
3616            	GLO.ClientHistory.init();
3617                
3618                if (useCurrentModal) {
3619                	var jmodal = $('#simplemodal-container').css({ "padding": "0", "background": "" });
3620                	var height = jmodal.find('.simplemodal-wrap > div').height();
3621                	
3622                	if (innerWidth > 760) {				//if (!GLO.Info.isMobile()) { $.modal.update(620, 760); }
3623		    			$.modal.update(height, 750);
3624		    		} else {
3625		    			jmodal.css({ "width": "inherit", "height": "inherit" });
3626		    			$.modal.update(height, null);
3627		    		}
3628                	
3629                	jmodal.find('.client-name-header').find('>a').remove();
3630                	jmodal.find('#client-appt-history #appt-history-footer').css({ "position": "absolute", "bottom": "0" });
3631                	jmodal.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
3632                	
3633                	ClientProfile.openApptHistoryCompleted(openFromSmid);
3634                }
3635                
3636                _constructor.loadDataComplete();
3637        	})
3638            .error(function(jqXHR, textStatus, errorThrown) {
3639                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3640            });
3641	}
3642	
3643    _constructor.search = function(thisBtn) {
3644        var j = $('#client-appt-history');
3645        var begin = UTIL.fromSADate(j.find('#report-start').val(), true, true);
3646        var end = UTIL.fromSADate(j.find('#report-end').val(), true, true);
3647        
3648        if (new Date(begin).getTime() > new Date(end).getTime() ) {
3649            new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>');
3650            return;
3651        }
3652
3653        var svc = j.find('.Service_Filter').val();
3654        var staff = j.find('#Staff_id').val();
3655
3656        if (!UTIL.isDate(begin)) { begin = ''; }
3657        if (!UTIL.isDate(end)) { end = ''; }
3658        if (UTIL.isEmpty(svc)) { svc = ''; }
3659        if (UTIL.isEmpty(staff)) { staff = ''; }
3660        
3661        var qs = 'id=' + _clientId + '&begin=' + begin + '&end=' + end + '&service=' + svc + '&staff=' + staff;
3662        var url = GLO.Link.Page.Provider.Home + 'ClientHistory?ispartial=1&' + qs;
3663        thisBtn = $(thisBtn).parent().css({ "top":"1px" });
3664        GLO.UI.Form.beginProcessing(thisBtn);
3665        
3666        setTimeout(function() { GLO.Report.TicketHistory.changeUrl(qs, 'Client Appointment History'); }, 50);
3667        
3668        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
3669                .success(function(data, textStatus, jqXHR) {
3670                    GLO.UI.Form.resetProcessing();
3671                    thisBtn.css({ "top":"12px" });
3672                    
3673                    var jd = $(data);
3674                    var jtbl = jd.find('.tablesorter');
3675                    var jf = jd.find('#appt-history-footer');
3676                    
3677                    var jrpt = $('.appt-list-result').html(jtbl);
3678                    var sortOrder = _getSortOrder(jrpt);
3679                    
3680                    UI.initTableSorter( $('#client-appt-history table.tablesorter'), sortOrder);
3681                    
3682                    if (jf.length) {
3683                    	$('.appt-list-result').append(jf);
3684                    }
3685                    
3686                    _constructor.loadDataComplete();
3687                })
3688                .error(function(jqXHR, textStatus, errorThrown) {
3689                    thisBtn.css({ "top":"12px" });
3690                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3691                });
3692    }
3693    
3694    _constructor.loadDataComplete = function() {
3695    	var j = $('#client-appt-history').find('.appt-list-result');
3696    	var jrows = j.find('table.apptList tbody tr');
3697    	
3698    	if (jrows.length === 100 && j) {
3699    		if ($('#client-appointment-history-table-note').length > 0) { return; }
3700    		
3701    		var htm = '<div id="client-appointment-history-table-note" style="">'
3702    				+ '<b>Latest 100 services displayed</b>'
3703    				+ '<span>use search filter above to see more services</span>'
3704    			+ '</div>';
3705    		
3706    		j.prepend(htm);
3707    	}
3708    	
3709    	GLO.Report.CellSummary.initReport(j, true);
3710    	GLO.Report.initIcons(j);
3711    	
3712    	GLO.Report.hideEmptyColumn(j, 'column-location');
3713    	GLO.Report.hideEmptyColumn(j, 'price-column');
3714    }
3715    
3716    return _constructor;
3717})();
3718
3719GLO.Recur = (function() {
3720    function _conRecur() { }
3721    
3722    _conRecur.init = function(isAll) {
3723        var j = $('#client-appt-history');
3724        _loadData(j);
3725        
3726        j.find('#item-row-box-all').click(GLO.Recur.selectAll);
3727        UI.setAccessKey('#client-appt-history', GLO.Recur.search);
3728        
3729        j.find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 });
3730        j.find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
3731        
3732        GLO.Report.enableFullPageCheck();
3733        
3734        if (!UTIL.parseBool(isAll)) {
3735        	var start = UTIL.coalesceDate(GLO.Uri.url('start'), new Date()).toGloDate();
3736        	var end = UTIL.coalesceDate(GLO.Uri.url('end'));
3737        	
3738        	j.find('.Begin_dt').val(start);
3739        	
3740        	if (UTIL.isDate(end)) {
3741        		j.find('.End_dt').val( new Date(end).toGloDate() );
3742        	}
3743        }
3744    }
3745
3746    function _loadData(jClient) {
3747        var rows = jClient.find('table.tablesorter tbody tr');
3748        var Total_Appt_nr = rows.length;
3749        
3750        if (UTIL.coalesceInt(Total_Appt_nr, 0) > 0 || !rows.hasClass('noResults')) { 
3751            if (Total_Appt_nr == 1) {
3752                var appt_str = ' ' + SA.Resource.Appointment.toLowerCase();
3753            } else {
3754                var appt_str = ' ' + SA.Resource.Appointments.toLowerCase();
3755            }
3756
3757            var msg = Total_Appt_nr + " <span style='font-size: 77%; color: #ccc;'>" + appt_str + "</span>";
3758            $('#xxx-client-header-switch-view').html(msg);
3759        }
3760        
3761        var jtbl = jClient.find('table.tablesorter');
3762        //var sortOrder = _getSortOrder(jtbl);
3763        UI.initTableSorter(jtbl, null, true);
3764    }
3765    
3766    function _getSortOrder(jtbl) {
3767    	var arr = [2,3];
3768    	
3769    	if (jtbl.find('.recur-column-staff').length > 0) {
3770    		++arr[0];
3771    		++arr[1];
3772    	}
3773    	
3774    	return arr;
3775    }
3776	
3777    _conRecur.selectAll = function() {
3778        var jcheckbox = $(this);
3779        var isChecked = jcheckbox.prop('checked');
3780        var tbl = jcheckbox.closest('table').find('tbody');
3781        
3782        var boxes = tbl.find('.item-row-box:visible input:checkbox');
3783        
3784        for (var i=0; i < boxes.length; i++) {
3785            boxes.eq(i).prop('checked', isChecked);
3786        }
3787        
3788        //setTimeout(function() { jcheckbox.prop('checked', isChecked); }, 200);			//= for some reason the 'all' checkbox doesn't stay checked.
3789    }
3790    
3791    _conRecur.addMore = function() {
3792    	$('#client-appt-history').find('tr:last').find('.apptListDate a').click();
3793    	
3794    	setTimeout(function() {
3795    		$('#simplemodal-container #ba-EditAppointment #ba-EditRecur').addClass('hide');
3796    		
3797    		UserPortal.Edit.displayRecur();
3798    		UserPortal.Edit.schedule_recur_id = $('#client-appt-history #clientName').attr('schedule_recur_id');
3799    	}, 900);
3800    }
3801    
3802    _conRecur.massDelete = function() {
3803    	var jbox = $('#client-appt-history').find('table.tablesorter tbody tr input:checked');
3804    	var apptCount = 0, xml = '<ul class="hide">';
3805    	
3806    	for (var i=0; i < jbox.length; i++) {
3807    		++apptCount;
3808    		xml += '<dl schedule_id="' + jbox.eq(i).closest('tr').attr('id') + '"/>';
3809    	}
3810    	
3811    	if (apptCount === 0) {
3812    		new GLO.Popup.Warning(SA.Resource.PleaseClickBoxNextToAppt);
3813    		return;
3814    	}
3815    	
3816    	xml += '</ul>';
3817    	
3818    	var htmPass = '', css = 'width: 90%; height: 40px; margin-left: 11px; line-height: 150%;';
3819    	
3820    	if (GLO.Info.isMobile()) { var pcss = 'margin-right: 9px; color: Red;'; } else { var pcss = 'color: Red;'; }
3821    	
3822    	if (GLO.Data && GLO.Data.Staff && GLO.Data.Staff.require_password_appointment_edit_fl) {
3823    		htmPass = '<div id="appointment-edit-password"><label for="Edit_Password_vc">Password</label><input id="Edit_Password_vc" type="password" class="required" autocomplete="new-password"></div>';
3824    	}
3825    	
3826    	var htm = '<form><p style="' + pcss + '">' + SA.Resource.DeleteWarning + ' ' + apptCount + ' ' + SA.Resource.Appointment.toLowerCase() + '?</p>'
3827    				+ xml
3828                    + '<textarea id="Delete_Reason_vc" name="Delete_Reason_vc" maxlength="2000" rows="2" placeholder="' + SA.Resource.DeleteReason + '" style="' + css + '"></textarea>'
3829                    + htmPass
3830                + '</form>';
3831    	
3832		GLO.Popup.Confirm(htm, _conRecur.massDeleteConfirmed);
3833    }
3834    
3835    function _requirePasswordOnDelete(editPassword) {
3836    	if (GLO.Data && GLO.Data.Staff && GLO.Data.Staff.require_password_appointment_edit_fl && UTIL.isEmpty(editPassword)) {
3837        	var msg = 'Please Enter Your Password to Delete Appointments';
3838        	GLO.Popup.Warning.open(msg, 'Password Required');
3839            return true;
3840        }
3841        
3842        return false;
3843    }
3844    
3845    _conRecur.massDeleteConfirmed = function(jform) {
3846        var editPassword = jform.find('#Edit_Password_vc').val();
3847        var reason = UTIL.htmlEncode(jform.find('#Delete_Reason_vc').val());
3848        var xml = UTIL.htmlEncode(jform.find('ul').outerHTML());
3849        
3850        if (_requirePasswordOnDelete(editPassword)) { return; }
3851        
3852        var j = $('#client-appt-history');
3853        var recurId = j.find('#clientName').attr('schedule_recur_id');
3854        
3855        var begin = j.find('.Begin_dt').val().replace(/\//g, '-');
3856        var end = j.find('.End_dt').val().replace(/\//g, '-');
3857        
3858        if (new Date(begin).getTime() > new Date(end).getTime() ) {
3859            var oj = new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>');
3860            oj.getPopup().find('.pop-buttons').css({ "width": "320px" });
3861            return;
3862        }
3863        
3864        var url = GLO.Link.WebsiteDomain + 'schedule/massDelete';
3865        var jd = { "schedule_recur_id": recurId, "xml": xml, "delete_reason_vc": reason, "edit_password_vc": editPassword };
3866        
3867        var ojProcessing = new GLO.Popup.Processing(SA.Resource.DeletingAppointments + '...');		//var thisBtn = $('#btnMassDeleteAppt').parent().css({ "top":"1px" }); GLO.UI.Form.beginProcessing(thisBtn);
3868        
3869        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
3870                .success(function(data, textStatus, jqXHR) {
3871                    ojProcessing.close();				//GLO.UI.Form.resetProcessing(); thisBtn.css({ "top":"12px" });
3872                    
3873                    if (!UTIL.isEmpty($(data).attr('error_cd'))) {
3874                    	new GLO.Popup.Warning(data);
3875                    } else {
3876	                    $('.appt-list-result').html(data);
3877	                    _loadData(j);
3878                    }
3879                })
3880                .error(function(jqXHR, textStatus, errorThrown) {
3881                    thisBtn.css({ "top":"12px" });
3882                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3883                });
3884    }
3885    
3886    _conRecur.search = function(thisBtn) {
3887        var j = $('#client-appt-history');
3888        var begin = j.find('.Begin_dt').val().replace(/\//g, '-');
3889        var end = j.find('.End_dt').val().replace(/\//g, '-');
3890        
3891        if (new Date(begin).getTime() > new Date(end).getTime()) {
3892            new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>');
3893            return;
3894        //} else if (UTIL.isEmpty(begin) && UTIL.isEmpty(end)) {
3895        //	new GLO.Popup.Warning('Please enter a begin and end date');
3896        //    return;
3897        }
3898
3899        if (UTIL.isEmpty(begin)) { begin = ''; }
3900        if (UTIL.isEmpty(end)) { end = ''; }
3901        
3902        var schedule_recur_id = j.find('#clientName').attr('schedule_recur_id');
3903        var url = GLO.Link.WebsiteDomain + 'schedule/recur?issearch=1&schedule_recur_id=' + schedule_recur_id + '&start=' + begin + '&end=' + end;
3904        
3905        thisBtn = $(thisBtn).parent().css({ "margin-top":"1px" });
3906        GLO.UI.Form.beginProcessing(thisBtn);
3907
3908        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
3909                .success(function(data, textStatus, jqXHR) {
3910                    GLO.UI.Form.resetProcessing();
3911                    thisBtn.css({ "margin-top":"15px" });
3912
3913                    $('.appt-list-result').html(data);
3914                    _loadData(j);
3915                })
3916                .error(function(jqXHR, textStatus, errorThrown) {
3917                    GLO.UI.Form.resetProcessing();
3918                    thisBtn.css({ "top":"12px" });
3919                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
3920                });
3921    }
3922
3923    return _conRecur;
3924})();
3925
3926var Search = (function() {
3927    function _constructor(name) { }
3928    var debug = false;
3929
3930    _constructor.inProgress = false;
3931
3932    _constructor.init = function(el, src, searchFunction, hasElementStyling) {
3933        el = $(el);
3934        
3935        if (el.length === 0) { return; }
3936        
3937        el.autocomplete({
3938            source: src,
3939            minLength: 2,
3940            select: function(event, ui) {
3941                _constructor.inProgress = true;
3942                el = _switchFromButtonBasedSearch(el);
3943                var val = ui.item.value;
3944                
3945                if (!UTIL.isEmpty(ui.item.gift_number_vc)) {
3946	            	el.attr('giftId', ui.item.id);
3947	            } else if (ui.item.id.substring(0, 1) === "I") {
3948                    el.attr('inventoryId', ui.item.id);
3949                } else if (ui.item.id.substring(0, 1) === "P") {
3950                    el.attr('bookingId', ui.item.id);
3951                } else if (ui.item.id.substring(0, 1) === "O") {
3952                    el.attr('shipmentId', ui.item.id);
3953                } else if (val.substring && val.length > 1 && (val.substring(0, 1) === "P" && UTIL.isNumber(val.substring(1))) || (val.substring(0, 2) === "#P") && UTIL.isNumber(val.substring(2))) {
3954                	_selectTicketNumber(ui.item);
3955                } else {
3956                    el.attr('clientId', ui.item.id);
3957                }
3958
3959                //if (debug) { log(ui.item ? "Selected: " + ui.item.value + " ; ID: " + ui.item.id : "Nothing selected, input was " + this.value); }
3960                $('#search-overlay').remove();
3961                
3962                if (!UTIL.isEmpty(ui.item.gift_number_vc)) {
3963                	if ($('#simplemodal-container:visible').length > 0) { return; }       //~ modal popup is open so shouldn't be here.
3964                	
3965                	UserPortal.Price.GiftCard.openEdit(ui.item.id, ui.item.gift_number_vc, ui.item.gift_balance_mn);
3966                	
3967                	Search.resetSearchBox();
3968                	setTimeout(Search.wait, 500);
3969                } else if (UTIL.isEmpty(searchFunction)) {
3970                    _constructor.run(ui.item.value, ui.item.id, ui.item);
3971                    setTimeout(Search.wait, 500);
3972                }
3973            },
3974            open: function(){
3975                $(this).autocomplete('widget').css("z-index", "5900 !important");
3976                
3977                return false;
3978            },
3979        });
3980        
3981        if (el.length) {		//hasElementStyling
3982        	el.data("ui-autocomplete")._renderItem = function(ul, item) {
3983	            var cssClass = "", cssStyle = "", title = "", aStyle = '';
3984	            
3985	            if (!UTIL.isEmpty(item.gift_number_vc)) {
3986	            	cssClass = " class='item-gift'";
3987	            } else if (item.id.substring(0,1) === 'I') {
3988	            	cssClass = " class='item-inventory'";
3989	            }
3990	            
3991	            if (item.location_name_vc && item.location_name_vc.length > 1) { title = " title='" + item.location_name_vc + "'"; }
3992	            
3993	            if (item.background_rgb_vc && item.background_rgb_vc.length > 4) {
3994	            	cssStyle = " style='background-color: rgb(" + item.background_rgb_vc + ");'";
3995	            	aStyle = " style='color: white;'";
3996	            }
3997	            
3998	            return $("<li" + cssClass + cssStyle + title + "></li>")
3999			        .data("ui-autocomplete-item", item)
4000			        .append("<a" + aStyle + ">" + item.label + "</a>")
4001			        .appendTo(ul);
4002	        };
4003        }
4004        
4005        el.focus(function() {
4006            $(this).parent().addClass("quick-search");
4007        });
4008
4009        //el.blur(function() { /* $(this).parent().removeClass("quick-search"); */ });
4010
4011        _constructor.wait = function() {		//this function simply mimicks the time of an ajax call, so the enter access key works.
4012            _constructor.inProgress = false;
4013        }
4014    }
4015    
4016    function _selectTicketNumber(uiItem) {
4017    	var msg = "Looking up Ticket " + UTIL.coalesceString(uiItem.label, ui
4017Item.value) + "...";
4018    	var jsonPostOpen = { "processing_message_vc": msg, "processing_header_vc": "Opening Ticket" };
4019    	
4020    	if (uiItem.appt_count_sr > 0) {
4021    		UserPortal.Edit.get(null, uiItem.id, null, null, null, jsonPostOpen);
4022    	} else if (uiItem.inventory_count_sr > 0) {
4023    		UserPortal.Price.get(uiItem.id, false, jsonPostOpen);
4024    	} else {
4025    		UserPortal.getTicket(uiItem.id, uiItem.value);
4026    	}
4027    }
4028    
4029    function _switchFromButtonBasedSearch(el) {
4030    	if (el.hasClass('sa-main-search')) {
4031    		var jpop = $('#pop-sa-keypad').closest('.glopop');
4032    		GLO.Popup.close(jpop);
4033    		
4034    		el = $('#easySearch_text');
4035    	}
4036    	
4037    	return el;
4038    }
4039    
4040    _constructor.resetSearchBox = function(jsearch) {
4041    	if (jsearch === undefined) {
4042    		jsearch = _getSearchBox();
4043    	}
4044    	
4045    	window.setTimeout( function() { jsearch.val('').blur(); }, 900);         //s.val('');
4046        jsearch.attr('clientId', '').attr('inventoryId', '').attr('shipmentId', '').attr('bookingId', '');
4047    }
4048    
4049    function _getSearchBox() {
4050    	if (GLO.Info.isMobile()) {
4051        	var s = $('#mp-pusher.mp-pushed').find('#mp-menu-search input');
4052        	
4053        	if (s.length === 0) { s = $('#easySearch_text'); }
4054        } else if ($('.glopop.sa-main-search').length) {
4055        	var s = $('.glopop.sa-main-search #pop-sa-keypad').find('input.sa-main-search');
4056        } else {
4057        	var s = $('#easySearch_text');
4058        }
4059        
4060        return s;
4061    }
4062    
4063    _constructor.run = function(text, id, uiItem) {
4064        $('#search-overlay').remove();
4065        if ($('#simplemodal-container:visible').length > 0) { return; }       //~ modal popup is open so shouldn't be here.
4066        
4067        var s = _getSearchBox();
4068        var sid = s.attr('clientId');
4069        var inventoryId = s.attr('inventoryId');
4070        var smid = UTIL.cleanString(s.attr('bookingId')).replace( 'P', '');
4071        var shipmentId = UTIL.cleanString(s.attr('shipmentId')).replace('O', '');
4072        
4073        var openAsFullPage = ($('.shadow-content0 #sale-keyboard:visible').length > 0);
4074        UTIL.Validate.changeReset();
4075
4076        if (!UTIL.isEmpty(inventoryId)) {
4077            GLO.Inventory.openSummary(inventoryId);
4078        } else if (!UTIL.isEmpty(shipmentId)) {
4079        	if (uiItem.order_type_cd == 200) {
4080        		//toDo: implement link to audit history report.
4081        	} else {
4082        		document.location = GLO.Link.Page.Provider.Home + 'Inventory/index?EditShipmentId=' + shipmentId;
4083        	}
4084        } else if (!UTIL.isEmpty(smid)) {
4085        	if (UTIL.coalesceInt(uiItem.appt_count_sr, 0) > 0) {
4086        		UserPortal.Edit.get(null, smid);
4087        	} else if (UTIL.coalesceInt(uiItem.inventory_count_sr, 0) > 0) {
4088        		UserPortal.Price.get(smid);
4089        	}
4090        } else if (!UTIL.isEmpty(sid) || openAsFullPage) {
4091            var loadPage = GLO.Link.Page.Provider.ClientProfile + '?cid=' + id;
4092            ClientProfile.open(loadPage, false, text);
4093        } else {
4094            var searchName = s.val().replace('(', '').replace('#', '').replace('$', '').replace('^', '').replace('<', '').replace('>', '').replace('&', '').replace('/', '').replace('\\', '').replace('"', '');    //toDo: make UTIL.replaceAll a function of JavaScript's String object (ie. ~ String.prototype.replaceAll = UTIL.replaceAll) and use replaceAll
4095            
4096            var loadPage = GLO.Link.Object.Provider.UserSearchResult + '?term=' + encodeURIComponent(searchName) + '&dt=' + UTIL.getDateString();
4097            var throbber = $('.loadingDiv').clone().find('img').css({"margin-top": "150px"});
4098            var jmodal = $('#pop-temp');
4099            var htmProcessing = '<p style="letter-spacing: 1px; font-size: large; font-weight: bold;">Looking up <b style="color: #4F81BD">' + searchName + '</b>...</p>';
4100            var ojProcessing = GLO.Popup.Processing.open('<div id="pop-running-search">
4100' + htmProcessing + '</div>', 'Searching');
4101            
4102            jmodal.html(throbber).load(loadPage, function() {
4103                _loadSearchResults(ojProcessing);
4104            });
4105            
4106            jmodal.modal();
4107            jmodal.find('#imgThrobber').css({ "margin-top": "22px" });
4108            $.modal.update(75, 75);
4109        }
4110        
4111        window.setTimeout( function() { s.val('').blur(); }, 900);         //s.val('');
4112        s.attr('clientId', '').attr('inventoryId', '').attr('shipmentId', '').attr('bookingId', '');
4113    }
4114    
4115    function _loadSearchResults(ojProcessing) {
4116    	if (innerWidth > 660) {
4117        	var popWidth = 650;
4118        } else if (!GLO.Info.isMobile()) {
4119        	var popWidth = innerWidth - 40;			//$('#simplemodal-container').css({ "width": "inherit" });
4120        	if (popWidth < 480) { popWidth = 500; }
4121        } else {
4122        	var popWidth = null;
4123        }
4124        
4125        ojProcessing.close();
4126        GLO.Popup.closeIfExist($('.glopop.sa-main-search'));
4127        $.modal.update(null, popWidth);
4128        
4129        var jm = $('#simplemodal-container');
4130        var jticket = jm.find('.ticket-search');
4131        var jproduct = jm.find('#inventory-item-summary');
4132        
4133        if (jticket.length) {
4134        	var smid = jticket.attr('schedule_multi_id');
4135        	
4136        	if (UTIL.parseBool(jticket.attr('is_appt_fl'))) {
4137        		UserPortal.Edit.get(null, smid, true, UserPortal.Edit.isCalendar, true);
4138        		return;
4139        	} else if (UTIL.parseBool(jticket.attr('is_product_fl'))) {
4140        		$.modal.close();
4141        		UserPortal.Price.get(smid);
4142        		return;
4143        	}
4144        } else if (jproduct.length) {
4145        	GLO.Inventory.openSummaryAdjust(true);				//GLO.Inventory.openSummary2(arguments[0], arguments[1], arguments[2]);
4146        	return;
4147        }
4148        
4149        if (jm.width() < 100 || jm.height() < 200) {              //BUG (Chrome): fixes bug when on calendar popup's width & height are both < 50px.
4150            var rowCnt = jm.find('#searchResults-Client tr').length;
4151            var rowHeight = 36;
4152            var h = 120 + rowCnt * rowHeight;
4153
4154            if (h < 240 && GLO.Info.isMobile()) {
4155            	h = 240;
4156            } else if (h < 200) {
4157                h = 200;
4158            } else if (h > 570) {
4159                h = 570;
4160            }
4161            
4162            /* if (rowCnt === 0) {
4163                searchName = UTIL.htmlEncode2(searchName);
4164                $('#pop-temp').html("<div style='margin: auto; margin-top: 70px; color: Black;'>" + SA.Resource.NoResultsFoundWouldYouLikeToCreate + " <b style='font-style: italic; color: Purple;'>" + searchName + "</b> " + SA.Resource.as_text + " <a onclick='GLO.Popup.Profile(null, \"" + searchName + "\")'>" + SA.Resource.a_new_client + "</a>?</div>");
4165            } */
4166            
4167            if (GLO.Info.isMobile()) {
4168            	$.modal.update(h, null);
4169            	
4170            	if (GLO.Info.isLandscape()) {
4171            		//$.modal.update(h, 555);
4172            		var isPortrait = false;
4173            	} else {
4174            		//$.modal.update(h, 310);
4175            		//jm.find('.landscape-only').addClass('hidePhone');
4176            		var isPortrait = true;
4177            	}
4178            	
4179            	$('#simplemodal-container .modalCloseImg').attr('style', 'top: 3px !important');
4180            	GLO.ClientProfile.resizeClientProfilePopup(jm, isPortrait);
4181            } else {
4182            	$.modal.update(h, null);
4183            }
4184            
4185            jm.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
4186        }
4187    }
4188	
4189	function log(message) {
4190        $("<div/>").text(message).prependTo("#log");
4191        $("#searchDebug").attr("scrollTop", 0);
4192    }
4193
4194    _constructor.createAppt = function() {         //opens the create appt popup from the search results popup
4195        var tblRow = $('#searchResults-Client tbody tr.selectedRow');
4196
4197        if (tblRow.length === 0) {
4198            tblRow = $('#searchResults-Client tbody tr');
4199            
4200            if (tblRow.length !== 1) {
4201                GLO.Popup.Warning(SA.Resource.PleaseClickRow);
4202                return;
4203            }
4204        } 
4205
4206        var c = tblRow.find('td[cid]')
4207        var clientId = c.attr('cid'), clientName = c.find('a').text();
4208        var otherAttributes = GLO.ClientProfile.getClientAttributes(tblRow);
4209        var row = '<tr client_id="' + clientId + '" client_vc="' + clientName + '"' + otherAttributes + '/>';
4210        
4211        $.modal.close();
4212        
4213        if (tblRow.find('.location-icon').length > 0) {
4214        	GLO.ClientProfile.importClient(clientId, clientName);
4215        } else {
4216        	UserPortal.Create.get(row);
4217        }
4218    }
4219    
4220    return _constructor;
4221})();
4222
4223
4224GLO.Report = (function() {
4225    function _conRpt() { }
4226    _conRpt.staffFilter = '';
4227    _conRpt.portalName = '';
4228	_conRpt.isInit = false;
4229	
4230    _conRpt.init = function() {
4231        _conRpt.isInit = GLO.Staff.Filter.isReportPortal = true;
4232        UI.initTableSorter( $('table.tablesorter:visible') );
4233        
4234        if (!(GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile())) {
4235        	_conRpt.initBeginAndEndDate(-7);
4236        }
4237        
4238        var j = $('.appt-list-search');
4239
4240        var begin = GLO.Uri.query('start');
4241        var end = GLO.Uri.query('end');
4242        
4243        var svcId = GLO.Uri.query('service');
4244        var sfilter = GLO.Uri.query('sfilter');
4245        
4246        if (UTIL.isDate(begin)) { j.find('.Begin_dt').val(new Date(begin).toGloDate(
4246)); }
4247        if (UTIL.isDate(end)) { j.find('.End_dt').val(new Date(end).toGloDate()); }
4248
4249        if (!UTIL.isEmpty(svcId) && (j.find('.Service_Filter').length === 1)) { j.find('.Service_Filter').val(svcId); }
4250        
4251        _conRpt.addSFilterHelloBar(sfilter);
4252        _conRpt.initShortcutKeys();
4253        _conRpt.isInit = false;
4254        _conRpt.enableFullPageCheck();
4255        _conRpt.initUrlAction();
4256    }
4257	
4258	_conRpt.initUrlAction = function() {
4259		var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
4260    	var step = UTIL.coalesceInt(GLO.Uri.url('step'), 0);
4261    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
4262    	
4263    	if (!UTIL.isEmpty(open)) {
4264			if (open === 'commission-help') {
4265				GLO.Provider.Commission.openReportHelp(step);
4266			}
4267		}
4268		
4269		if (!UTIL.isEmpty(highlight)) {
4270			var jhighlight = $('#' + highlight + ', .' + highlight);
4271			
4272			if (jhighlight.length > 0) {
4273				UI.highlight(jhighlight, 800, 6400, true);
4274			}
4275		}
4276	}
4277	
4278	_conRpt.initBeginAndEndDate = function(beginDays, endDays, jContainer) {
4279        if (jContainer === undefined || jContainer === null) { jContainer = $('.appt-list-search'); }
4280
4281        var Begin_dt = new Date(), End_dt = new Date();
4282        var dtUI1 = jContainer.find('.Begin_dt').val(), dtUI2 = jContainer.find('.End_dt').val();
4283        
4284        if (UTIL.isDate(dtUI1)) {
4285        	Begin_dt = new Date(dtUI1);
4286        } else if (!UTIL.isEmpty(beginDays)) {
4287        	Begin_dt.setDate(Begin_dt.getDate() + beginDays);
4288        }
4289        
4290        if (UTIL.isDate(dtUI2)) {
4291        	End_dt = new Date(dtUI2);
4292        } else if (!UTIL.isEmpty(endDays)) {
4293        	End_dt.setDate(End_dt.getDate() + endDays);
4294        }
4295        
4296        jContainer.find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
4297                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1
4298                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }).val(Begin_dt.toGloDate());
4299        
4300        jContainer.find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
4301                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths()
4302                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect }).val(End_dt.toGloDate());
4303    }
4304	
4305	_conRpt.initShortcutKeys = function() {
4306		//toDo (low priority): implement so that on report portals w/ multiple tabs, ctrl + right/left arrow --> navigates b/ reports
4307	}
4308	
4309	_conRpt.initStaffFilter = function(isAddHelloBar) {
4310		var sfilter = GLO.Uri.query('sfilter');
4311		var sgid = GLO.Uri.query('id');
4312		
4313		if (UTIL.isEmpty(sfilter) && UTIL.isEmpty(sgid)) { return; }
4314		
4315		var jfilter = $('#hd #staff-filter');
4316		
4317		if (UTIL.isNumber(sfilter) && sfilter.indexOf(',') === -1) {
4318			jfilter.val(sfilter);
4319		} else if (UTIL.isNumber(sgid) && GLO.Uri.query('type') === 'sg') {
4320			jfilter.val(sfilter);
4321		} else if (sfilter.indexOf('-9') !== -1) {
4322			jfilter.val('house');
4323		} else {
4324			jfilter.find('#staff-filter-custom').prop('selected', true);
4325			
4326			if (jfilter.find('option#staff-filter-change').length === 0) {
4327	            jfilter.find('#staff-filter-custom-group').prepend('<option value="-99" id="staff-filter-change" title="' + SA.Resource.ClickToChangeFilter + '">' + SA.Resource.ChangeFilter + '</option>');
4328	        }
4329		}
4330		
4331		jfilter.find('#staff-filter-today').remove();
4332		
4333		if (isAddHelloBar && UTIL.coalesce(sfilter, 'all').toLowerCase() != 'all') {
4334			if (sfilter == 'house') {
4335	        	sfilter = GLO.Staff.Filter.getHouseStaff();
4336			} else if (UTIL.isNumber(sgid) && GLO.Uri.query('type') === 'sg') {
4337	            sfilter = $('#ServiceGroupOptionsClone option[value="' + jOption.attr('value') + '"]').attr('staff_ids');
4338	        }
4339	        
4340	        _conRpt.setStaffFilter(sfilter);
4341		}
4342	}
4343	
4344	_conRpt.initIcons = function(jtbl) {
4345		if (!jtbl || jtbl.length === 0) {
4346			jtbl = $('#bd table.tablesorter');
4347		}
4348		
4349		var searchQuery = '.location-icon, .appt-edit-contains-products, .staff-only-note-icon, .special-request-icon, .mult-service-icon, .cal-event-icon-multi-ticket';
4350		searchQuery += ', .multi-service-icon, .multi-ticket-icon-container, .staff-only-note-icon, .special-request-icon, .camera-icon, .client-rating-icon';
4351		
4352		jtbl.find(searchQuery).css({ "cursor": "pointer" }).click(GLO.Report.openIconSummary);
4353	}
4354	
4355	_conRpt.initEnterPasswordPage = function() {
4356		_hideReportInfo();
4357		var jinput = $('#report-password-container #Report_Password_vc');
4358		
4359		if (jinput.length) {
4360			jinput.focus();
4361			jinput[0].addEventListener("keydown", function (e) {
4362			    if (e.code === "Enter") {  //checks whether the pressed key is "Enter"
4363			        $('#report-password-container .btnSearchWithReportPassword').find('> a').click();
4364			    }
4365			});
4366		}
4367	}
4368	function _hideReportInfo() {
4369		$('.report-chart-container').remove();
4370	}
4371	
4372	_conRpt.openTag = function(event) {
4373    	var jtag = $(this);
4374    	var tr = jtag.closest('tr');
4375    	var thisClientId = tr.attr('client_id'), thisClientName = tr.find('.reminder-client-name').find('a').text();
4376    	
4377    	if (UTIL.isEmpty(thisClientName)) {
4378    		thisClientName = tr.find('.member-client-name').text();
4379    	}
4380    	
4381    	GLO.ClientProfile.Tag.openTagFromReport(jtag, thisClientId, thisClientName);
4382    }
4383	
4384	_conRpt.openIconSummary = function(event) {
4385		var jicon = $(this);
4386		var id = jicon.attr('id');
4387		title = UTIL.cleanString(jicon.attr('title'));
4388		if (!title && title != '') {
4389			title = UTIL.cleanString(jicon.find('>img').attr('title'));
4390		}
4391		
4392		if (jicon.hasClass('location-icon')) {
4393			var h1 = 'Different Location', msg = title;
4394		} else if (jicon.hasClass('appt-edit-contains-products')) {
4395			var h1 = 'Has Product', msg = title;
4396		} else if (jicon.hasClass('staff-only-note-icon')) {
4397			var h1 = 'Staff Only Note', msg = '<label>Staff Only Note:</label> ' + title;
4398		} else if (jicon.hasClass('special-request-icon')) {
4399			var h1 = 'Special Request', msg = '<label>Special Request:</label> ' + title;
4400		} else if (jicon.hasClass('mult-service-icon')) {
4401			var h1 = 'Multiple Services', msg = title;
4402		} else if (jicon.hasClass('recur-icon')) {
4403			var h1 = 'Recurring Appointment', msg = UTIL.coalesce(title, 'is recurring appointment');
4404		} else if (jicon.hasClass('cal-event-icon-multi-ticket')) {
4405			var h1 = 'Multiple Tickets', msg = 'Ticket linked to other tickets';
4406		} else if (jicon.hasClass('camera-icon')) {
4407			var h1 = 'Appointment has Images', msg = UTIL.pluralLabel(jicon.attr('image_count_sr'), 'Image') + ' attached to appointment';
4408		} else if (jicon.hasClass('client-rating-icon')) {
4409			var msg ='';
4410			var responseData = _getRatingDetails(title);
4411			if (responseData && responseData!='') {
4412				var arrResponse = UTIL.cleanString(responseData).split('|');
4413				for (var i=0; i < arrResponse.length; i++) {
4414					if (!UTIL.isEmpty(arrResponse[i])) {
4415						msg += '<p>' + (arrResponse[i]) + '</p>';
4416					} else {
4417						msg += '<br/>';
4418					}
4419				}
4420			}
4421
4422			var h1 = 'Client Rating', msg = '<label>Rating Details:</label> ' + msg;
4423		} else {
4424			return;
4425		}
4426		
4427		GLO.Popup.close($('#pop-help-icon-summary').closest('.glopop'));
4428		
4429		var htm = '<div id="pop-help-icon-summary">' + msg + '</div>';
4430		GLO.Popup.Info.open(htm, h1);
4431	}
4432	
4433	_conRpt.enableFullPageCheck = function(isDefaultToDisplayAll) {
4434		var rptDefault = $.cookies.get("reports");
4435		
4436		if (rptDefault === "display-all" || (isDefaultToDisplayAll && UTIL.isEmpty(rptDefault))) {
4437			_conRpt.enableFullPage(true, true);
4438		} else {
4439			_conRpt.enableFullPage(false, true);
4440		}
4441	}
4442	
4443	_conRpt.enableFullPage = function(isYes, isIgnoreCookie) {
4444		if (isYes) {
4445			$('body').removeClass('report-custom-page').addClass('report-full-page');
4446			$('.btnReportAll').addClass('hideX');
4447			$('.btnReportFit').removeClass('hideX');
4448			
4449			//var expireDate = new Date();
4450			//expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 1));
4451			
4452			if (!isIgnoreCookie) {
4453				UTIL.setCookie("reports", "display-all");						//$.cookies.set("reports", "display-all", { "expiresAt": expireDate });
4454			}
4455		} else {
4456			if (GLO.Report.portalName === 'payroll') {
4457				if ($('body.report-custom-page').length === 1) {
4458					$('body').removeClass('report-custom-page');
4459				} else if (_payrollUseCustomPage()) {
4460					$('body').removeClass('report-full-page').addClass('report-custom-page');
4461				}
4462			}
4463			
4464			$('body').removeClass('report-full-page');
4465			$('.btnReportAll').removeClass('hideX');
4466			$('.btnReportFit').addClass('hideX');
4467			
4468			if (!isIgnoreCookie) {
4469				UTIL.setCookie("reports", "fit-screen");						//UTIL.setCookieWithExpire("reports", null);
4470			}
4471		}
4472	}
4473	
4474	function _getRatingDetails(title) {
4475
4476    	var msg = '', arr = UTIL.cleanString(title).split('|');
4477		var pid = arr[0];
4478		var smid = arr[1];
4479		var url = GLO.Link.WebsiteDomain + 'repman/getRatingDetailsForClientHistory?providerId='+pid+'&bookingId='+smid;
4480        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false,"async":false })
4481            .success(function(data, textStatus, jqXHR) {
4482            })
4483            .error(function(jqXHR, textStatus, errorThrown) {
4484            }).responseText;
4485
4486    	return jqxhr;
4487    }
4488
4489	function _payrollUseCustomPage() {
4490		var cnt = 0, tds = $('#report-payroll-summary #report-payroll-header2 td');
4491		
4492		for (var i=0; i < tds.length; i++) {
4493			var td = tds.eq(i);
4494			
4495			if (!td.hasClass('staff-column') && !td.hasClass('staff-type-column') && !td.hasClass('narrow-column') && !td.hasClass('hideX')) {
4496				++cnt;
4497			}
4498		}
4499		
4500		if (GLO.Info.isGold()) { var groupWidth = 300; } else { var groupWidth = 200; }
4501		
4502		if (cnt * groupWidth < innerWidth) {
4503			return true;
4504		} else {
4505			return false;
4506		}
4507	}
4508	
4509	_conRpt.addSFilterHelloBar = function(sfilter) {
4510		if (UTIL.isEmpty(sfilter) || String(sfilter).toLowerCase() === 'all') {
4511            $('#staff-filter').val('all');
4512        } else if (String(sfilter).indexOf(',') !== -1) {
4513            $('#staff-filter').val('staff-filter-custom');
4514            _conRpt.setStaffHelloBar(sfilter);
4515        } else if (UTIL.isNumber(sfilter)) {
4516            $('#staff-filter').val(sfilter);
4517            _conRpt.setStaffHelloBar(sfilter);
4518        }
4519	}
4520	
4521    _conRpt.datePickerBeforeShow = function(input, inst) {
4522        $("#ui-datepicker-div").removeClass('is-week-picker').removeClass('is-month-picker');
4523
4524        if ($(input).hasClass('week-picker')) {
4525            $("#ui-datepicker-div").addClass('is-week-picker');
4526        } else if ($(input).hasClass('month-picker')) {
4527            $("#ui-datepicker-div").addClass('is-month-picker');
4528        }
4529    }
4530
4531    _conRpt.datePickerOnChange = function(year, month, inst) {
4532        var jInput = $(inst.input);
4533
4534        if (jInput.hasClass('month-picker')) {
4535            if (jInput.hasClass('Begin_dt')) {
4536                var dt = new Date(year, month - 1, 1);
4537            } else {
4538                var dt = new Date(year, month, 0);
4539            }
4540
4541            jInput.val(dt.toGloDate());
4542        }
4543    }
4544	
4545	_conRpt.firstDayOfWeek = function(dt, firstDayOfWeek) {
4546		var selectedDayOfWeek = dt.getDay();
4547        
4548        if (selectedDayOfWeek >= firstDayOfWeek) {
4549        	var diff = selectedDayOfWeek - firstDayOfWeek;
4550        } else {
4551        	var diff = 7 + selectedDayOfWeek - firstDayOfWeek;
4552        }
4553        
4554        return new Date(dt).addDays(-diff);
4555	}
4556	
4557    _conRpt.datePickerOnSelect = function(dateText, inst) {
4558        var jInput = $(inst.input);
4559        
4560        if (jInput.hasClass('week-picker')) {
4561            var dt = new Date(dateText);
4562            var firstDayOfWeek = jInput.datepicker('option', 'firstDay');			//= first day of the week in the datepicker (likely 'Sunday' = 0 or 'Monday' = 1)
4563            var dtStart = _conRpt.firstDayOfWeek(dt, firstDayOfWeek);
4564            
4565            if (!jInput.hasClass('Begin_dt')) {
4566                dtStart.addDays(6);
4567            }
4568
4569            jInput.val(dtStart.toGloDate());
4570        }
4571    }
4572    
4573    _conRpt.setBeginDate = function(dt, view, jInput) {
4574        dt = new Date(dt);
4575
4576        if (view === 'week') {
4577            dt.setDate(dt.getDate() - dt.getDay());
4578        } else if (view === 'month') {
4579            dt = new Date(dt.getFullYear(), dt.getMonth(), 1);
4580        }
4581
4582        jInput.val(dt.toGloDate());
4583    }
4584    _conRpt.setEndDate = function(dt, view, jInput) {
4585        dt = new Date(dt);
4586
4587        if (view === 'week') {
4588            dt.setDate(dt.getDate() - dt.getDay() + 6);
4589        } else if (view === 'month') {
4590            var dt = new Date(dt.getFullYear(), dt.getMonth() + 1, 0);
4591        }
4592
4593        jInput.val(dt.toGloDate());
4594    }
4595    
4596    _conRpt.movePrev = function() {
4597        _moveDates(-1);
4598    }
4599    _conRpt.moveNext = function() {
4600        _moveDates(1);
4601    }
4602    function _moveDates(up) {
4603        var j = $('.appt-list-search');
4604        if (j.length === 0) { j = $('.report-search-header'); }
4605        
4606        var jBegin = j.find('.Begin_dt');
4607        var jEnd = j.find('.End_dt');
4608        
4609        var dt1 = jBegin.val();
4610        var dt2 = jEnd.val();
4611        var monthCount = null, isWeekRange = false;
4612
4613        if (!UTIL.isEmpty(dt1)) {
4614            if (GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile()) {
4615            	var arr = dt1.split('-');
4616            	dt1 = new Date(arr[1] + '/' + arr[2] + '/' + arr[0]);
4617            } else {
4618            	dt1 = new Date(dt1);
4619            }
4620        } else {
4621            dt1 = new Date();
4622        }
4623
4624        if (!UTIL.isEmpty(dt2)) {
4625            if (GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile()) {
4626            	var arr = dt2.split('-');
4627            	dt2 = new Date(arr[1] + '/' + arr[2] + '/' + arr[0]);
4628            } else {
4629            	dt2 = new Date(dt2);
4630            }
4631        } else {
4632            dt2 = new Date();
4633        }
4634
4635        if (jBegin.hasClass('month-picker')) {
4636            dt1.setMonth(dt1.getMonth() + (1 * up) );
4637            dt2.setMonth(dt2.getMonth() + (1 * up) );
4638        } else {
4639            if (jBegin.hasClass('week-picker')) {
4640                var moveBy = 7;
4641            } else if (!jBegin.is(':visible') && j.find('#Week_dt').length === 1) {
4642            	var moveBy = 7;
4643            	isWeekRange = true;
4644            } else if (GLO.Report.Template.isMonthRange(dt1, dt2)) {
4645            	var monthCount = up * (dt2.getMonth() - dt1.getMonth() + (12 * (dt2.getFullYear() - dt1.getFullYear())) + 1);
4646	        	dt1 = new Date(dt1.setMonth(dt1.getMonth() + monthCount));
4647	        	dt2 = GLO.Report.Template.addMonthsToEndDate(dt2, monthCount);
4648            } else {
4649                var oneDay = 24*60*60*1000; 						//hours * minutes * seconds * milliseconds.
4650        		var moveBy = Math.round(Math.abs((dt2.getTime() - dt1.getTime())/(oneDay))) + 1;
4651            }
4652            
4653            if (monthCount === null) {
4654	            dt1.setDate(dt1.getDate() + (moveBy * up));
4655		        dt2.setDate(dt2.getDate() + (moveBy * up));
4656	        }
4657        }
4658        
4659        if ((GLO.Report.portalName === 'timesheet' && GLO.Info.isMobile())) {
4660        	jBegin.val(dt1.toGloDate(true));
4661        	jEnd.val(dt2.toGloDate(true));
4662        } else {
4663	        jBegin.val(dt1.toGloDate());
4664	        jEnd.val(dt2.toGloDate());
4665        }
4666        
4667        var dtRange = GLO.Report.Timesheet.getWeekDateRange(dt1, dt2);
4668        
4669        if (isWeekRange) {
4670        	j.find('#week-date-range').text(dtRange);
4671        	
4672        	GLO.UI.Form.beginProcessing( j.find('.btnAction1') );
4673        	GLO.Report.Timesheet.search();
4674        } else if ($('#report-header-search').length > 0) {
4675        	$('#report-header-search').click();
4676        } else {
4677        	$('#report-ticket-history').find('.report-search-header .btnSearch:visible a').click();
4678        }
4679    }
4680    
4681    _conRpt.hideEmptyColumn = function(jtbl, columnClass) {
4682    	var tds = jtbl.find('tbody').find('.' + columnClass);
4683    	
4684    	for (var i=0; i < tds.length; i++) {
4685    		if (!UTIL.isEmpty(tds.eq(i).text())) {
4686    			return false;
4687    		}
4688    	}
4689    	
4690    	tds.addClass('hideX');
4691    	jtbl.find('thead').find('.' + columnClass).addClass('hideX');
4692    	
4693    	var tf = jtbl.find('tfoot').find('.' + columnClass);
4694    	var colspan = UTIL.coalesceInt(tf.attr('colspan'), 0);
4695    	
4696    	if (colspan > 1) {
4697    		tf.attr('colspan', colspan - 1);
4698    		return false;
4699    	} else {
4700    		tf.addClass('hideX');
4701    		return true;
4702    	}
4703    }
4704	
4705    _conRpt.changeStaffFilter = function(jOption) {
4706        if (jOption === undefined || jOption.attr('value') == 'all') {
4707            _conRpt.setStaffFilter('');
4708        } else if (jOption.attr('value') == '' || jOption.attr('value') == '-99') {
4709            GLO.Staff.Filter.open(true);
4710            return;
4711        } else if (jOption.attr('value') == 'house') {
4712        	var sfilter = GLO.Staff.Filter.getHouseStaff();
4713        	_conRpt.setStaffFilter(sfilter);
4714        } else if (jOption.attr('value') == 'not-house') {
4715        	var sfilter = GLO.Staff.Filter.getNotHouseStaff();
4716        	_conRpt.setStaffFilter(sfilter);
4717        } else if (jOption.parent().attr('id') == 'staff-filter-sg') {
4718            _conRpt.setStaffFilter( $('#ServiceGroupOptionsClone option[value="' + jOption.attr('value') + '"]').attr('staff_ids') );
4719        } else {            //if (jOption.parent().attr('id') == 'staff-filter-s')
4720            _conRpt.setStaffFilter(jOption.attr('value'));
4721        }
4722        
4723        if (GLO.Report.portalName === 'sales' || GLO.Report.portalName === 'popular') {		//re-run all reports
4724        	var jrpt, jrpts = $('.inventory-report, .entire-report');
4725        	
4726        	for (var i=0; i < jrpts.length; i++) {
4727        		jrpt = jrpts.eq(i);
4728        		GLO.Report.Template.search(null, jrpt);
4729        	}
4730        } else if (GLO.Report.portalName === 'timesheet') {
4731        	$('#timesheet-header #report-header-search').click();
4732        } else if (GLO.Report.portalName === 'ticket') {
4733        	GLO.Report.TicketHistory.search();
4734        } else if (GLO.Report.portalName === 'incorrect-payment') {
4735        	var btnRefresh = $('#bd h1 .fa-refresh')[0];
4736        	GLO.Report.Other.search(btnRefresh);
4737        } else if (GLO.Report.portalName === 'payroll-days') {
4738        	_searchDailyPayrollReport();
4739        } else {
4740        	$('.report-search-header').find('.btnSearch > a').click();
4741        }
4742    }
4743    
4744    function _searchDailyPayrollReport() {
4745    	var btnSearch = $('.report-search-header').find('.btnSearch:visible');
4746    	
4747    	if (btnSearch.length) {
4748    		GLO.Report.Payroll.search();
4749    	} else {
4750    		var btn = $('#payroll-report-date-period .btnPayrollPeriods').find('.btnAdd.selected');
4751    		
4752    		if (btn.hasClass('btnProcessing4')) {
4753    			setTimeout(function() {
4754	    			location.reload();
4755	    		}, 1500);
4756	    		
4757	    		GLO.Popup.Processing.open('Re-loading page to complete this request', 'Processing Multiple Report Requests');
4758    		} else {
4759    			btn.find('>a').click();
4760    		}
4761    	}
4762    }
4763    
4764    _conRpt.setStaffFilter = function(staffIds) {
4765        staffIds = UTIL.cleanString(staffIds);
4766        
4767        var queryString = GLO.Uri.getQueryString('sfilter', staffIds);
4768        var uri = document.location.origin + document.location.pathname + '?' + queryString + document.location.hash;
4769        //var uri = document.location.origin + document.location.pathname + '?sfilter=' + staffIds + GLO.Uri.urlToArray() + document.location.hash;
4770        
4771        try {
4772            window.history.pushState("", "Report", uri);
4773        } catch (e) {
4774            document.location = uri;
4775            return;
4776        }
4777
4778        _conRpt.setStaffHelloBar(staffIds);
4779        
4780        /*
4781        if (GLO.Report.portalName !== 'sales') {
4782	        if ($('#report-header-search:visible').length === 1) {
4783	            $('#report-header-search').click();
4784	        } else {
4785	            $('.report-search-header:visible').find('.btnSearch a').click();
4786	        }
4787        }
4788        */
4789    }
4790    
4791    _conRpt.getStaffHelloLabel = function(staffIds) {
4792    	if (staffIds.substring(staffIds.length - 1) === ',') { staffIds = staffIds.substring(0, staffIds.length - 1); }
4793    	
4794    	if (!UTIL.isEmpty(staffIds)) {
4795    		var sname, slabel = '', arr = staffIds.split(',');
4796	        var jddStaff = $('#ba-CreateAppointment').find('#Staff_id');
4797			
4798	        for (var s=0; s < arr.length; s++) {
4799	            sname = jddStaff.find('option[value="' + arr[s] + '"]').text();
4800				
4801	            if (!UTIL.isEmpty(sname)) {
4802	                if (slabel !== '') { slabel += ', '; }
4803	                
4804	                slabel += '<span>' + sname + '</span>';
4805	            }
4806	        }
4807	        
4808	        return slabel;
4809	    } else {
4810	    	return '';
4811	    }
4812    }
4813    
4814    _conRpt.setStaffHelloBar = function(staffIds) {
4815        if (GLO.Info.isMobile()) { return; }
4816        
4817        $('#staffFilter').remove();
4818        
4819        if (!UTIL.isEmpty(staffIds)) {
4820	        var slabel = _conRpt.getStaffHelloLabel(staffIds);
4821			
4822			if (!UTIL.isEmpty(slabel)) {
4823		        var htm = '<div id="staffFilter"> <p>'
4824		                    +'<span class="filter-by">' + SA.Resource.FilterBy + ':</span> <span class="hello-bar-label">' + slabel + '</span>'
4825		                    + '<span class="ui-icon ui-icon-circle-close" style="position: fixed; right: 7px; top: 3px; cursor: pointer;" onclick="GLO.Staff.Filter.removeFilter()" title="' + SA.Resource.RemoveFilter + '"></span>'
4826		                    + '</p> </div>';
4827				
4828		        $('#hd-parent').after(htm);
4829		        $('#doc3').css({ "margin-top": "25px" });
4830	        } else {
4831	        	$('#doc3').css({ "margin-top": "" });
4832	        }
4833	    } else {
4834	    	$('#doc3').css({ "margin-top": "" });
4835	    }
4836    }
4837    
4838    _conRpt.setViewType = function() {
4839        var jContainer = $('.appt-list-search');
4840        var jdt1 = jContainer.find('.Begin_dt');
4841        var jdt2 = jContainer.find('.End_dt');
4842        
4843        if (this.value === 'week') {
4844            jContainer.find('#Week_dt').addClass('week-picker');
4845            jContainer.find('.timesheet-search-day').addClass('hide');
4846            jContainer.find('.timesheet-search-week').removeClass('hide');
4847            
4848            GLO.Report.Timesheet.datePickerOnSelect2(new Date(jdt1.val()));
4849        } else if (this.value === 'month') {
4850            pickers.addClass('month-picker');
4851            pickers.datepicker("option", "changeMonth", true)
4852            pickers.datepicker("option", "changeYear", true);
4853
4854            var jdt1 = jContainer.find('.Begin_dt');
4855            var jdt2 = jContainer.find('.End_dt');
4856
4857            GLO.Report.setBeginDate(jdt1.val(), 'month', jdt1);
4858            GLO.Report.setEndDate(jdt1.val(), 'month', jdt2);
4859            
4860            jContainer.find('.timesheet-search-week').addClass('hide');
4861        	jContainer.find('.timesheet-search-day').removeClass('hide');
4862        } else {
4863        	jContainer.find('.timesheet-search-week').addClass('hide');
4864        	jContainer.find('.timesheet-search-day').removeClass('hide');
4865        }
4866
4867        $('#timesheet-view-options .view-selected').removeClass('view-selected');
4868        $(this).parent().addClass('view-selected');
4869        
4870        if (!GLO.Report.isInit && GLO.Report.portalName === 'timesheet' && this.value !== 'week') {		//= if is timesheet report (+ not initializing page, + not wk vw) --> run search.
4871        	jContainer.find('#report-header-search').click();
4872        }
4873    }
4874    
4875    _conRpt.setupFastClick = function() {
4876		if (GLO.Info.isMobile(true)) {
4877	    	var jhead = $('.report-search-header');
4878	    	
4879	    	for (var i=0; i < jhead.length; i++) {
4880	    		GLO.Info.setupFastClick(jhead[i]);
4881	    	}
4882	    }
4883	}
4884	
4885	_conRpt.initReportPassword = function(jrpt) {
4886		if (GLO.Info.roleType < 220) {
4887			if (UTIL.isEmptyObject(jrpt)) {
4888				jrpt = $('#report-main');
4889			}
4890			
4891			jrpt.find('.tablesorter').find('input').prop('disabled', 'disabled').click(GLO.Report.allowReportChange);
4892			
4893			if ($('#bd #commission-by-staff-service').length) {
4894				//UI.setAccessKey('#bd #commission-by-staff-service', null, GLO.Report.searchWithReportPassword);
4895				//jrpt.find('.commission-column-wage > a, .commission-column-product > a, .svc-price > a, .commission-column-tax-withheld').click(GLO.Report.allowReportChange);
4896				$('#bd #commission-by-staff-service-more').find('input').prop('readonly', 'readonly').click(GLO.Report.allowReportChange);
4897			}
4898		}
4899	}
4900	_conRpt.allowReportChange = function() {
4901		if (GLO.Info.roleType < 220) {
4902			if ($('#pop-warn-role-report').closest('.glopop').length === 0) {
4903				var htm = '<div id="pop-warn-role-report">Please login as manager or admin to change this setting</div>';
4904				GLO.Popup.Warning.open(htm, 'Manager or Admin Required');
4905			}
4906			
4907			return false;
4908		}
4909		
4910		return true;
4911	}
4912	_conRpt.hasReportPasswordWarning = function(data) {
4913		GLO.Popup.closeIfExist($('#pop-warn-missing-pin-session').closest('.glopop'));
4914		
4915		if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
4916        	GLO.UI.Form.resetProcessing();
4917        	
4918        	var jpopPIN = GLO.Popup.Custom.openSimple('<div id="pop-warn-missing-pin-session">' + data + '</div>', 'Enter PIN / Password');
4919        	jpopPIN.find('.pop-buttons-parent').remove();
4920        	
4921        	jpopPIN[0].addEventListener("keydown", function(e) {
4922			    if (e.code === "Enter") {  //checks whether the pressed key is "Enter"
4923			        jpopPIN.find('.btnSearchWithReportPassword').find('> a').click();
4924			    }
4925			});
4926        	
4927        	return true;
4928        } else {
4929        	return false;
4930        }
4931	}
4932	_conRpt.openReportPassword = function() {
4933		GLO.UI.Form.resetProcessing();
4934		
4935		var htm = '<div id="pop-report-role-password" style="padding: 12px;">'
4936					+ '<label for="Report_Password_vc">Enter Password to Access Report</label>'
4937	                + '<input type="password" id="Report_Password_vc"/>'
4938	            + '</div>';
4939		
4940		var jpop = GLO.Popup.Custom.openSimple(htm, 'Report Password', GLO.Report.searchWithReportPassword);
4941		
4942		jpop.find('.pop-buttons').css({ "max-width": "320px" });
4943		jpop.find('.btnSave').addClass('btnSearchWithReportPassword').addClass('btnAdd').removeClass('btnSave').css({ "position": "absolute", "right": "6px" }).find('a').text('Lookup');
4944		
4945		jpop[0].addEventListener("keydown", function(e) {
4946		    if (e.code === "Enter") {  //checks whether the pressed key is "Enter"
4947		        jpop.find('.btnSearchWithReportPassword').find('> a').click();
4948		    }
4949		});
4950	}
4951	_conRpt.searchWithReportPassword = function() {
4952		if ($('#enter-report-password-page').length) {
4953			var url = document.location.href;
4954			var element = $('#enter-report-password-page').find('.btnSearchWithReportPassword');
4955			
4956			SA.Menu.verifyPIN(url, false, element);
4957		} else if ($('#pop-edit-wage').closest('.glopop').length) {
4958			var jpop = $('#pop-edit-wage').closest('.glopop');
4959			var password = jpop.find('#Report_Password_vc').val();
4960			
4961			if (jpop.find('#edit-employee-service').length) {
4962				GLO.Provider.Commission.saveEditWage();
4963			} else {
4964				var sid = jpop.find('#Edit_Staff_id').val();
4965				var sname = jpop.find('label[for="Edit_Hourly_Wage_mn"]').text();
4966				var wage = '';
4967				//var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>';
4968				
4969				GLO.Popup.close(jpop);		// jpop.find('.no-results-report-role').replaceWith(throbber);
4970				GLO.Provider.Commission.openEditWage2(sid, sname, wage, password);
4971			}
4972		} else if ($('#bd #commission-by-staff-service').length) {
4973			GLO.Provider.Commission.loadCommissionReport();
4974		} else if ($('#pop-confirm-save-goals').closest('.glopop').length) {
4975			var jpop = $('#pop-confirm-save-goals').closest('.glopop');
4976			jpop.find('.btnSave > a').click();
4977		} else if ($('#cash-event-popup').closest('.glopop').length) {
4978			var jpop = $('#cash-event-popup').closest('.glopop');
4979			jpop.find('.btnSave > a').click();
4980		//} else if ($('.glopop').length > 0 && $('#Report_Password_vc').closest('.glopop').length === 0) {
4981		//	_conRpt.openReportPassword();
4982		} else if ($('#client-list-search-button').find('#btnFilter > a').length) {
4983			$('#client-list-search-button').find('#btnFilter > a').click();
4984		} else if ($('#timesheet-view-options #timesheet-weekly').prop('checked')) {
4985			GLO.Report.Timesheet.search();
4986		} else {
4987			var jbtn = $('#report-main, .report-search-header, #doc3 #timesheet-report').find('.btnSearch > a:visible');
4988			
4989			if (jbtn.length) {
4990				jbtn.eq(0).click();
4991			} else if (GLO.Report.portalName == 'payroll-days') {
4992				$('#payroll-report-date-period .btnPayrollPeriods').find('.btnAdd.selected > a').click();
4993			} else {
4994				$('#bd').find('h1, h2').find('.fa-refresh').click();
4995			}
4996		}
4997	}
4998	_conRpt.isReport = function(urlPath) {
4999		if (GLO.Staff && GLO.Staff.Filter && GLO.Staff.Filter.isReportPortal) {
5000			return true;
5001		}
5002		
5003		urlPath = $.trim(urlPath);
5004		
5005		if (urlPath.startsWith(document.location.origin)) {
5006			urlPath = urlPath.substring(document.location.origin.length);
5007		}
5008		
5009		var arr = urlPath.toLowerCase().split('?');
5010		var urlPath2 = arr[0];
5011		
5012		if (urlPath2.length && urlPath2.substring(0, 1) === '/') {
5013			urlPath2 = urlPath2.substring(1);
5014		}
5015		
5016		if (urlPath2.length && urlPath2.substring(urlPath2.length - 1) === '/') {
5017			urlPath2 = urlPath2.substring(0, urlPath2.length - 1);
5018		}
5019		
5020		if (UTIL.startsWith(urlPath2, 'report/') || UTIL.startsWith(urlPath2, 'reports/')) {
5021			return true;
5022		} else if (urlPath2 == 'provider/inventory' || urlPath2 == 'inventory' || urlPath2 == 'message/clientlist' 
5023				|| urlPath2 == 'membership/report' || urlPath2 == 'membership/servicereport' || urlPath2 == 'payment/reportdaterange' || urlPath2 == 'payment/reportbatch'
5024				|| urlPath2 == 'provider/manage/discount' || urlPath2 == 'provider/manage/addon' || urlPath2 == 'provider/manage/referral' || urlPath2 == 'provider/manage/commissionbystaffservice') {
5025			return true;
5026		}
5027		
5028		return false;
5029	}
5030	_conRpt.autoSearch = function(element) {
5031		$('#report-main, .appt-list-search').find('.btnSearch > a:visible').click();
5032	}
5033	_conRpt.hasTimesheetAccess = function(jd) {
5034		var rr = UTIL.coalesceInt(GLO.Data.Staff.role_report_cd, 0);
5035		
5036		if (rr === 30 || rr === 36) {
5037			return true;
5038		} else {
5039			return _conRpt.hasReportPassword(jd);
5040		}
5041	}
5042	_conRpt.hasReportPassword = function(jd, isPayroll) {
5043		var rr = UTIL.coalesceInt(GLO.Data.Staff.role_report_cd, 0);
5044		
5045		if (rr === 0 || rr === 99 || rr === 199) {
5046			return true;
5047		} else if (!isPayroll && rr < 99) {
5048			return true;
5049		}
5050		
5051		var j = $('#report-password-container');
5052		var pass = j.find('#Report_Password_vc').val();
5053		
5054		if (UTIL.isEmpty(pass)) {
5055			var jpop = $('#pop-report-role-password').closest('.glopop');
5056			
5057			if (jpop.length) {
5058				pass = jpop.find('#Report_Password_vc').val();
5059				
5060				if (UTIL.isEmpty(pass)) {
5061					var fnFocus = function() { jpop.find('#Report_Password_vc').focus(); }
5062					GLO.Popup.Warning.open('Please Enter Password', 'Report Password Empty', fnFocus);
5063					return false;
5064				} else {
5065					GLO.Popup.close(jpop);
5066					jd.report_password_vc = UTIL.htmlEncode(pass);
5067					return true;
5068				}
5069			} else if (j.length) {
5070				var fnFocus = function() { j.find('#Report_Password_vc').focus(); }
5071				GLO.Popup.Warning.open('Please Enter Password', 'Report Password Empty', fnFocus);
5072				return false;
5073			}
5073 else if (!UTIL.isEmpty($.cookies.get('pinsession'))) {
5074				return true;
5075			} else {
5076				_conRpt.openReportPassword();
5077				return false;
5078			}
5079		} else {
5080			GLO.UI.Form.beginProcessing(j.find('.btnSearchWithReportPassword'));
5081			jd.report_password_vc = UTIL.htmlEncode(pass);
5082			return true;
5083		}
5084	}
5085	
5086	_conRpt.exportAsSpreadsheet = function(trs, fileName, btnId) {
5087		var htm = '<table border="2px">';
5088	    var textRange, j=0, rowCount = 0;
5089	    
5090	    for (a=0 ; a < trs.length ; a++) {
5091	        var tr = trs.eq(a);
5092	        
5093	        if (!tr.hasClass('ignore-export')) {
5094	        	if (tr.parent().is('thead')) {
5095	        		var css = 'text-align: center; font-weight: bold; background-color: rgb(180,200,255);';
5096	        	} else if (tr.parent().is('tfoot')) {
5097	        		var css = 'background-color: rgb(200,200,200);';
5098	        	} else {
5099	        		if (rowCount % 2 === 1) {
5100	        			var css = 'background-color: rgb(250,250,250);';
5101	        		} else {
5102	        			var css = '';
5103	        		}
5104	        		
5105	        		++rowCount;
5106	        	}
5107	        	
5108	        	htm += '<tr style="' + css + '">';
5109	        	var tds = trs.eq(a).find('th,td');
5110		        
5111		        for (var b=0; b < tds.length; b++) {
5112		        	var td = tds.eq(b);
5113		        	
5114		        	if (!td.hasClass('ignore-export')) {
5115		        		td = td.clone();
5116		        		td.find('.btnAdd, .btnSave').remove();
5117		        		
5118		        		if (td.find('input').length) {
5119		        			var jinput = td.find('input');
5120		        			td.append(jinput.val());
5121		        			jinput.remove();
5122		        		}
5123		        		
5124		        		htm += td.outerHTML();
5125		        	}
5126		        }
5127		        
5128	        	htm += '</tr>';
5129	        }
5130	    }
5131		
5132	    htm += '</table>';
5133	    htm = htm.replace(/<A[^>]*>|<\/A>/g, '');				//remove if u want links in your table
5134	    htm = htm.replace(/<img[^>]*>/gi, ''); 					//remove if u want images in your table
5135	    //htm = htm.replace(/<input[^>]*>|<\/input>/gi, ''); 		//removes input params
5136		
5137	    var ua = window.navigator.userAgent;
5138	    var msie = ua.indexOf("MSIE "); 
5139		
5140		if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {      // If Internet Explorer
5141	        txtArea1.document.open("txt/html","replace");
5142	        txtArea1.document.write(htm);
5143	        txtArea1.document.close();
5144	        txtArea1.focus();
5145	        sa = txtArea1.document.execCommand('SaveAs', true, fileName);
5146	    } else {
5147	    	//sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(htm));
5148	    	
5149	    	var btnId = UTIL.coalesceString(btnId, 'btnExportLink');
5150	    	var downloadLink = $('#' + btnId)[0];
5151	    	downloadLink.href = 'data:application/vnd.ms-excel,' + encodeURIComponent(htm);
5152	    	downloadLink.download = fileName;
5153	        downloadLink.click();
5154	    }
5155		
5156	    //return (sa);
5157	}
5158	
5159    return _conRpt;
5160})();
5161
5162
5163GLO.Report.Template = (function() {
5164    function _conRptTemplate() { }
5165    
5166    _conRptTemplate.init = function() {
5167    	GLO.Staff.Filter.isReportPortal = true;
5168    	var jhead = $('.report-search-header');
5169    	
5170        for (var i=0; i < jhead.length; i++) {
5171            var includeYearRange = _isIncludeYearRange(jhead);
5172            var yearRange = GLO.UI.getYearRange(true);					//'2012:' + (new Date().getFullYear() + 2);
5173            
5174            jhead.eq(i).find('input[type=text].Report_Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true
5175            																	, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1
5176            																	, beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange });
5177            jhead.eq(i).find('input[type=text].Report_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true
5178            																	, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths()
5179            																	, beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange });
5180        }
5181        
5182        var jtbls = $('.tablesorter');
5183        
5184        for (var i=0; i < jtbls.length; i++) {
5185            UI.initTableSorter2( jtbls.eq(i) );
5186        }
5187        
5188        $('#report-portal-header').removeClass('hide');
5189        
5190        if (!GLO.Report.Sales.initStaffFilter()) {
5191        	_conRptTemplate.initStaffFilter();
5192        }
5193        
5194        GLO.Report.setupFastClick();
5195        return GLO.Uri.url('tab');
5196    }
5197    
5198    function _isIncludeYearRange(jhead) {
5199    	var jrpt = jhead.closest('.inventory-report');
5200    	var rptid = jrpt.attr('id');
5201    	
5202    	if (rptid === 'report-sales-summary' || rptid === 'report-popular-services' || rptid === 'report-popular-products' || rptid === 'report-product-activity'
5203    			|| rptid === 'report-product-history' || rptid === 'report-shipment-history' || rptid === 'report-audit-history' || rptid === 'report-returns-exchanges') {
5204    		return true;
5205    	} else {
5206    		return false;
5207    	}
5208    }
5209    
5210    _conRptTemplate.initDateRange = function(jhead, includeYearRange, isBlockFutureDays) {
5211    	if (jhead.find('#report-start').length === 0) { return; }
5212    	
5213    	var yearRange = GLO.UI.getYearRange(true);					//'2012:' + (new Date().getFullYear() + 2);
5214    	var monthsToShow = 1;
5215    	
5216    	if (innerWidth > 970) {
5217    		monthsToShow = 2;
5218    	}
5219    	
5220    	var startOptions = { showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
5221								, dateFormat: "M d, yy", numberOfMonths: monthsToShow, beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange };
5222    	
5223    	var endOptions = { showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
5224							, dateFormat: "M d, yy", numberOfMonths: monthsToShow, beforeShow: UI.loadDatepicker, changeYear: includeYearRange, yearRange: yearRange };
5225    	
5226    	if (isBlockFutureDays) {
5227    		startOptions.maxDate = 0;
5228    		endOptions.maxDate = 0;
5229    	} else {
5230    		startOptions.showCurrentAtPos = 1;
5231    	}
5232    	
5233    	//number of months must be '1' (cannot use UI.getDatepickerMonths() ) because if show more than 1 month then datepicker on start overlaps left side of screen on client history report
5234    	var jstart = jhead.find('#report-start').datepicker(startOptions);
5235		var jend = jhead.find('#report-end').datepicker(endOptions);
5236		
5237		var dtStart = jhead.find('label[for="report-start"]').attr('inital_date');
5238    	var dtEnd = jhead.find('label[for="report-end"]').attr('inital_date');
5239    	
5240    	if (UTIL.isDate(dtStart)) {
5241	    	dtStart = new Date(dtStart).toSADate(true);
5242	    	jstart.val(dtStart);
5243		}
5244		
5245		if (UTIL.isDate(dtEnd)) {
5246			dtEnd = new Date(dtEnd).toSADate(true);
5247			jend.val(dtEnd)
5248		}
5249    }
5250    
5251    _conRptTemplate.initStaffFilter = function(isAddHelloBar) {
5252		GLO.Report.initStaffFilter(isAddHelloBar);
5253		return;
5254		/* if (!UTIL.isEmpty(GLO.Uri.query('sfilter'))) {
5255        	var sfilter = GLO.Uri.query('sfilter');
5256        	var jdd = $('#header-navigation-links #staff-filter');
5257        	
5258        	if (jdd.length === 0) { jdd = $('#hd-parent #staff-filter'); }
5259        	
5260        	var option = jdd.find('option[value="' + sfilter + '"]');
5261        	
5262        	if (option.length > 0) {
5263        		//jdd.val(sfilter).change();						//Apr 2016: was throwing invalid begin date warning message.
5264        	} else {
5265        		jdd.find('option#staff-filter-custom').prop('selected', true);
5266        	}
5267        } */
5268	}
5269	
5270    _conRptTemplate.movePrev = function() {
5271        _conRptTemplate.moveDates(-1);
5272        _moveSearch();
5273    }
5274    _conRptTemplate.moveNext = function() {
5275        _conRptTemplate.moveDates(1);
5276        _moveSearch();
5277    }
5278    function _moveSearch() {
5279    	var jsearch = $('.report-search-header:visible').find('.btnSearch > a');
5280        
5281        if (jsearch.length === 1) {
5282        	jsearch.click();
5283        } else { 
5284        	_conRptTemplate.search();
5285        }
5286    }
5287    
5288    function _getSearchDate(jdt) {
5289    	if (jdt.hasClass('is-sa-date')) {
5290    		var dt = UTIL.fromSADate(jdt.val());
5291    	} else {
5292    		var dt = UTIL.replaceAll(jdt.val(), '-', '/');			//= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone).
5293    	}
5294    	
5295    	if (UTIL.isDate(dt)) {
5296            return new Date(dt);
5297        } else {
5298        	if (jdt.hasClass('Report_Begin_dt') || jdt.hasClass('Begin_dt')) {
5299        		var msg = 'start';
5300        	} else {
5301        		var msg = 'end';
5302        	}
5303        	
5304        	msg = '<div> <h1 class="friendly-msg2">' + SA.Resource.DateMissing + '</h1> <div class="friendly-msg2">' + SA.Resource.Please_enter_a + ' ' + msg + ' ' + SA.Resource.Date.toLowerCase() + '</div> </div>';
5305        	new GLO.Popup.Warning(msg, function() { jdt.focus(); });
5306        	
5307        	return null;
5308        }
5309    }
5310    
5311    _conRptTemplate.addMonthsToEndDate = function(dt, monthCount) {
5312    	return new Date(dt.getFullYear(), dt.getMonth() + monthCount + 1, 0)
5313    }
5314    
5315    _conRptTemplate.isMonthRange = function(dt1, dt2) {
5316    	var dtNextDay = new Date(dt2);
5317    	dtNextDay = new Date(dtNextDay.setDate(dtNextDay.getDate() + 1));
5318        
5319        if (dt1.getDate() === 1 && dtNextDay.getDate() === 1) {
5320        	return true;
5321        } else {
5322        	return false;
5323        }
5324    }
5325    
5326    _conRptTemplate.focusDate = function(selector) {
5327    	if ($('.pop-warning:visible').length === 0 || $('.pop-warning:visible').length === 0) {
5328    		$(selector).focus()
5329    	}
5330    }
5331    
5332    _conRptTemplate.moveDates = function(up) {
5333        var oneDay = 24 * 60 * 60 * 1000; 						//hours * minutes * seconds * milliseconds.
5334        var j = $('.report-search-header:visible');
5335        var jBegin = j.find('.Report_Begin_dt');
5336        var jEnd = j.find('.Report_End_dt');
5337        
5338        if (jBegin.length === 0) { jBegin = j.find('.Begin_dt'); }
5339        if (jEnd.length === 0) { jEnd = j.find('.End_dt'); }
5340        
5341        if (jBegin.length === 0) { jBegin = j.find('#report-start'); }
5342        if (jEnd.length === 0) { jEnd = j.find('#report-end'); }
5343        
5344        var dt1 = _getSearchDate(jBegin);
5345        if (dt1 === null) { return; }
5346        var dt2 = _getSearchDate(jEnd);
5347        if (dt2 === null) { return; }
5348        
5349        if (_conRptTemplate.isMonthRange(dt1, dt2)) {
5350        	var monthCount = up * (dt2.getMonth() - dt1.getMonth() + (12 * (dt2.getFullYear() - dt1.getFullYear())) + 1);
5351        	dt1 = new Date(dt1.setMonth(dt1.getMonth() + monthCount));
5352        	dt2 = GLO.Report.Template.addMonthsToEndDate(dt2, monthCount);
5353        } else if (dt1.getTime() == dt2.getTime()) {
5354        	dt1 = new Date(dt1.setDate(dt1.getDate() + up));
5355        	dt2 = new Date(dt2.setDate(dt2.getDate() + up));
5356        } else {
5357        	var dayCount = up * Math.round(Math.abs((dt2.getTime() - dt1.getTime())/(oneDay))) + up * 1;
5358        	
5359        	dt1 = new Date(dt1.setDate(dt1.getDate() + dayCount));
5360        	dt2 = new Date(dt2.setDate(dt2.getDate() + dayCount));
5361        }
5362        
5363        UI.setDateInput(jBegin, dt1);
5364        UI.setDateInput(jEnd, dt2);
5365    }
5366    
5367    _conRptTemplate.validateDates = function(start, end, isBackgroun
5367dSearch) {
5368    	if (!UTIL.isDate(start)) {
5369            if (!isBackgroundSearch) {
5370            	GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('.Report_Begin_dt:visible'); });
5371            }
5372            
5373            return false;
5374        } else if (!UTIL.isDate(end)) {
5375            if (!isBackgroundSearch) {
5376            	GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('.Report_End_dt:visible'); });
5377            }
5378            
5379            return false;
5380        } else if (new Date(start) > new Date(end)) {
5381            if (!isBackgroundSearch) {
5382            	GLO.Popup.Warning(SA.Resource.BeginDateWarning2);
5383            }
5384            
5385            return false;
5386        }
5387        
5388        return true;
5389    }
5390    
5391    function _getHash(jhead, jrpt, isBackgroundSearch, report, start, end) {
5392    	var sfilter = GLO.Uri.query('sfilter');		//if (GLO.Info.isMobile() && UTIL.isEmpty(sfilter)) { sfilter = jrpt.find('#staff-filter').val(); }
5393        
5394        if (report == 'sales-summary' && sfilter == -1) {
5395        	GLO.Staff.Filter.removeFilter();
5396        	return null;
5397        }
5398        
5399        /*
5400    	if (GLO.Report.staffFilter !== null) {
5401            var sfilter = GLO.Report.staffFilter;
5402            GLO.Report.staffFilter = null;
5403        } else {
5404            var sfilter = GLO.Uri.query('sfilter');
5405        }
5406        */
5407        
5408        var uhash = 'sfilter=' + sfilter + '&report=' + report + '&start=' + start + '&end=' + end;
5409        
5410        var svcFilter = jhead.find('.Service_Filter').val();
5411        if (!UTIL.isEmpty(svcFilter)) { uhash += '&servicefilter=' + svcFilter; }
5412		
5413		var jInventoryFilter = jhead.find('.Inventory_Filter:visible');
5414        
5415        if (jInventoryFilter.length === 0) { jInventoryFilter = $('#report-product-history:visible .Inventory_Filter'); }
5416        
5417        var inventoryFilter = jInventoryFilter.val();
5418        
5419        if (!UTIL.isEmpty(inventoryFilter)) {
5420        	uhash += '&inventoryfilter=' + inventoryFilter;
5421        } else if (jhead.find('.Inventory_Filter:visible').hasClass('required')) {
5422        	if (!isBackgroundSearch) {
5423        		new GLO.Popup.Warning(SA.Resource.PleaseSelectAProduct, function() { jhead.find('.Inventory_Filter:visible').focus(); });
5424        	}
5425        	
5426        	return null;
5427        }
5428        
5429        var paymeth = jhead.find('.Payment_Method_cd:visible, .Payment_Method_cd.use').val();
5430        if (!UTIL.isEmpty(paymeth)) { uhash += '&paymethod=' + paymeth; }
5431        
5432        var jpopular = jrpt.parent().find('.popular-input:visible');
5433        if (jpopular.length > 0) {
5434        	if (jpopular.find('#radio-popular-most-services, #radio-popular-most-products').prop('checked')) {
5435        		uhash += '&most_popular_nr=' + jpopular.find('.number-popular-most').val();
5436        	} else if (jpopular.find('#radio-popular-least-services, #radio-popular-least-products').prop('checked')) {
5437        		uhash += '&least_popular_nr=' + jpopular.find('.number-popular-least').val();
5438        	}
5439        }
5440        
5441        if (report === 'sales-history') {
5442        	if ($('#hello-bar-gift-card').length > 0) {
5443	        	var gcid = GLO.Uri.query('giftcard');
5444	        	
5445	        	if (!UTIL.isEmpty(gcid)) {
5446	        		uhash += '&giftcard=' + gcid;
5447	        	}
5448        	}
5449        	
5450        	if (jhead.parent().find('#Include_Unpaid_Tickets_fl').prop('checked')) {
5451        		uhash += '&include-unpaid=1';
5452        	}
5453        }
5454        
5455        var jforecast = jhead.parent().find('.report-search-forecast #Include_Forecast_fl');
5456		
5457		if (jforecast.length === 1 && jforecast.prop('checked')) {
5458			uhash += '&forecast=1';
5459		}
5460		
5461		var processedBy = jhead.find('#Payment_Processed_By_id:visible').val();
5462		
5463		if (!UTIL.isEmpty(processedBy)) {
5464			uhash += '&processedby=' + processedBy;
5465		}
5466		
5467        uhash += _getClientFilter(jhead);
5468        return uhash
5469    }
5470    
5471    function _getClientFilter(jhead) {
5472    	var jclient = jhead.find('#Client_Filter_id');
5473        
5474        if (jclient.length > 0 && !UTIL.isEmpty(jclient.val())) {
5475        	var cid = jclient.attr('autoId');
5476        	
5477        	if (!UTIL.isEmpty(cid)) {
5478        		return '&client=' + cid;
5479        	}
5480        }
5481        
5482        return '';
5483    }
5484    
5485    function _getReportUrl(start, end) {
5486    	
5487    }
5488    
5489    _conRptTemplate.search = function(exportToExcel, jrpt) {
5490        if (jrpt !== undefined) {
5491        	var isBackgroundSearch = true;
5492        } else {
5493        	jrpt = $('.inventory-report:visible, .entire-report:visible');
5494        	var isBackgroundSearch = false;
5495        }
5496        
5497        var jhead = jrpt.find('.report-search-header');					// var jhead = $('.report-search-header:visible');
5498        var start = jhead.find('.Report_Begin_dt').val();
5499        var end = jhead.find('.Report_End_dt').val();
5500        
5501        if (start === undefined) {
5502        	var start = jhead.find('.Begin_dt').val();
5503        	var end = jhead.find('.End_dt').val();
5504        }
5505        
5506        if (!_conRptTemplate.validateDates(start, end, isBackgroundSearch)) { return; }
5507        
5508        var report = jrpt.attr('id').replace('report-', '');
5509        jrpt = jrpt.find('.inventory-report-container, .report-container');
5510        
5511        var uhash = _getHash(jhead, jrpt, isBackgroundSearch, report, start, end);
5512        if (UTIL.isEmpty(uhash)) { return; }
5513        
5514        if (jhead.find('#Date_Range_Type_Pay_fl').prop('checked')) {
5515        	uhash += '&ispaydate=1';
5516        }
5517        
5518        var url = GLO.Link.Page.Provider.Home + 'report/search?' + uhash;
5519        var pageUrl = document.location.origin + document.location.pathname + '?isfullpage=1&' + uhash.replace('report=sales-history&', '');
5520        var searchBtn = null;
5521        var isIncludeDetail = (jrpt.find('#sales-summary-ticket-info:visible').length > 0);
5522        var reportPassword = $.trim($('#report-password-container #Report_Password_vc').val());
5523        var jdPost = { "report_password_vc": reportPassword };
5524        
5525        if (exportToExcel) {
5526        	var btnExport = jhead.parent().find('.btnExportToExcel');
5527        	GLO.UI.Form.beginProcessing(btnExport);
5528        	
5529        	window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 2500);
5530        	
5531        	url += '&ExportToExcel=1';
5532        	var childWindow = UI.openChildWindow(url, '', true);
5533        	
5534        	return;
5535        } else {
5536        	searchBtn = jhead.parent().find('.btnSearch');
5537        	GLO.UI.Form.beginProcessing(searchBtn);
5538        }
5539        
5540        if (_isRefreshReportScreen(report, start, end, isIncludeDetail)) {
5541        	return;
5542        } else if (isIncludeDetail) {
5543        	url += '&include_detail_fl=1';
5544        }
5545        
5546        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jdPost })
5547            .success(function(data, textStatus, jqXHR) {
5548                if (searchBtn !== null) { GLO.UI.Form.resetProcessing(searchBtn); }
5549                
5550                if (jrpt.find('#sales-summary-container').length > 0) {						//#report-table-sales-summary
5551                	var jdata = $('<div>' + data + '</div>');
5552                	data = GLO.Report.Sales.preInitSalesSummary(jdata, true);
5553                }
5554                
5555                if ($(data).find('.no-results-report-role #Report_Password_vc').length) {
5556                	jrpt.html(data);
5557                } else if (!UTIL.isEmpty(data)) {
5558                    if (report === 'sales-summary') {
5559                    	data = GLO.Report.Sales.initSummaryChart(data);
5560                    	$('#ssh-payment-column').remove();				//cash drawer + incorrect payments are not re-freshed on search (+ issue because report loaded incorrect payments report container as well).
5561                    }
5562                    
5563                    jrpt.html(data);
5564                    UI.initTableSorter( jrpt.find('table.tablesorter') );
5565                    GLO.Report.Sales.hideCommissionColumn(jrpt);
5566                    _conRptTemplate.hideEmptyColumn(jrpt, 'column-profit');
5567                    GLO.Report.enableFullPageCheck();
5568                    
5569                    if (report == 'product-history') {
5570                    	GLO.Report.CellSummary.initReport(jrpt, true, true);
5571                    } else if (report == 'payment-history') {
5572                    	GLO.Report.CreditCard.postSearch(jrpt, report);
5573                    } else if (report == 'returns-exchanges') {
5574                    	GLO.Inventory.Reports.loadReturnReport(jrpt);
5575                    } else if (report === 'sales-summary') {
5576                    	var jcontainer = jrpt.closest('#report-sales-summary');
5577                    	
5578                    	if (GLO.Report.Sales.postInitSalesSummary(jcontainer, true)) {
5579	                    	var jbtns = $('#sales-summary-ticket-buttons');
5580	                		
5581		                	if (jbtns.find('#sales-average-ticket-on').hasClass('selected')) {
5582		                		GLO.Report.Sales.switchToTicketAverage(true);
5583		                	}
5584		                	
5585		                	GLO.Report.Sales.createSummaryChart();
5586	                	}
5587                    } else if (report === 'popular-products' || report === 'popular-services' || report === 'sales-history') {
5588                    	GLO.Report.CellSummary.initReport(jrpt, true, true);
5589                    	GLO.Report.Sales.loadHistory();
5590                    	
5591                    	if (report === 'sales-history') {
5592                    		GLO.Report.Sales.initPaymentDetailReport();
5593                    	}
5594                    }
5595                    
5596                    GLO.Report.initIcons(jrpt);
5597                } else {
5598                    GLO.Popup.Info(SA.Resource.NoResultsFound);
5599                }
5600                
5601                if (document.location.pathname.toLowerCase() === "/reports/saleshistory") {
5602                	window.history.pushState('', 'Sales History', pageUrl);
5603                	document.title = _getPageTitle(jhead, start, end);
5604                	GLO.Report.Sales.loadPaymentDetailReport();
5605                }
5606                
5607                if (GLO.Info.isMobile(true) || GLO.Mobile.isTablet) {
5608                	var jlinks = $('#sales-summary-ticket-info').find('a');
5609                	GLO.UI.initAnimateLink(jlinks, 4, GLO.UI.pinkify);
5610                }
5611            })
5612            .error(function(jqXHR, textStatus, errorThrown) {
5613                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
5614                GLO.UI.Form.resetProcessing(searchBtn);
5615            });
5616    }
5617    
5618    function _isRefreshReportScreen(report, start, end, isIncludeDetail) {			//= if just refreshing current day then refresh report page so report is in dashboard mode (looks up incorrect payments, cash drawer, + payment summary)
5619    	if (report === 'sales-summary') {
5620    		if (new Date(start).toGloDate() === new Date().toGloDate() && new Date(end).toGloDate() === new Date().toGloDate()) {
5621    			var url = location.origin + location.pathname;
5622    			var sfilter = GLO.Uri.url('sfilter');
5623    			var isIncludeForecast = $('#report-sales-summary #Include_Forecast_fl').prop('checked');
5624    			
5625    			if (isIncludeDetail) {
5626    				url = GLO.Uri.addQueryKeyAndValue(url, 'include_detail_fl=1');
5627    			}
5628    			
5629    			if (!isIncludeForecast) {
5630		        	url = GLO.Uri.addQueryKeyAndValue(url, 'forecast=0');
5631		        }
5632		        
5633    			if (!UTIL.isEmpty(sfilter)) {
5634    				url = GLO.Uri.addQueryKeyAndValue(url, 'sfilter=' + sfilter);
5635    			}
5636    			
5637    			setTimeout(function() {
5638    				document.location = url;
5639    			}, 100);
5640    			
5641    			return true;
5642    		}
5643    	}
5644    	
5645    	return false;
5646    }
5647    
5648    _conRptTemplate.hideEmptyColumn = function(jcontainer, className, isInputText, hideClass, isNoteField) {
5649    	var tds = jcontainer.find('tbody').find('.' + className);
5650    	hideClass = UTIL.coalesceString(hideClass, 'hideX');
5651    	
5652    	if (_columnIsEmpty(tds, isInputText, isNoteField)) {
5653    		jcontainer.find('.' + className).addClass(hideClass);
5654    		return true;
5655    	} else {
5656    		return false;
5657    	}
5658    }
5659    
5660    function _columnIsEmpty(jcolumn, isInputText, isNoteField) {
5661    	var total = 0;
5662    	
5663    	for (var i=0; i < jcolumn.length; i++) {
5664    		if (isInputText) {
5665    			var text = jcolumn.eq(i).find(':text').val();
5666    		} else {
5667    			var text = jcolumn.eq(i).text();
5668    		}
5669    		
5670    		if (isNoteField) {
5671    			if (!UTIL.isEmpty(text)) {
5672    				return false;
5673    			}
5674    		} else {
5675    			total += UTIL.coalesceMoney($.trim(text).replace('$', '').replace(' ', ''));
5676    		}
5677    	}
5678    	
5679    	if (total == 0) {
5680    		return true;
5681    	} else {
5682    		return false;
5683    	}
5684    }
5685    
5686    function _getPageTitle(jhead, start, end) {
5687    	var jpaymeth = jhead.find('.Payment_Method_cd:visible, .Payment_Method_cd.use');
5688        var title = 'Sales Detail: ';
5689        
5690        if (!UTIL.isEmpty(jpaymeth.val())) {
5691        	title = jpaymeth.find(':selected').text().replace(' Payments', '') + ' Payment Detail: ';
5692        }
5693        
5694        if (UTIL.isDate(start) && UTIL.isDate(end)) {
5695        	title += start + ' - ' + end;
5696        }
5697        
5698        return title;
5699    }
5700    
5701    _conRptTemplate.goToReport = function(event, url, sfilter, element) {
5702    	if (event && event.target && element === undefined) {
5703    		element = event.target;
5704    	}
5705    	
5706    	GLO.Uri.gotoReport(url, element, sfilter, null, null, event);
5707    	return;
5708    	
5709    	if (sfilter === 'h') { sfilter = GLO.Staff.Filter.getHouseStaff(); }
5710    	if (!UTIL.isEmpty(sfilter)) { url = url + '&sfilter=' + sfilter; }
5711    	
5712    	if (SA.Menu.isRequirePIN(url, null, event)) {
5713    		return false;
5714    	}
5715    	
5716    	if (event.ctrlKey || event.altKey) {
5717    		window.open(url);
5718    	} else {
5719    		document.location = url;
5720    	}
5721    }
5722    
5723    return _conRptTemplate;
5724})();
5725
5726
5727GLO.Report.Template2 = (function() {
5728    function _conRptTemplate2() { }
5729    
5730    _conRptTemplate2.init = function(reportName, start, end) {
5731		GLO.Staff.Filter.isReportPortal = true;
5732		
5733		if (!GLO.Report.Sales.initStaffFilter()) {
5734			GLO.Report.Template.initStaffFilter(true);
5735		}
5736		
5737		$('#header-icon-container').remove();
5738		
5739		var j = $('#report-main');
5740        UI.initTableSorter2( j.find('table.tablesorter') );
5741        
5742        var jhead = $('.report-search-header');
5743        GLO.Report.Template.initDateRange(jhead, true);
5744        
5745        if (start) { jhead.find('#report-start').val(start); }
5746        if (end) { jhead.find('#report-end').val(end); }
5747        if (reportName) { GLO.Report.portalName = reportName; }
5748		
5749		GLO.Report.setupFastClick();
5750	}
5751	
5752	_conRptTemplate2.getBlueThrobber = function(css) {
5753		var blueThrobber = '<img id="imgThrobber" src="' + GLO.Data.cdnDirectory + 'image/icon/throbber-blue.gif" style="' + UTIL.cleanString(css) + '"/>';
5754        return '<div id="imgThrobberContainer" style="height: 100%; width: 100%; text-align: center;">' + blueThrobber + '</div>';
5755	}
5756	
5757	function _displayBlueThrobber(appendTo) {
5758    	$('#simplemodal-container, .glopop, #doc3').find('#imgThrobber').remove();
5759        
5760        var htmThrobber = _conRptTemplate2.getBlueThrobber('height: 60px; margin: auto; margin-top: 24px; margin-bottom: 12px;');
5761        
5762        if (appendTo) {
5763        	appendTo.append(htmThrobber);
5764        } else {
5765        	var j = $('.report-container');
5766        	var jNoResults = j.find('.no-results');
5767        	
5768        	if (jNoResults.length > 0) {
5769        		jNoResults.replaceWith(htmThrobber);
5770        	} else {
5771        		j.append(htmThrobber);
5772        	}
5773        }
5774    }
5775    
5776    _conRptTemplate2.search = function(reportUrlName, isDisplayThrobber, fnOnSearchComplete) {
5777    	var jrpt = $('#report-main');
5778    	var btnSearch = jrpt.find('.btnSearch');
5779    	var pageTitle = UTIL.directTagOnly($('#report-header-text'));
5780    	var qstring = '', sids = GLO.Uri.url('sfilter');
5781    	var jGiftFilter = $('#gift-card-filter');
5782    	
5783    	if (UTIL.isEmpty(pageTitle)) {
5784    		pageTitle = UTIL.directTagOnly($('#bd h1'));
5785    		
5786    		if (UTIL.isEmpty(pageTitle)) {
5787    			pageTitle = UTIL.directTagOnly($('#bd h1 > b'));
5788    		}
5789    	}
5790    	
5791    	if (!UTIL.isEmpty(sids)) {
5792    		qstring += '&sfilter=' + sids;
5793    		var sfilter = $('#staff-filter').find('option:selected').text();
5794    		
5795    		if (UTIL.coalesce(sfilter, 'all').toLowerCase() != 'all') {
5796    			pageTitle += ' ' + sfilter;
5797    		}
5798    	}
5799    	
5800    	if (jGiftFilter.length === 1) {
5801	    	var ifilter = $.trim($('#gift-report-header-product-list #Gift_Product_List').val());
5802	    	
5803	    	if (jGiftFilter.find('#gift-option-all-with-balance').prop('checked')) {
5804	    		pageTitle = 'All Gift Cards with a Balance'
5805	    		qstring += '&allWithBalance=1&ifilter=' + ifilter;
5806	    	} else if (jGiftFilter.find('#gift-option-number').prop('checked')) {
5807	    		var gcnr = UTIL.replaceAll(jGiftFilter.find('#Gift_Number_vc').val(), '#', '');
5808	    		
5809	    		if (UTIL.isEmpty(gcnr)) {
5810	    			var msg = '<p>Please Enter Gift Card Number</p><p>or select <i>date range</i> or <i>all cards with a balance</i></p>';
5811	    			GLO.Popup.Warning.open(msg, 'Enter Gift Card Number', function() { jGiftFilter.find('#Gift_Number_vc').focus(); });
5812	    			return;
5813	    		}
5814	    		
5815	    		pageTitle = 'Sale & Reloads for Gift Card: ' + gcnr;
5816	    		qstring += '&gcnr=' + gcnr;
5817	    	} else if (jGiftFilter.find('#gift-option-client-name').prop('checked')) {
5818	    		var jclient = jGiftFilter.find('#Gift_Client_Name_vc');
5819    			var cid = jclient.attr('autoId');
5820    			
5821	    		if (!UTIL.isEmpty(cid)) {
5822	    			pageTitle = 'Gift Card: ' + jclient.val();
5823	    			qstring += '&client=' + cid;
5824	    		} else {
5825	    			var htm = 'Please enter client name or select a different search filter option';
5826	    			var fn = function() { $('#doc3 #Gift_Client_Name_vc').focus(); };
5827	    			GLO.Popup.Warning.open(htm, 'Enter Client Name', fn);
5828	    			return;
5829	    		}
5830	    	} else {
5831	    		var start = jGiftFilter.find('#report-start:visible').val();
5832	    		var end = jGiftFilter.find('#report-end:visible').val();
5833	    	 	pageTitle += ': ' + start + ' - ' + end;
5834	    		qstring += '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&ifilter=' + ifilter;
5835	    	}
5836    	} else {
5837    		var start = jrpt.find('#report-start:visible').val();
5838    		var end = jrpt.find('#report-end:visible').val();
5839    	 	pageTitle = $.trim(pageTitle) + ': ' + start + ' - ' + end;
5840    		qstring += '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true);
5841    	}
5842    	
5843    	if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); }
5844        
5845    	GLO.UI.Form.beginProcessing(btnSearch);
5846        
5847        var url = GLO.Link.WebsiteDomain + 'report/' + reportUrlName + '?' + qstring;
5848        var jRptData = jrpt.find('.report-container');
5849        var jd = {};
5850        
5851        if (!GLO.Report.hasReportPassword(jd)) {
5852	    	return;
5853	    } else if (isDisplayThrobber) {
5854        	_displayBlueThrobber();
5855        }
5856        
5857        $.ajax({ type: "POST", url: (url + '&ispartial=1'), "cache": false, "data": jd })
5858            .success(function(data, textStatus, jqXHR) {
5859                GLO.UI.Form.resetProcessing();
5860                
5861                if (fnOnSearchComplete) {
5862                	fnOnSearchComplete(jRptData, data);
5863                } else {
5864                	jRptData.html(data);
5865		        }
5866		        
5867		        UI.initTableSorter2(jRptData.find('table.tablesorter'));
5868		        
5869		        window.history.pushState("", pageTitle, url);
5870		        
5871		        if (reportUrlName === 'GiftCardSales') {
5872		        	var isLookupDates = !$('#gift-option-all-with-balance').prop('checked');
5873    				GLO.Report.CellSummary.initReport(jRptData, isLookupDates, true);
5874    				GLO.Report.initIcons(jRptData);
5875    				UserPortal.Price.GiftCard.loadAfterSearch();
5876		        }
5877            })
5878            .error(function(jqXHR, textStatus, errorThrown) {
5879                GLO.UI.Form.resetProcessing();
5880                GLO.Popup.Error('Unable to lookup data at this time.  Please try again.');
5881                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
5882            });
5883    }
5884    
5885    _conRptTemplate2.hideHeaderHelp = function(element) {
5886    	var jhelp = $('#report-header-help');
5887    	jhelp.find('.emphasize-only').slideUp(1400, function() { });
5888    	
5889    	setTimeout(function(){
5890    		$('#report-header-help').removeClass('emphasize');
5891    		jhelp.find('.de-emphasize-only').slideDown(600);
5892    	}, 800);
5893    }
5894    
5895    _conRptTemplate2.displayHeaderHelp = function(element) {
5896    	var jhelp = $('#report-header-help');
5897    	
5898    	jhelp.find('.de-emphasize-only').slideUp(400, function() {
5899    		
5900    	});
5901    	
5902    	jhelp.find('.emphasize-only').slideDown(1800, function() {
5903			jhelp.addClass('emphasize');
5904		});
5905    }
5906    
5907    _conRptTemplate2.searchCompleteFade = function(jrpt, data) {
5908    	jrpt.css({ "display": "none" }).html(data).slideDown(2400);
5909    	var jhelp = $('#report-header-help');
5910    	
5911    	jhelp.find('.emphasize-only').slideUp(2400, function() {
5912    		$('#report-header-help').find('.close-icon').removeClass('hide');
5913    	});
5914    	
5915    	setTimeout(function(){
5916    		$('#report-header-help').find('.de-emphasize-only').css({ "display": "none" }).slideDown(600);
5917    		$('#report-header-help').removeClass('emphasize');
5918    	}, 1800);
5919    }
5920    
5921    _conRptTemplate2.goToReport2 = function(url, event, isLookupDate, sfilter, element) {
5922    	var reportName2 = '', reportName = 'Report';
5923    	var jheader = $('#simplemodal-container .report-header, .glopop .report-header');
5924    	
5925    	if (jheader.length === 0) {
5926    		jheader = $('#bd .report-header');
5927    	}
5928    	
5929    	var jheaderText = jheader.find('.report-header-text');
5930    	
5931    	if (jheaderText.length) {
5932    		var reportName2 = UTIL.directTagOnly(jheaderText);
5933    	} else {
5934    		var reportName2 = UTIL.directTagOnly(jheader);
5935    	}
5936    	
5937    	if (reportName2.length) {
5938    		reportName = reportName2.replace('Report').replace('report') + ' Report';
5939    	}
5940    	
5941    	return _conRptTemplate2.goToReport(reportName, url, event, isLookupDate, sfilter, element);
5942    }
5943    _conRptTemplate2.goToReport = function(reportName, url, event, isLookupDate, sfilter, element) {
5944    	if (event && event.target && element === undefined) {
5945    		element = event.target;
5946    	}
5947    	
5948    	GLO.Uri.gotoReport(url, element, sfilter, isLookupDate, reportName, event);
5949    	return;
5950    	
5951    	if (url.indexOf('?') === -1 && url.indexOf('#') === -1) { url += '?'; }
5952    	if (sfilter === 'h') { sfilter = GLO.Staff.Filter.getHouseStaff(); }
5953    	if (!UTIL.isEmpty(sfilter)) { url += '&sfilter=' + sfilter; }
5954    	
5955    	if (isLookupDate) {
5956    		var jhead = $('.report-search-header:visible');
5957    		
5958    		if (jhead.length) {
5959    			var start = jhead.find('.Report_Begin_dt').val();
5960    			var end = jhead.find('.Report_End_dt').val();
5961    			
5962    			if (UTIL.isDate(start)) { url += '&start=' + new Date(start).toGloDate(); }
5963    			if (UTIL.isDate(end)) { url += '&end=' + new Date(end).toGloDate(); }
5964    		}
5965    	}
5966    	
5967    	if (SA.Menu.isRequirePIN(url, null, event)) {
5968    		return false;
5969    	}
5970    	
5971    	GLO.Popup.Processing.open('Loading ' + UTIL.cleanString(reportName) + '...', reportName);
5972    	url = GLO.Link.WebsiteDomain + url;
5973    	
5974    	setTimeout(function() {
5975	    	if (event && (event.ctrlKey || event.altKey)) {
5976	    		window.open(url);
5977	    	} else {
5978	    		document.location = url;
5979	    	}
5980    	}, 100)
5981    }
5982    
5983    return _conRptTemplate2;
5984})();
5985
5986
5987GLO.Report.ProductActivity = (function() {
5988	function _conProductActivity() { }
5989	_conProductActivity.isProductSummaryReport = false;
5990	
5991	_conProductActivity.init = function() {
5992		var jfilter = $('#report-product-activity-filter');
5993		var jco = jfilter.find('#report-product-activity-company');
5994		var jhead = $('.report-search-header .report-search-header-table');
5995		
5996		jfilter.find('.Report_Begin_dt').attr('id', 'Begin_dt');
5997		jfilter.find('.Report_End_dt').attr('id', 'End_dt');
5998		
5999		var filter = UTIL.coalesce(GLO.Uri.query('inventoryfilter'), GLO.Uri.query('inventory-filter'));
6000		jco.find('#Filter_Company').val(filter);
6001		
6002		jhead.find('#rpt-filter-pay-method, .report-list-line').remove();
6003		jhead.find('td:first').append(jco);
6004		
6005		$('.report-inventory-header-search').attr('onclick', 'GLO.Report.ProductActivity.search()');
6006		
6007		GLO.Report.Template.init();
6008		_initData(filter);
6009		
6010		jfilter.css({ "visibility": "" });
6011		GLO.Report.enableFullPageCheck();
6012		
6013		_conProductActivity.isProductSummaryReport = true;
6014		UserPortal.Lookup.initMonitorQRScan();
6015	}
6016	
6017	function _initData(inventoryFilter) {
6018		var tbl = $('#report-product-activity');
6019		
6020		tbl.find('td.column-brand-name').click(GLO.Report.ProductActivity.searchRow);
6021		tbl.find('td.column-product-line-name').click(GLO.Report.ProductActivity.searchRow);
6022		//tbl.find('td.column-product-name').click(GLO.Report.ProductActivity.gotoProductHistory);
6023		
6024		var jh2 = $('#report-inventory-h2');
6025		
6026		_addNoBrandOption(tbl);
6027		
6028		if (UTIL.isEmpty(inventoryFilter)) {
6029			jh2.find('.h2text').text('Product Activity Summary');
6030			jh2.find('#report-activity-h2-arrow').addClass('hide');
6031			
6032			tbl.find('#product-activity-detail-help').addClass('hide');
6033			tbl.find('#product-activity-summary-help').removeClass('hide');
6034		} else {
6035			jh2.find('.h2text').text('Product Activity Detail');
6036			jh2.find('#report-activity-h2-arrow').removeClass('hide');
6037			
6038			var filter = '<i style="color: rgb(80, 180, 200);">' + $.trim(tbl.find('#Filter_Company option:selected').text()) + '</i>';
6039			
6040			tbl.find('#product-activity-detail-help').removeClass('hide').find('b').html('for each ' + filter + ' product');
6041			tbl.find('#product-activity-summary-help').addClass('hide');
6042		}
6043		
6044		GLO.Report.CellSummary.initReport(tbl, true, true);
6045		GLO.Report.initIcons(tbl);
6046	}
6047	
6048	function _addNoBrandOption(tbl) {
6049		if (tbl.find('tr[vendor_id=1]').length > 0) {
6050			var jco = $('#report-product-activity-company #Filter_Company');
6051			
6052			if (jco.find('option[value="v1"]').length === 0) {
6053				jco.append('<option class="v-option" value="v1">( No Brand )</option>');
6054			}
6055		}
6056	}
6057	
6058	_conProductActivity.gotoProductHistory = function() {
6059		var td = $(this);
6060		var tr = td.closest('tr');
6061		var iid = td.attr('inventory_id');
6062		var name = UTIL.coalesce(td.attr('title'), td.find('a').text());
6063		
6064		var jrpt = $('#report-product-activity');
6065		
6066		var start = new Date(jrpt.find('.Report_Begin_dt').val()).toGloDate(true);
6067		var end = new Date(jrpt.find('.Report_End_dt').val()).toGloDate(true);
6068		
6069		var htm = 'Loading ' + name + ' Product History...';
6070		new GLO.Popup.Processing(htm);
6071		
6072		setTimeout(function() {
6073			document.location = document.location.protocol + '//' + document.location.host + '/reports/inventory#tab=product-history&id=' + iid + '&start=' + start + '&end=' + end;
6074		}, 100);
6075	}
6076	
6077	function _getHash(jhead, start, end, co) {
6078		var uhash = 'start=' + start + '&end=' + end + '&inventoryfilter=' + UTIL.cleanString(co);
6079		
6080		/*
6081		var ifilter = jhead.find('.Inventory_Filter:visible').val();
6082        
6083        if (!UTIL.isEmpty(ifilter)) {
6084        	uhash += '&inventoryfilter=' + ifilter;
6085        }
6086        */
6087        
6088        return uhash;
6089    }
6090	
6091	_conProductActivity.gotoTopLevel = function() {
6092		var j = $('#report-product-activity');
6093		var start = j.find('.Report_Begin_dt').val();
6094		var end = j.find('.Report_End_dt').val();
6095		
6096		var jparent = j.parent();
6097		UI.displayProcessingLayer(jparent);
6098		
6099		setTimeout(function() {
6100			document.location = document.location.protocol + '//' + document.location.host + '/reports/ProductActivity?start=' + start + '&end=' + end;
6101		}, 100);
6102	}
6103	
6104	_conProductActivity.searchRow = function() {
6105		var jrpt = $('#report-product-activity');
6106		var jfilter = jrpt.find('.report-search-header-table #Filter_Company');
6107		var td = $(this);
6108		var tr = td.closest('tr');
6109		
6110		if (UTIL.isEmpty(td.find('a').text())) { return; }
6111		
6112		if (td.hasClass('column-brand-name')) {
6113			jfilter.val('v' + tr.attr('vendor_id'));
6114		} else if (td.hasClass('column-product-line-name')) {
6115			jfilter.val('p' + tr.attr('product_line_id'));
6116		}
6117		
6118		jrpt.find('.btnSearch:visible > a').click();
6119	}
6120	
6121	_conProductActivity.search = function() {
6122        var jrpt = $('.inventory-report');
6123        var jhead = jrpt.find('.report-search-header');					// var jhead = $('.report-search-header:visible');
6124        var start = jhead.find('.Report_Begin_dt').val();
6125        var end = jhead.find('.Report_End_dt').val();
6126        var co = jhead.find('#Filter_Company').val();
6127        var isBackgroundSearch = false, jd = {};
6128        
6129        if (!GLO.Report.Template.validateDates(start, end, isBackgroundSearch)) {
6130        	return;
6131        } else if (!GLO.Report.hasReportPassword(jd)) {
6132	    	return;
6133	    }
6134	    
6135	    var uhash = _getHash(jhead, start, end, co);
6136        var jrpt = jrpt.find('.inventory-report-container');
6137        
6138        var url = GLO.Link.Page.Provider.Home + 'report/ProductActivity?ispartial=1&' + uhash;
6139        var pageUrl = document.location.origin + document.location.pathname + '?' + uhash;
6140        
6141        var searchBtn = searchBtn = jhead.parent().find('.btnSearch');
6142        GLO.UI.Form.beginProcessing(searchBtn);
6143        
6144        var jqxhr = $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd })
6145            .success(function(data, textStatus, jqXHR) {
6146                if (searchBtn !== null) { GLO.UI.Form.resetProcessing(searchBtn); }
6147                
6148                if (!UTIL.isEmpty(data)) {
6149                    jrpt.html(data);
6150                    UI.initTableSorter( jrpt.find('table.tablesorter') );
6151                    _initData(co);
6152                } else {
6153                    GLO.Popup.Info(SA.Resource.NoResultsFound);
6154                }
6155                
6156                var htitle = 'Product Activity ' + new Date(start).toSADate(true) + ' - ' + new Date(end).toSADate(true);
6157                window.history.pushState('', htitle, pageUrl);
6158            })
6159            .error(function(jqXHR, textStatus, errorThrown) {
6160                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
6161                GLO.UI.Form.resetProcessing(searchBtn);
6162            });
6163    }
6164    
6165    _conProductActivity.openReportHelp = function() {
6166    	var msg0 = '<p>Dashboard of activity for each product, product line, and brand as well as offers insight into your product sales profitability</p>';
6167    	var h = '<h3 style="margin-top: 24px; margin-bottom: 0; line-height: 1.8; border-radius: 28px; font-size: 131%; background-color: rgba(80, 200, 240,1);">';
6168    	
6169    	var h1 = h + 'Product Activity Summary</h3>';
6170    	var msg1 = '<p>The first report when the screen loads is the <i>Product Activity Summary report</i> which is a summary of activity for each brand / product line</p>';
6171    	
6172    	var h2 = h + 'Product Activity Detail</h3>';
6173    	var msg2 = '<p>Click a brand or product line <small>(any underlined value in the report)</small> or select a brand or product line <small>(from the drop down in the report filter)</small> to go to the <i>Product Activity Detail report</i> which displays the activity for each product in that brand / product line over the selected date range</p>';
6174    	
6175    	var h3 = h + 'Staff Access</h3>';
6176    	var msg3a = '<p>Managers and Admins have full access to this report</p>';
6177    	var msg3b = '<p>Receptionists can only see sales information <small>(not cost or profitability information)</small> specifically receptionists cannot see the last five columns (Order Cost, Total Cost, Profit, Gross Margin, and Profit Margin)</p>';
6178    	var msg3c = '<p>Other staff roles do not have access to this report</p>';
6179    	
6180    	var htm = '<div>' + msg0 + h1 + msg1 + h2 + msg2 + h3 + msg3a + msg3b + msg3c + '</div>';
6181    	var jpop = GLO.Popup.Info.open(htm, 'Inventory Activity Report').getPopup();
6182    	
6183    	jpop.attr('id', 'pop-help-inventory-activity-report').css({ "background-color": "rgb(240, 255, 255)" });
6184    }
6185    
6186    return _conProductActivity;
6187})();
6188
6189GLO.Report.Sales = (function() {
6190	function _conRptSales() { }
6191    
6192    _conRptSales.currentTab = 1;
6193    _conRptSales.MAX_TAB = 2;
6194    
6195    _conRptSales.init = function() {
6196    	var jsummary = $('#report-sales-summary');
6197    	if (jsummary.find('#report-table-sales-summary').length === 0) { $('#sales-summary-ticket-buttons').addClass('hide'); }
6198    	
6199    	_conRptSales.preInitSalesSummary(jsummary);
6200    	_conRptSales.postInitSalesSummary(jsummary);
6201    	
6202    	var initTab = GLO.Report.Template.init();				//GLO.Report.setupFastClick();
6203        
6204        if (!UTIL.isEmpty(initTab)) { 
6205            initTab = initTab.toLowerCase();
6206            
6207            if (initTab === 'sales-summary' || initTab == '1') {
6208                initTab = 1;
6209            } else if (initTab === 'sales-history' || initTab == '2') {
6210                initTab = 2;
6211            }
6212        } else {
6213            initTab = _conRptSales.currentTab;
6214        }
6215        
6216        _conRptSales.goToTab(1);					//must display summary to create chart.
6217        //_conRptSales.goToTab(initTab);
6218        _preInitSalesHistory(initTab);
6219        _initProductFilter();
6220        
6221        _initSalesSummary();
6222        _initSalesHistory(true);
6223        //_initMostPopular(true);
6224        //_initMostPopular(false);
6225        GLO.Report.Sales.createSummaryChart();
6226        
6227        $('#report-sales-trends').find('#rpt-filter-pay-method').remove();
6228        $('#report-shipment-history').find('#rpt-filter-pay-method').remove();
6229        $('#report-audit-history').find('#rpt-filter-pay-method').remove();
6230        
6231        GLO.Report.portalName = 'sales';
6232        _loadIncorrectPayments();
6233        _conRptSales.loadHistory();
6234    }
6235    
6236    _conRptSales.loadPaymentDetailReport = function() {
6237    	if (innerWidth < 500) { return; }
6238    	
6239    	var jtbl = $('#report-payment-history');
6240    	var trs = jtbl.find('tbody tr');
6241    	var hasGiftCard = false;
6242    	
6243    	for (var i=0; i < trs.length; i++) {
6244    		if (!UTIL.isEmpty(trs.find('.report-gift-card').text())) {
6245    			hasGiftCard = true;
6246    			break;
6247    		}
6248    	}
6249    	
6250    	if (hasGiftCard) {
6251    		jtbl.find('.report-gift-card').removeClass('hide');
6252    	}
6253    }
6254    
6255    function _loadIncorrectPayments(days) {
6256    	if ($('#ssh-payment-incorrect').length === 0) { return; }
6257    	
6258    	days = UTIL.coalesceInt(days, 7);
6259    	var uri = GLO.Link.WebsiteDomain + 'reports/IncorrectPayment?ispartial=1&rows=5&days=' + days;
6260    	var sfilter = GLO.Uri.query('sfilter');
6261    	
6262    	if (!UTIL.isEmpty(sfilter)) {
6263    		uri += '&sfilter=' + sfilter;
6264    	}
6265    	
6266        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false })
6267            .success(function(data, textStatus, jqXHR) {
6268                var j = $('#ssh-payment-incorrect');
6269                
6270                if ($(data).find('tbody > tr').length) {
6271                	j.removeClass('hideX');
6272                } else {
6273                	j.addClass('hideX');
6274                	return;
6275                }
6276                
6277                j.find('img').remove();
6278                j.append( $(data).html() );
6279                
6280                var tbl = j.find('.tablesorter');
6281                if (tbl.length > 0) { UI.initTableSorter(tbl); }
6282            })
6283            .error(function(jqXHR, textStatus, errorThrown) {
6284            	$('#ssh-payment-incorrect').addClass('hideX');
6285            });
6286    }
6287    
6288    _conRptSales.initHistory = function(giftCardId, giftCardNumber, giftCardBalance) {
6289    	GLO.Report.Template.init();
6290    	
6291    	_preInitSalesHistory(2);
6292    	_initProductFilter();
6293        _conRptSales.goToTab(2);
6294        _initSalesHistory(false);
6295        
6296        GLO.Report.portalName = 'sales';
6297        GLO.Report.setupFastClick();
6298        GLO.Report.Sales.initStaffFilter();
6299        
6300        _initSetHistoryHeader();
6301        _initGiftCard(giftCardId, giftCardNumber, giftCardBalance);
6302        _initSalesHistoryUrl();
6303        _conRptSales.loadHistory();
6304        
6305        _initPaymentProcessedBy();
6306        _conRptSales.initPaymentDetailReport();
6307    }
6308    _conRptSales.initPaymentDetailReport = function() {
6309    	if ($('#doc3').hasClass('is-payment-report')) {
6310    		var jheadDT = $('#report-search-header-date-range');
6311    		
6312    		/* if (innerWidth > 800) {
6313    			jheadDT.find('label[for="Begin_dt"]').text('Payment Date Range');
6314    			jheadDT.find('label[for="End_dt"]').text('-');
6315    		} */
6316    		
6317    		/* if (innerWidth > 420) {
6318    			var title = 'Filter the payments by the payment date', small = 'To filter by appointment date use a Sales Report';
6319    			var icon = '<b class="question-icon" onclick="GLO.UI.openHelp(this)" header="Filter by Payment Date" title="' + title + '" htm_small="' + small + '" alt="" alt_html="">?</b>';
6320    			jheadDT.find('td:last-child').append(icon);
6321    		} */
6322    		
6323    		var jrpt = $('#report-payment-history');
6324    		GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-service', null, null, true);
6325    		GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-product', null, null, true);
6326    		GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-note', null, null, true);
6327    		GLO.Report.Template.hideEmptyColumn(jrpt, 'report-gift-card', null, null, true);
6328    		GLO.Report.Template.hideEmptyColumn(jrpt, 'report-pay-process-by', null, null, true);
6329    	}
6330    }
6331    function _initPaymentProcessedBy() {
6332    	if (GLO.Info.roleType > 209) {
6333	    	var htmOptions = $('#staff-filter #staff-filter-s').html();
6334	    	var label = '<label for="Payment_Processed_By_id">Payment Processed By</label>';
6335	    	var select = '<select id="Payment_Processed_By_id"> <option value="">All</option>' + htmOptions + '</select>';
6336	    	var cssHide = '';
6337	    	var jFilterPayMeth = $('#rpt-filter-pay-method');
6338	    	
6339	    	if (UTIL.isEmpty(jFilterPayMeth.find('.Payment_Method_cd').val())) {
6340	    		cssHide = 'hide';
6341	    	}
6342	    	
6343	    	if ($('#report-sales-history .is-pay-history-report').length > 0) {
6344	    		jFilterPayMeth.append('<span id="filter-pay-processed-by" class="' + cssHide + '">' + label + select + '</span>');
6345	    	}
6346    	}
6347    }
6348    function _initSalesHistoryUrl() {
6349    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
6350    	var staffId = GLO.Uri.url('staff');
6351    	
6352    	if (open === 'print') {
6353    		GLO.Report.Sales.printScreenInit();
6354    	} else if (open === 'print-staff') {
6355    		if (!UTIL.isEmpty(staffId)) {
6356    			GLO.Report.Sales.printByStaff2(staffId);
6357    		} else {
6358    			GLO.Report.Sales.printByStaff();
6359    		}
6360    	}
6361    }
6362    function _initProductFilter() {
6363    	var jp = $('#report-sales-history .Inventory_Filter');
6364    	var jno = jp.find('option[value="-1"]');
6365    	var isIncludeUnpaid = $.cookies.get('sales-detail-is-include-unpaid');
6366    	
6367    	if (GLO.Provider.isValidGoldPackage()) {
6368    		if (GLO.Data.provider.MembershipList && GLO.Data.provider.MembershipList.length > 0) {
6369    			jno.after('<option value="m" title="Sales of memberships">Memberships</option>');
6370    		}
6371    		
6372    		jno.after('<option value="g" title="Sales of gift cards">Gift Card</option>');
6373    		jno.after('<option value="b" title="Only products available for internal users (like backbar products)">Internal Only (backbar)</option>');
6374    		jno.after('<option value="r" title="Only products available for retail sale">Retail Only</option>');
6375    	}
6376    	
6377    	if (UTIL.parseBool(isIncludeUnpaid) || UTIL.isEmpty(isIncludeUnpaid)) {
6378    		$('#report-sales-history #Include_Unpaid_Tickets_fl').prop('checked', true);
6379    	}
6380    }
6381    
6382    function _initGiftCard(giftCardId, giftCardNumber, giftCardBalance) {
6383    	var pmeth = $('#report-sales-history .report-search-header .Payment_Method_cd').val();
6384    	
6385    	if (pmeth == 0 || pmeth == 20) {
6386    		_initGiftCardHelloBar(giftCardId, giftCardNumber, giftCardBalance);
6387        	_conRptSales.loadPaymentDetailReport();
6388        }
6389    }
6390    
6391    function _initGiftCardHelloBar(giftCardId, giftCardNumber, giftCardBalance) {
6392    	if (UTIL.isEmpty(giftCardId)) { return; }
6393    	//var gcnr = GLO.Uri.query('giftcard');
6394    	if (UTIL.isEmpty(giftCardNumber)) { return; }
6395    	
6396    	var onclick = 'UserPortal.Price.GiftCard.openEdit(' + giftCardId + ', \'' + giftCardNumber + '\', ' + UTIL.coalesceMoney(giftCardBalance) + ')';
6397    	var label = '<b style="white-space: nowrap; padding-right: 2px;">Payments with Gift Card #' + giftCardNumber + '</b>';
6398    	
6399    	if (giftCardBalance > 0) {
6400    		label += '<b class="hell-bar-gift-balance"> Balance: ' + UTIL.displayMoney(giftCardBalance) + '</b>';
6401    	}
6402    	
6403    	var helloBar = '<div id="hello-bar-gift-card" class="hello-bar-container" style="display:none;"> <p style="padding-top: 2px;">'
6404    					+ '<span class="hello-bar-label" onclick="' + onclick + '" style="position: relative; top: inherit; left: inherit;">' + label + '</span>'
6405    					+ '<span class="hello-bar-close"> <a onclick="GLO.Report.Sales.removeGiftCardHelloBar(this, event)"> &#10006;</a> </span>'
6406    				 + '</p> </div>';
6407    	
6408    	GLO.Info.displayGiftCardHelloBar(helloBar);
6409    }
6410    
6411    _conRptSales.removeGiftCardHelloBar = function(xbutton, event) {
6412    	GLO.Uri.removeQueryKey('giftcard');
6413    	$('#hello-bar-generic, #hello-bar-gift-card').remove();
6414    	$('#report-sales-history .report-search-header .btnSearch > a').click();
6415    	$('body').removeClass('phone-has-hello-bar');
6416    }
6417    
6418    function _getSalesReportLink(url, label, isLeft, sfilter, elementClass) {
6419    	var onclick = 'GLO.Uri.gotoReport(\'' + url + '\', this, ' + sfilter + ', true)';			//(uri, element, sfilter, isLookupDate, reportName, event2, isSpinButton)
6420    	var cssClass = 'quietest ' + $.trim(elementClass);
6421    	
6422    	if (isLeft) {
6423    		cssClass += ' quietest-left';
6424    	} else {
6425    		cssClass += ' quietest-right';
6426    	}
6427    	
6428    	return '<a class="' + cssClass + '" onclick="' + onclick + '">' + label + '</a>';
6429    }
6430    
6431    function _initSetHistoryHeader() {
6432    	var jPayMeth = $('#rpt-filter-pay-method .Payment_Method_cd').change(GLO.Report.Sales.changePaymentMethod);
6433    	var jlanguage = $('#language-icon-container, #language-icons').remove();
6434    	
6435    	if (GLO.Info.roleType > 200) {
6436	    	var aPayDetail 	  = _getSalesReportLink('reports/saleshistory?isfullpage=1&paymethod=0', 'Payment Detail', true, true, 'display-on-sales-detail');
6437	    	var aSalesSummary = _getSalesReportLink('reports/sales#tab=sales-summary', 'Sales Summary', false, true, 'display-on-sales-detail');
6438	    	var aSalesDetail  = _getSalesReportLink('reports/saleshistory?isfullpage=1', 'Sales Detail', true, true, 'display-on-pay-detail');
6439	    	var aPaySummary   = _getSalesReportLink('reports/PaymentSummary', 'Payment Summary', false, false, 'display-on-pay-detail');
6440    	} else {
6441    		var aPayDetail = '', aSalesSummary = '', aSalesDetail = '', aPaySummary = '';
6442    	}
6443    	
6444    	var htext = '<b id="detail-report-header-text"></b>';
6445    	var h2 = '<h2 id="detail-report-header" class="report-header">' + aPayDetail + aSalesDetail + htext + aSalesSummary + aPaySummary + jlanguage.html() + '</h2>';
6446    	
6447    	$('.shadow0').css({ "padding-top": 0, "border-radius": "20px" });
6448    	var j = $('.shadow-content0').css({ "padding-top": 0, "border-radius": "20px" });
6449    	j.prepend(h2);
6450    	
6451    	if (jPayMeth.length) {
6452    		jPayMeth.change();
6453    	} else {
6454    		_conRptSales.changePaymentMethod();
6455    	}
6456    	
6457    	if (UTIL.isEmpty(jPayMeth.val())) {					//= hide on 'Sales Detail' full page report
6458    		jPayMeth.addClass('hide');
6459    	}
6460    }
6461    
6462    _conRptSales.loadHistory = function() {
6463    	var jrpt = $('#report-sales-history .tablesorter');
6464    	var totalFees = UTIL.coalesceMoney($.trim(jrpt.find('tfoot .column-staff-fee').text()).replace('$', ''));
6465    	var totalCommission = UTIL.coalesceMoney($.trim(jrpt.find('tfoot .commission-cell').text()).replace('$', ''));
6466    	
6467    	if (totalFees > 0) {
6468    		jrpt.find('.column-staff-fee').removeClass('hide');
6469    	}
6470    	
6471    	if (totalCommission > 0) {
6472    		jrpt.find('.commission-cell').removeClass('hide');
6473    	}
6474    	
6475    	GLO.Report.hideEmptyColumn(jrpt, 'column-due-date');
6476    	var isHideDiscount = GLO.Report.hideEmptyColumn(jrpt, 'column-discount');
6477    	var isHideAddOnFee = GLO.Report.hideEmptyColumn(jrpt, 'column-add-on');
6478    	GLO.Report.hideEmptyColumn(jrpt, 'column-staff-fee');
6479    	
6480    	if (isHideDiscount && isHideAddOnFee) {
6481    		_hideTotalColumn(jrpt);
6482    	} else if (GLO.Info.roleType > 219) {
6483    		_displayCommissionSplitNotExpected(jrpt);
6484    	}
6485    }
6486    
6487    function _displayCommissionSplitNotExpected(jrpt) {
6488    	var trs = jrpt.find('tbody tr');
6489    	
6490    	for (var i=0; i < trs.length; i++) {
6491    		var tr = trs.eq(i);
6492    		var splitCode = tr.attr('commission_split_cd'), splitAmount = tr.attr('commission_split_mn'), splitAdjust = tr.attr('commission_adjust_mn'), splitPercent = tr.attr('commission_split_pct');
6493    		var discountCount = UTIL.coalesceInt(tr.attr('discount_count_sr'), 0), feeCount = UTIL.coalesceInt(tr.attr('add_on_fee_count_sr'), 0);
6494    		var hasCustomDiscountSplit = UserPortal.Price.Discount.hasCommissionSplitByDiscountType;
6495    		var hasCustomFeeSplit = UserPortal.Price.Discount.hasCommissionSplitByFeeType;
6496    		
6497    		var isDiffDiscountSplit = (splitCode != GLO.Data.provider.commission_split_discount_cd);
6498    		var isDiffAddOnFeeSplit = (splitCode != GLO.Data.provider.commission_split_fee_cd);
6499    		
6500    		if (discountCount + feeCount > 0) {
6501    			if (discountCount > 0 && feeCount > 0) {
6502    				if (!hasCustomFeeSplit && splitCode == 2) {
6503    					_displayDiscountSplitNotExpected(tr, splitCode, splitAmount, splitAdjust, splitPercent);
6504    				} else if (!hasCustomDiscountSplit && !hasCustomFeeSplit) {
6505    					//for now only process discounts
6506    				}
6507    			} else if (isDiffDiscountSplit && (discountCount == 1 || !hasCustomDiscountSplit)) {
6508    				_displayDiscountSplitNotExpected(tr, splitCode, splitAmount, splitAdjust, splitPercent);
6509    			} else if (isDiffAddOnFeeSplit && (feeCount == 1 || !hasCustomFeeSplit)) {
6510    				//for now only process discounts
6511    			}
6512    		}
6513    	}
6514    }
6515    function _displayDiscountSplitNotExpected(tr, splitCode, splitAmount, splitAdjust, splitPercent) {
6516    	if (UserPortal.Price.Discount.hasCommissionSplitByDiscountType)  { return; }
6517    	
6518    	var price = UTIL.coalesceMoney(UTIL.removeNonNumber(tr.find('td.column-price-only').text()));
6519    	var discount = UTIL.coalesceMoney(UTIL.removeNonNumber(tr.find('td.column-discount').text()));
6520    	var fee = UTIL.coalesceMoney(UTIL.removeNonNumber(tr.find('td.add-on-discount').text()));
6521    	var isExpected = false, title = null;
6522    	var hasCustomDiscountSplit = UserPortal.Price.Discount.hasCommissionSplitByDiscountType;
6523    	
6524    	if (splitCode == 0) {					//Proportional
6525    		if (!UTIL.isDollarDiff( UTIL.coalesceMoney(splitAmount), UTIL.coalesceMoney(fee) ) && UTIL.coalesceMoney(splitAdjust, splitPercent) == 0) {
6526    			isExpected = true;
6527    		} else {
6528    			title = 'Discount commission split expected to be proportional, but is calculated differently';
6529    		}
6530    	} else if (splitCode == 1) {			//Staff
6531    		if ( !UTIL.isDollarDiff(splitAdjust, discount - fee) && UTIL.coalesceMoney(splitAmount) == 0) {
6532    			isExpected = true;
6533    		} else {
6534    			title = 'Discount commission split expected to be take from staff commission, but is calculated differently';
6535    		}
6536    	} else if (splitCode == 2) {			//Business
6537    		if (UTIL.coalesceMoney(splitAdjust) == 0 && !UTIL.isDollarDiff(splitAmount, discount)) {
6538    			isExpected = true;
6539    		} else if (!hasCustomDiscountSplit && GLO.Data.provider.commission_split_discount_cd == 2 && UTIL.isEmpty(splitAdjust) && UTIL.isEmpty(splitAmount)
6540    				&& (fee == 0 || GLO.Data.provider.commission_split_fee_cd == 2)) {
6541    			isExpected = true;
6542    		} else {
6543    			title = 'Discount commission split expected to be taken out of the business, but is calculated differently';
6544    		}
6545    	} else if (splitCode == 3) {			//Custom
6546    		if (!UTIL.isDollarDiff(splitAdjust, UTIL.coalesceMoney(splitPercent) * UTIL.coalesceMoney(discount + fee))) {
6547    			isExpected = true;
6548    		} else {
6549    			title = 'Discount commission split expected to be ' + splitPercent + '% of the discount, but is calculated differently';
6550    		}
6551    	}
6552    	
6553    	if (title) {
6554    		var tdDiscount = tr.find('td.column-discount');
6555    		var currentTitle = tdDiscount.attr('title');
6556    		
6557    		tdDiscount.attr('title', currentTitle + ' | ' + title);
6558    		tr.addClass('discount-commission-split-unexpected');
6559    	}
6560    }
6561    
6562    function _hideTotalColumn(jrpt) {				//= hide Total column if always the same as the Price column		
6563		var tdTotal = jrpt.find('tbody td.column-price-only');
6564		var tdPrice = jrpt.find('tbody td.column-price');
6565		
6566		for (var i=0; i < tdTotal.length; i++) {
6567			if (tdTotal.eq(i).text() != tdPrice.eq(i).text()) {
6568				return false;
6569			}
6570		}
6571		
6572		jrpt.find('.column-price-only').addClass('hideX');
6573		return true;
6574    }
6575    
6576    function _removeCommissionStaff() {			//= on Payment Detail report remove individual commission staff members, because payments go to the house account not each house staff
6577    	var jf = $('#hd #staff-filter');
6578    	var jfilter = jf.find('#staff-filter-s').find('option');
6579    	var jstaff = UserPortal.getStaffDropDown();
6580    	var hasHouseStaff = false;
6581    	
6582    	for (var i=0; i < jfilter.length; i++) {
6583    		var sid = jfilter.eq(i).val();
6584    		var mtype = UTIL.coalesceInt(jstaff.find('option[value="' + sid + '"]').attr('merchant_type_cd'), 99);
6585    		
6586    		if (mtype < 20) {
6587    			jfilter.eq(i).remove();
6588    			hasHouseStaff = true;
6589    		}
6590    	}
6591    	
6592    	if (hasHouseStaff || GLO.Data.provider.merchant_type_cd < 10) {
6593    		jf.find('#staff-filter-custom').remove();
6594    		jf.find('#staff-filter-sg').remove();
6595    	}
6596    }
6597    
6598    _conRptSales.initPopular = function() {
6599    	_conRptSales.MAX_TAB = 2;
6600    	var initTab = GLO.Report.Template.init();			//GLO.Report.setupFastClick();
6601        
6602        if (!UTIL.isEmpty(initTab)) { 
6603            initTab = initTab.toLowerCase();
6604            
6605            if (initTab === 'popular-services' || initTab == '1') {
6606                initTab = 1;
6607            } else if (initTab === 'popular-products' || initTab == '2') {
6608                initTab = 2;
6609            }
6610        } else {
6611            initTab = _conRptSales.currentTab;
6612        }
6613        
6614        _conRptSales.goToPopularTab(initTab);
6615        _conRptSales.hideCommissionColumn();
6616        
6617        _initMostPopular(true);
6618        _initMostPopular(false);
6619        
6620        GLO.Report.portalName = 'popular';
6621        $('#header-navigation-links').find('#report-popular-service > a, #report-popular-product > a').addClass('ignore-animate');
6622        GLO.Report.enableFullPageCheck();
6623    }
6624    
6625    function _preInitSalesHistory(initTab) {
6626    	var pmeth = GLO.Uri.hash('pay-method');
6627        var jrpt = $('#report-sales-history');
6628        
6629        if (UTIL.isEmpty(pmeth)) {
6630        	pmeth = UTIL.coalesce(GLO.Uri.query('pay-method'), GLO.Uri.query('paymethod'));
6631        }
6632        
6633        if (!UTIL.isEmpty(pmeth)) {
6634        	jrpt.find('.Payment_Method_cd').val(pmeth);
6635        	//if (jrpt.find('.payment-history').length === 0) { setTimeout(function() { $('#report-sales-history .report-inventory-header-search').click(); }, 1500); }
6636        }
6637    }
6638    
6639    function _initSalesHistory(isSalesSummary) {
6640    	var jrpt = $('#report-sales-history');
6641    	jrpt.find('.report-inventory-search-prev, .report-inventory-search-next').css({ "margin-top": "10px" });
6642    	jrpt.find('.report-inventory-search-prev img, .report-inventory-search-next img').css({ "height": "70px" });
6643    	
6644    	var svc = GLO.Uri.query('servicefilter');
6645    	var product = GLO.Uri.query('inventoryfilter');
6646    	var sfilter = GLO.Uri.query('sfilter');
6647    	
6648    	if (!UTIL.isEmpty(svc)) {
6649    		jrpt.find('.Service_Filter').val(svc);
6650    	} else if (UTIL.coalesceInt(GLO.Info.getStaffRole(), 0) > 200 && GLO.Report.Sales.isCommissionBusiness == 0) {
6651        	jrpt.find('.Service_Filter').val(-1);
6652        }
6653        
6654        if (!UTIL.isEmpty(product)) {
6655    		jrpt.find('.Inventory_Filter').val(product);
6656    	}
6657    	
6658    	//if (!UTIL.isEmpty(sfilter)) { $('#staff-filter').val(sfilter); }
6659    	GLO.Report.enableFullPageCheck(isSalesSummary);
6660    	GLO.Report.CellSummary.initReport(jrpt, true, true);
6661    	GLO.Report.initIcons(jrpt);
6662    	
6663    	_initClientFilter(jrpt);
6664    	_conRptSales.hideCommissionColumn();			//GLO.Report.Template.hideEmptyColumn(jrpt, 'commission-cell');
6665        GLO.Report.Template.hideEmptyColumn(jrpt, 'column-profit');
6666    }
6667    
6668    function _initClientFilter(jrpt) {
6669    	var jclient = jrpt.find('#report-client-filter').find('#Client_Filter_id');
6670    	
6671    	if (jclient.length > 0) {
6672    		UI.initAutoComplete(jclient, GLO.Link.Object.Provider.ClientSearch);
6673    	
6674	    	if (UTIL.isEmpty(jclient.val())) {
6675	    		var jtd = jrpt.find('table.tablesorter').find('tbody').find('.column-buyer:first, .report-pay-buyer:first');
6676	    		
6677	    		jclient.val(UTIL.coalesce(jtd.find('a').text(), jtd.text()));
6678	    	}
6679    	}
6680    }
6681    
6682    _conRptSales.preInitSalesSummary = function(jcontainer, isSearch) {
6683    	//var cashDIV = jcontainer.find('#cash-drawer-info').removeClass('hide');
6684    	//jcontainer.find('#report-table-sales-summary').before(cashDIV);
6685    	
6686    	var jrpts = jcontainer.find('.report-sales-summary-by-booking');
6687    	var javg = jcontainer.find('.report-sales-average-by-booking');
6688    	var htm = '', tbl = '<table class="hide tablesorter tblSlim report-sales-average-by-booking" style="margin: auto; margin-top: 60px;">';
6689    	
6690    	for (var i=0; i < jrpts.length; i++) {
6691    		var avgRPT = tbl + jrpts.eq(i).find('thead').outerHTML();
6692    		var trs = jrpts.eq(i).find('tbody tr.average-total');
6693    		
6694    		for (var r=0; r < trs.length; r++) {
6695    			avgRPT += trs.eq(r).removeClass('hide').outerHTML();
6696    			trs.eq(r).remove();
6697    		}
6698    		
6699    		/* removed footer
6700    		var trfoot = jrpts.eq(i).find('tfoot tr.average-total');
6701    		avgRPT += '<tfoot style="border-top: 1px solid #333;">' + trfoot.removeClass('hide').outerHTML() + '</tfoot> </table>';
6702    		trfoot.remove();
6703    		*/
6704    		
6705    		javg.eq(i).html(avgRPT);
6706    	}
6707    	
6708    	_conRptSales.loadSalesSummary(jcontainer);
6709    	
6710    	if (isSearch) {
6711    		htm = $('<div>' + jcontainer.outerHTML() + htm + '</div>');
6712    		htm = _formatSalesSummaryByBkg(htm);
6713    		return htm.html();
6714    	} else {
6715    		_formatSalesSummaryByBkg(jcontainer);
6716    		var checkedAttribute = '';
6717    		var isForecast = UTIL.parseBool(UTIL.coalesceString(GLO.Uri.query('Include_Forecast_fl'), GLO.Uri.query('forecast'), $.cookies.get('is-forecasted-sales'), 1));
6718    		
6719    		if (isForecast) {
6720    			checkedAttribute = ' checked="checked"';
6721    		}
6722    		
6723    		var chk = '<input type="checkbox" id="Include_Forecast_fl" onchange="GLO.Report.Sales.changeForecastedSales()"' + checkedAttribute + '/>';
6724    		var lblMessage = 'Include Forecasted Sales <small>(appointments scheduled in the future)';
6725    		
6726    		if (innerWidth < 500) { lblMessage = 'Include Sales Forecast <small>(future appointments)'; }
6727    		
6728    		var lbl = '<label for="Include_Forecast_fl">' + lblMessage + '</small><label>';
6729    		var htm = '<div class="report-search-forecast">' + chk + lbl + '</div>';
6730    		jcontainer.find('.report-search-header').after(htm);
6731    	}
6732    	
6733    	_conRptSales.initSummaryChart();
6734    }
6735    _conRptSales.changeForecastedSales = function() {
6736    	var isForecastedSales = $('.report-search-forecast #Include_Forecast_fl').prop('checked');
6737    	
6738    	UTIL.setCookie('is-forecasted-sales', isForecastedSales);
6739    }
6740    _conRptSales.initStaffFilter = function() {
6741    	GLO.Info.init();
6742    	
6743    	if (GLO.Info.roleType > 199 && !GLO.Info.isIndependentPackage() && GLO.Info.isMobile()) {
6744    		var sfilter = UTIL.coalesceString(GLO.Uri.query('sfilter'), 'all');
6745    		var jstaff = $('#staff-filter');
6746    		
6747    		if (jstaff.find('option[value = "all"]').length === 0) {
6748	    		jstaff.prepend('<option value="all">ALL</option>');
6749	    	}
6750	    	
6751    		jstaff.val(sfilter);
6752    		return true;
6753    	}
6754    	
6755    	return false;
6756    }
6757    _conRptSales.postInitSalesSummary = function(jcontainer, isSearch) {
6758    	_displayPriceOnlyColumn(jcontainer);
6759    	var jh = jcontainer.find('#ss-header');
6760    	
6761    	if (jcontainer.find('#ss-no-results').length > 0) {
6762    		jh.addClass('hide');
6763    		return false;
6764    	}
6765    	
6766    	var jTicketData = jcontainer.find('#sales-summary-ticket-data');
6767    	$('#sales-summary-ticket-container-left').html(jTicketData.find('#sales-summary-ticket-data-left'));
6768    	$('#sales-summary-ticket-container-right').html(jTicketData.find('#sales-summary-ticket-data-right'));
6769    	
6770    	if (jTicketData.length > 0) {
6771    		$('#sales-summary-ticket-buttons').removeClass('hide');
6772    	} else {
6773    		$('#sales-summary-ticket-buttons').addClass('hide');
6774    	}
6775    	
6776    	_initPaySummary(jcontainer, jh, isSearch);
6777    	_postSearchHideEmptyColumns(jcontainer);
6778    	
6779    	jh.removeClass('hide');
6780    	GLO.Report.CellSummary.initReport(jcontainer, true, true);
6781    	return true;
6782    }
6783    function _displayPriceOnlyColumn(jcontainer) {
6784    	var trs  = jcontainer.find('#report-table-sales-summary tbody tr');
6785    	var hasPriceDiff = false;
6786    	
6787    	for (var i=0; i < trs.length; i++) {
6788    		var sales = UTIL.coalesceMoney(trs.eq(i).find('td.summary-column-service-sale').text().replace('$', ''));
6789    		var price = UTIL.coalesceMoney(trs.eq(i).find('td.summary-column-service-price').text().replace('$', ''));
6790    		
6791    		if (sales != price) {
6792    			hasPriceDiff = true;
6793    			break;
6794    		}
6795    	}
6796    	
6797    	if (hasPriceDiff) {
6798    		jcontainer.find('#report-table-sales-summary .summary-column-service-price').removeClass('hideX');
6799    	}
6800    }
6801    function _postSearchHideEmptyColumns(jrpt) {
6802    	if (!jrpt.hasClass('tablesorter')) {
6803        	jrpt = jrpt.find('table.tablesorter');
6804        }
6805        
6806        GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-count');
6807		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-sale');
6808		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-discount');
6809		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-tax');
6810		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-return');
6811		
6812		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-commission');
6813		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-cost');
6814		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-product-profit');
6815		
6816		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-fee');
6817		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-commission');
6818		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-profit');
6819		
6820		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-discount');
6821		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-addon');
6822		GLO.Report.hideEmptyColumn(jrpt, 'summary-column-service-tip');
6823		
6824		var jrpts = $('table.report-sales-summary-by-booking');
6825		
6826		for (var i=0; i < jrpts.length; i++) {
6827			var report = jrpts.eq(i);
6828			
6829			GLO.Report.hideEmptyColumn(report, 'column-product-count');
6830			GLO.Report.hideEmptyColumn(report, 'column-product-sale');
6831			GLO.Report.hideEmptyColumn(report, 'column-product-discount');
6832			
6833			GLO.Report.hideEmptyColumn(report, 'column-product-tax');
6834			GLO.Report.hideEmptyColumn(report, 'column-product-total');
6835			GLO.Report.hideEmptyColumn(report, 'column-product-return');
6836			
6837			GLO.Report.hideEmptyColumn(report, 'column-product-commission');
6838			GLO.Report.hideEmptyColumn(report, 'column-product-cost');
6839			GLO.Report.hideEmptyColumn(report, 'column-product-profit');
6840		}
6841    }
6842    
6843    function _initPaySummary(jcontainer, jh, isSearch) {
6844    	jh.find('#sales-summary-payment-summary').remove();
6845    	
6846    	var jPaySummary = jcontainer.find('#sales-summary-payment-summary');
6847    	var tds = jPaySummary.find('tfoot tr td');
6848    	var paymentTypeCount = 0;
6849    	
6850    	if (tds.length === 0) {
6851    		tds = jPaySummary.find('tbody tr td');
6852    	}
6853    	
6854    	if (isSearch) {
6855    		jh.removeClass('is-initial-page-load').addClass('is-search');
6856    	} else {
6857    		jh.addClass('is-initial-page-load');
6858    	}
6859    	
6860    	for (var i=0; i < tds.length; i++) {
6861    		var td = tds.eq(i);
6862    		
6863    		if (td.hasClass('ps-merchant-column')) {
6864    			++paymentTypeCount;
6865    		} else {
6866    			var amt = UTIL.coalesceMoney($.trim(td.find('a').text()).replace('$', ''));
6867    			
6868    			if (amt > 0) {
6869    				++paymentTypeCount;
6870    			} else {
6871    				var cssClass = td.attr('class');
6872    				jPaySummary.find('.' + cssClass).remove();
6873    			}
6874    		}
6875    	}
6876    	
6877    	jh.find('#ssh-payment-column').append(jPaySummary);
6878    	/* if (paymentTypeCount < 4 && !isSearch) {
6879    		jh.find('#ssh-data').append(jPaySummary);
6880    	} else {
6881    		jh.append(jPaySummary);
6882    	} */
6883    }
6884    
6885    function _formatSalesSummaryByBkg(jcontainer) {
6886    	var jrpts = jcontainer.find('.report-sales-summary-by-booking, .report-sales-average-by-booking');
6887    	
6888    	for (var i=0; i < jrpts.length; i++) {
6889    		var pcommission = 0, pdiscount = 0, sdiscount = 0;
6890    		var trs = jrpts.eq(i).find('tbody > tr');
6891    		
6892    		for (var r=0; r < trs.length; r++) {
6893    			var tr = trs.eq(r);
6894    			pcommission += UTIL.coalesceMoney($.trim(tr.find('td.commission-column').text()).replace('$', ''));
6895	    		pdiscount += UTIL.coalesceMoney($.trim(tr.find('td.product-discount-column').text()).replace('$', ''));
6896	    		sdiscount += UTIL.coalesceMoney($.trim(tr.find('td.service-discount-column').text()).replace('$', ''));
6897    		}
6898    		
6899    		//Remove Columns (if empty)
6900	    		if (pcommission === 0) {
6901	    			jrpts.eq(i).find('tr .commission-column').remove();
6902	    		}
6903	    		
6904	    		if (pdiscount === 0) {
6905	    			jrpts.eq(i).find('tr .product-discount-column').remove();
6906	    		}
6907	    		
6908	    		if (sdiscount === 0) {
6909	    			jrpts.eq(i).find('tr .service-discount-column').remove();
6910	    		}
6911	    	
6912	    	//If have all columns make text smaller
6913	    		if (pcommission > 0 && pdiscount > 0 && sdiscount > 0) {
6914	    			jrpts.eq(i).addClass('report-smaller');
6915	    		}
6916    	}
6917    	
6918    	return jcontainer;
6919    }
6920    
6921    function _initSalesSummary() {
6922    	var jrpt = $('#report-sales-summary');
6923    	jrpt.find('.Payment_Method_cd, #report-search-header-line2').remove();
6924    	
6925    	/*
6926    	var jsearch = jrpt.find('.btnSearch');
6927    	var btnSearch = jsearch.css({ "position": "absolute", "left": "5px" }).outerHTML();
6928    	var btoday = '<span class="btnAdd" style="position: absolute; right: 5px; height: 20px; padding-top: 0;"><a onclick="GLO.Report.Sales.searchToday()"> Today </a></span>';
6929    	var td = jsearch.parent().css({ "width": "260px" });
6930    	td.html('<span style="position: relative; display: block; width: 240px; margin-top: -6px;">' + btnSearch + btoday + '</span>');
6931    	*/
6932    	
6933    	jrpt.find('#sales-summary-ticket-container').removeClass('hide');
6934    	
6935    	if (jrpt.find('.report-sales-summary-by-booking').length < 2) {
6936    		jrpt.find('#sales-summary-ticket-info').remove();
6937    		jrpt.find('.report-sales-summary-by-booking').css({ "box-shadow": "inherit" });
6938    	}
6939    	
6940    	GLO.Info.init();
6941    	_conRptSales.initStaffFilter();
6942    	
6943    	_initWideScreen(jrpt);
6944    	_gotoByUri();
6945    }
6946    function _initWideScreen(jrpt) {
6947    	var columnCount = jrpt.find('#report-table-sales-summary').find('thead th').length;
6948    	
6949    	if (columnCount > 12) {
6950    		$('body').addClass('wide-report');
6951    	}
6952    }
6953    
6954    function _gotoByUri() {
6955    	if (GLO.Uri.hash('tab').toLowerCase() !== 'sales-summary') { return; }
6956    	
6957    	var gt = GLO.Uri.query('goto');
6958    	var redirectFrom = UTIL.cleanString(GLO.Uri.query('redirectFrom')).toLowerCase();
6959    	
6960    	if (!UTIL.isEmpty(gt)) {
6961    		var jsection = $('#sales-summary-container #report-sales-summary-' + gt + ':visible');
6962    		
6963    		if (jsection.length === 1) {
6964    			$(window).scrollTop(jsection[0].offsetTop);
6965    			UI.highlight(jsection);
6966    		}
6967    	}
6968    	
6969    	if (!UTIL.isEmpty(redirectFrom) && GLO.Info.providerPackage == 4) {
6970    		if (redirectFrom == 'staffgoal' || redirectFrom == 'staff-goal') {
6971    			GLO.Info.isRequireGold(false, 'the Staff Goal report');
6972    		} else if (redirectFrom == 'staffsummary' || redirectFrom == 'staff-summary') {
6973    			GLO.Info.isRequireGold(false, 'the Staff Summary report');
6974    		}
6975    	}
6976    }
6977    
6978    _conRptSales.infoSalesTotal = function(element, timePeriod, searchQuery) {
6979    	var jelement = $('#ssh-total-top').find(searchQuery);				//.closest('#sales-summary-totals');
6980    	
6981    	if (jelement.length === 0) {
6982    		if (timePeriod) {
6983    			var htm = '<div id="pop-info-sales-total-inner" style="margin-bottom: 24px;">No sales over ' + timePeriod + '</div>';
6984    			var jpop = GLO.Popup.Info.open(htm, timePeriod).getPopup().attr('id', 'pop-info-sales-total').css({ "margin-top": "0" });
6985    		}
6986    		
6987    		return;
6988    	}
6989    	
6990    	var total = UTIL.coalesceMoney(jelement.attr('total_mn')), product = UTIL.coalesceMoney(jelement.attr('product_mn'));
6991    	var service = UTIL.coalesceMoney(jelement.attr('service_mn')), tip = UTIL.coalesceMoney(jelement.attr('tip_mn'));
6992    	var start = jelement.attr('start_d'), end = jelement.attr('end_d');
6993    	var backbar = UTIL.coalesceMoney(jelement.attr('backbar_mn')), gift = UTIL.coalesceMoney(jelement.attr('gift_mn')), membership = UTIL.coalesceMoney(jelement.attr('membership_mn'));
6994    	
6995    	var htmTotal = '<label style="color: #aaa;">Total Sales</label> <b style="color: #BDE5F8;">' + UTIL.displayMoney(total, false, false, true) + '</b>';
6996    	var pcss = 'margin-bottom: 0; cursor: pointer;';
6997    	var rptUri = 'reports/saleshistory?isfullpage=1&sfilter=' + GLO.Uri.query('sfilter');
6998    	
6999    	var ssales = UTIL.displayMoney(service, false, false, true);
7000    	var cntLabel = UTIL.pluralLabel(jelement.attr('service_nr'), 'service');
7001    	var fn = 'GLO.Report.Template2.goToReport(\'Service Sales\', \'' + rptUri + '&inventoryfilter=-1\', event, true)';
7002    	var msg = '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Service Sales</label> <b>' + ssales + '</b> <small> (' + cntLabel + ')</small></p>';
7003    	
7004    	if (tip > 0) {
7005    		msg += '<p><label>Service Tips</label> <b>' + UTIL.displayMoney(tip, false, false, true) + '</b></p>';
7006    		
7007    		if (!GLO.Info.isIndividual()) {
7008	    		htmTotal += '<div>'
7009		    				+ '<label style="color: #aaa;">Total Sales <small style="letter-spacing: 0;">(including tip)</small></label>'
7010	    					+ '<b style="padding-left: 4px; color: #BDE5F8;">' + UTIL.displayMoney(total + tip, false, false, true) + '</b>'
7011	    				+ '</div>';
7012    		}
7013    	}
7014    	
7015    	if (product > 0) {
7016    		var totalReturns = _returnTotal();
7017    		var psales = UTIL.displayMoney(product, false, false, true);
7018    		var cntLabel = UTIL.pluralLabel(jelement.attr('product_nr'), 'product');
7019    		var fn = 'GLO.Report.Template2.goToReport(\'Backbar Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=r\', event, true)';
7020    		msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Product Sales</label> <b>' + psales + '</b> <small> (' + cntLabel + ')</small></p>';
7021    		
7022    		if (totalReturns) {
7023    			var disclaimer = 'product sales of ' + psales + ' ignores returns<br/><i style="font-size: 11px;">for return details see the return\'s and tax columns in the report below</i>';
7024    			msg += '<p style="margin-left: -24px; margin-top: 0; line-height: 1.5;"><small style="display: inline-block; letter-spacing: 0; font-size: 12px;">' + disclaimer +'</p>';
7025    		}
7026    	}
7027    	
7028    	if (backbar > 0) {
7029    		var bsales = UTIL.displayMoney(backbar, false, false, true);
7030    		var cntLabel = UTIL.pluralLabel(jelement.attr('backbar_nr'), 'product');
7031    		var fn = 'GLO.Report.Template2.goToReport(\'Backbar Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=b\', event, true)';
7032    		msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Backbar Sales</label> <b>' + bsales + '</b> <small> (' + cntLabel + ')</small></p>';
7033    	}
7034    	if (gift > 0) {
7035    		var gsales = UTIL.displayMoney(gift, false, false, true);
7036    		var cntLabel = UTIL.pluralLabel(jelement.attr('gift_nr'), 'gift card');
7037    		var fn = 'GLO.Report.Template2.goToReport(\'Retail Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=g\', event, true)';
7038    		msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Gift Card Sales</label> <b>' + gsales + '</b> <small> (' + cntLabel + ')</small></p>';
7039    	}
7040    	if (membership > 0) {
7041    		var msales = UTIL.displayMoney(membership, false, false, true);
7042    		var cntLabel = UTIL.pluralLabel(jelement.attr('membership_nr'), 'membership');
7043    		var fn = 'GLO.Report.Template2.goToReport(\'Retail Sales\', \'' + rptUri + '&servicefilter=-1&inventoryfilter=r\', event, true)';
7044    		msg += '<p class="pop-info-sales-row" onclick="' + fn + '"><label>Membership Sales</label> <b>' + msales + '</b> <small> (' + cntLabel + ')</small></p>';
7045    	}
7046    	
7047    	if (!UTIL.isEmpty(timePeriod)) {
7048    		timePeriod = timePeriod + ': ';
7049    	} else {
7050    		timePeriod = '';
7051    	}
7052    	
7053    	timePeriod = new Date(start).toGloDateString(true, true, true, true);
7054    	
7055    	if (UTIL.isDate(end) && start != end) {
7056    		timePeriod += ' - ' + new Date(end).toGloDateString(true, true, true, true);
7057    	}
7058    	
7059    	var htm = '<div id="pop-info-sales-total-inner" style="margin-bottom: 24px;">' + msg + '</div>';
7060    	var jpop = GLO.Popup.Info.open(htm, timePeriod).getPopup().attr('id', 'pop-info-sales-total').css({ "margin-top": "0" });
7061    	jpop.find('.msg').before('<div class="total-sales">' + htmTotal + '</div>');
7062    	
7063    	if (tip >
7063 0 && !GLO.Info.isIndividual()) {
7064    		jpop.find('.pop-icon').css({ "margin-top": "24px" });
7065    	}
7066    }
7067    
7068    function _returnTotal() {
7069    	var tds = $('#report-table-sales-summary').find('tbody .summary-column-product-return');
7070    	var total = 0;
7071    	
7072    	for (var i=0; i < tds.length; i++) {
7073    		total += UTIL.coalesceMoney(tds.eq(i).text().replace('$', ''));
7074    	}
7075    	
7076    	return total;
7077    }
7078    
7079    _conRptSales.changePaymentMethod = function() {
7080    	var jby = $('#rpt-filter-pay-method').find('#filter-pay-processed-by');
7081    	
7082    	if (!UTIL.isEmpty(this.value)) {
7083    		var headerText = SA.Resource.PaymentDetail;
7084    		jby.removeClass('hide');
7085    		$('#doc3').addClass('is-payment-report');
7086    	} else {
7087    		var headerText = SA.Resource.SalesDetail;
7088    		jby.addClass('hide');
7089    		$('#doc3').removeClass('is-payment-report');
7090    	}
7091    	
7092    	$('.shadow-content0 #detail-report-header-text').text(headerText);
7093    }
7094    
7095    
7096    _conRptSales.switchToTicketAverage = function(isAverage) {
7097    	var jbig = $('#sales-summary-ticket-info');
7098    	var j = $('#report-sales-summary');
7099    	var jbtns = j.find('#sales-summary-ticket-buttons');
7100    	
7101    	if (isAverage) {
7102    		jbig.addClass('average');
7103    		jbtns.find('#sales-average-ticket-on').addClass('selected');
7104    		jbtns.find('#sales-summary-ticket-on').removeClass('selected');
7105    		
7106    		j.find('#sales-summary-description-total, .report-sales-summary-by-booking').addClass('hide');
7107    		_displayProcessingBar(j);
7108    		
7109    		setTimeout(function() {
7110    			var j = $('#report-sales-summary');
7111    			j.find('#sales-summary-ticket-processing').addClass('hide');
7112    			j.find('#sales-summary-description-average, .report-sales-average-by-booking').removeClass('hide');
7113    		}, 900);
7114    		
7115    		j.find('#sales-summary-ticket-data-right').removeClass('hide');
7116    		j.find('#ssh-payment-incorrect').addClass('hideX');
7117    	} else {
7118    		jbig.removeClass('average');
7119    		jbtns.find('#sales-average-ticket-on').removeClass('selected');
7120    		jbtns.find('#sales-summary-ticket-on').addClass('selected');
7121    		
7122    		j.find('#sales-summary-description-average, .report-sales-average-by-booking').addClass('hide');
7123    		_displayProcessingBar(j);
7124    		
7125    		setTimeout(function() {
7126    			var j = $('#report-sales-summary');
7127    			j.find('#sales-summary-ticket-processing').addClass('hide');
7128    			j.find('#sales-summary-description-total, .report-sales-summary-by-booking').removeClass('hide');
7129    		}, 1100);
7130    		
7131    		j.find('#sales-summary-ticket-data-right').addClass('hide');
7132    		j.find('#ssh-payment-incorrect').removeClass('hideX');
7133    	}
7134    }
7135    
7136    function _displayProcessingBar(jcontainer) {
7137    	var jprocessing = jcontainer.find('#sales-summary-ticket-processing');
7138		var img = jprocessing.find('img');
7139		var src = img.attr('src');
7140		img.remove();
7141		jprocessing.removeClass('hide').html('<img/>');
7142		
7143		setTimeout(function() {
7144            jprocessing.find('img').attr('src', src);
7145        }, 50);
7146    }
7147    
7148    _conRptSales.searchToday = function() {
7149    	var jrpt = $('#report-sales-summary');
7150    	var jtoday = jrpt.find('.btnAdd');
7151    	var today = new Date().toGloDate();
7152    	
7153    	jrpt.find('.Report_Begin_dt, .Report_End_dt').val(today);
7154    	GLO.UI.Form.beginProcessing(jtoday);
7155    	
7156    	GLO.Report.Template.search();
7157    	setTimeout(function() { GLO.UI.Form.resetProcessing(); }, 2500);
7158    }
7159    
7160    function _initMostPopular(isService) {
7161    	if (isService) { var idPostfix = '-services'; } else { var idPostfix = '-products'; }
7162    	
7163    	var jMost = $('#report-popular' + idPostfix);
7164    	jMost.find('#rpt-filter-pay-method').remove();
7165    	
7166    	if (isService) {
7167    		jMost.find('.inventory-filter-container').remove();
7168    		var jdd = jMost.find('.service-filter-container').css({ "margin-right": "90px" });
7169    		
7170    		var jopts = jdd.find('option:not(.sg-option)');
7171    		for (var i=1; i < jopts.length; i++) { jopts.eq(i).remove(); }
7172    		
7173    		var svcfilter = GLO.Uri.query('inventoryfilter');
7174    		
7175    		if (svcfilter) {
7176    			jdd.find('.Service_Filter').val(svcfilter);
7177    		}
7178    	} else {
7179    		jMost.find('.service-filter-container').remove();
7180    		var jdd = jMost.find('.inventory-filter-container').css({ "margin-right": "90px" });
7181    		
7182    		var jopts = jdd.find('option:not(.v-option)');
7183    		for (var i=1; i < jopts.length; i++) { jopts.eq(i).remove(); }
7184    		
7185    		var ifilter = GLO.Uri.query('inventoryfilter');
7186    		
7187    		if (ifilter) {
7188    			jdd.find('.Inventory_Filter').val(ifilter);
7189    		}
7190    	}
7191    	
7192    	var radio = '<fieldset class="popular-input">'
7193    					+ '<table> <tr>'
7194    					+ '<td class="popular-selection view-selected" onclick="GLO.Report.Sales.focusPopular(this)">'
7195	    					+ '<input type="radio" id="radio-popular-most' + idPostfix + '" name="popular-switch' + idPostfix + '" class="popular-radio" checked="checked"/>'
7196    						+ '<input type="text" class="number-popular-most" value="10" maxlength="3" mask="int" pattern="[0-9]" onclick="GLO.Report.Sales.focusPopularText(this)"/>'
7197    						+ '<label for="radio-popular-most' + idPostfix + '">' + SA.Resource.MostPopular + '</label>'
7198    					+ '</td>'
7199    					+ '<td id="popular-input-center-column"></td>'
7200    					+ '<td class="popular-selection" onclick="GLO.Report.Sales.focusPopular(this)">'
7201	    					+ '<input type="radio" id="radio-popular-least' + idPostfix + '" name="popular-switch' + idPostfix + '"/>'
7202	    					+ '<input type="text" class="number-popular-least" value="10" maxlength="3" mask="int" pattern="[0-9]" onclick="GLO.Report.Sales.focusPopularText(this)"/>'
7203	    					+ '<label for="radio-popular-least' + idPostfix + '">' + SA.Resource.LeastPopular + '</label>'
7204    					+ '</td>'
7205    					
7206    					//+ '<span class="popular-selection">'
7207	    				//	+ '<input type="radio" id="radio-popular-all' + idPostfix + '" name="popular-switch' + idPostfix + '"/>'
7208	    				//	+ '<label for="radio-popular-all' + idPostfix + '" style="margin-left: 30px;">All</label>'
7209    					//+ '</span>'
7210    				+ '</tr> </table>'
7211    				+ '</fieldse>';
7212    	
7213    	jMost.find('.report-search-header').append(radio);
7214    	jMost.find('.popular-selection').click(GLO.Report.Sales.selectPopular)
7215    	
7216    	if (GLO.Info.providerPackage === 1) {
7217    		var mleft = "105px";
7218    	} else {
7219    		var mleft = "-45px";
7220    	}
7221    	
7222    	jMost.find('.btnSearch').css({ "position": "absolute", "margin-top": "65px", "margin-left": mleft, "font-size": "larger" });		//, "margin-left": "50px"
7223    	jMost.find('.report-inventory-search-prev, .report-inventory-search-next').css({ "margin-top": "30px" });
7224    	jMost.find('.report-inventory-search-prev img, .report-inventory-search-next img').css({ "height": "90px" });
7225    	GLO.Report.CellSummary.initReport(jMost, false, true);
7226    }
7227    
7228    _conRptSales.focusPopularText = function(inputElement) {
7229    	var j = $(inputElement);
7230    	j.closest('td').find(':radio').prop('checked', true);
7231    }
7232    
7233    _conRptSales.focusPopular = function(tdElement) {
7234    	$(tdElement).find(':radio').prop('checked', true);
7235    }
7236    
7237    _conRptSales.goToTab = function(tab) {
7238        if (tab > _conRptSales.MAX_TAB) {
7239            tab = _conRptSales.MAX_TAB;
7240        } else if (tab < 1) {
7241            tab = 1;
7242        }
7243        
7244        $('#report-sales-summary').addClass('hide');
7245        $('#report-sales-history').addClass('hide');
7246        
7247        if (tab === 1) {
7248            $('#report-sales-summary').removeClass('hide');
7249        } else if (tab === 2) {
7250            var historyRpt = $('#report-sales-history').removeClass('hide');
7251            var jsearch2 = historyRpt.find('#report-search-header-line2')
7252            
7253            if (jsearch2.length > 0) {
7254	            historyRpt.find('.report-search-header .btnSearch').remove();
7255	            historyRpt.find('#report-search-header-line2').removeClass('hide');
7256            }
7257        }
7258
7259        var backColor = $('.shadow-content0').css('backgroundColor');
7260        var jhead = $('#report-portal-header');
7261        var oj = jhead.find('table tr td span b');
7262        
7263        oj.each(function() {
7264            $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent');
7265        });
7266
7267        oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent();
7268        oj.addClass('report-tab');
7269        oj.css('backgroundColor', backColor);
7270
7271        _conRptSales.currentTab = tab;
7272        var hashTab = '';
7273
7274        if (tab == 1) {
7275            hashTab = 'sales-summary';
7276        } else if (tab == 2) {
7277            hashTab = 'sales-history';
7278            //var pmeth = historyRpt.find('.Payment_Method_cd').val();
7279        	//if (!UTIL.isEmpty(pmeth)) { hashTab += '&paymethod=' + pmeth; }
7280        }
7281
7282        document.location.hash = 'tab=' + hashTab;
7283    }
7284    
7285    _conRptSales.goToPopularTab = function(tab) {
7286        if (tab > _conRptSales.MAX_TAB) {
7287            tab = _conRptSales.MAX_TAB;
7288        } else if (tab < 1) {
7289            tab = 1;
7290        }
7291        
7292        $('#report-popular-services').addClass('hide');
7293        $('#report-popular-products').addClass('hide');
7294        
7295        if (tab === 1) {
7296            $('#report-popular-services').removeClass('hide');
7297        } else if (tab === 2) {
7298            $('#report-popular-products').removeClass('hide');
7299        }
7300
7301        var backColor = $('.shadow-content0').css('backgroundColor');
7302        var jhead = $('#report-portal-header');
7303        var oj = jhead.find('table tr td span b');
7304        
7305        oj.each(function() {
7306            $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent');
7307        });
7308
7309        oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent();
7310        oj.addClass('report-tab');
7311        oj.css('backgroundColor', backColor);
7312
7313        _conRptSales.currentTab = tab;
7314        var hashTab = '';
7315
7316        if (tab == '1') {
7317        	hashTab = 'popular-services';
7318        } else if (tab == '2') {
7319        	hashTab = 'popular-products';
7320        }
7321
7322        document.location.hash = 'tab=' + hashTab;
7323    }
7324    
7325    _conRptSales.selectPopular = function() {
7326    	var me = $(this); 		//var j = me.closest('.popular-selection');
7327    	
7328    	me.closest('.popular-input').find('.view-selected').removeClass('view-selected');
7329        me.addClass('view-selected');
7330    }
7331    
7332    _conRptSales.hideCommissionColumn = function() {
7333        var rptSalesSummary = $('#report-table-sales-summary');
7334        _hideCommissionColumn2(rptSalesSummary);
7335
7336        var rptSalesHistory = $('#report-sales-history');
7337        _hideCommissionColumn2(rptSalesHistory);
7338    }
7339    
7340    function _hideCommissionColumn2(jContainer) {
7341        var totalCommission = UTIL.coalesceMoney(jContainer.find('tfoot, tr.tfoot').find('.commission-cell').text().replace('$', '').replace(',', ''), 0);
7342
7343        if (totalCommission === 0) {
7344            jContainer.find('.commission-cell').addClass('hideX');
7345            var pcell = jContainer.find('thead th.product-cell:visible');
7346            
7347            if (pcell.length === 1) {
7348            	pcell.removeClass('notify-cell-left notify-cell-top').css({ "vertical-align": "" }).html(SA.Resource.Product + '<br/>' + SA.Resource.Sales);
7349            }
7350        }
7351    }
7352    
7353    function _setPaymentMethod(jrpt) {
7354		var pmeth = jrpt.find('.Payment_Method_cd').val();
7355        GLO.Uri.hash('pay-method', pmeth);
7356	}
7357	
7358	_conRptSales.displayDetail = function() {
7359		var throbber = $('#imgThrobber').outerHTML();
7360		$('#sales-summary-more-detail').css({ "background-color": "inherit" }).attr('id', 'sales-summary-ticket-info').html(throbber);
7361		$('#report-sales-summary .report-inventory-header-search').click();
7362		
7363		//setTimeout(function() { $('#sales-summary-more-detail').css({ "background-color": "" }) }, 3000);
7364	}
7365    
7366    _conRptSales.loadSalesSummary = function(data) {
7367    	var tdEarly = data.find('tfoot .summary-column-service-commission-early');
7368    	
7369    	if (tdEarly.length === 0) {
7370    		tdEarly = data.find('td.summary-column-service-commission-early');
7371    	}
7372    	
7373    	var earlyTotal = $.trim(tdEarly.text()).replace('$', '');
7374    	
7375    	if (earlyTotal) {
7376    		data.find('.summary-column-service-commission-early').removeClass('hideX');
7377    	}
7378    }
7379    
7380    _conRptSales.initSummaryChart = function(data) {
7381    	var ssh = $('#ss-header');
7382    	
7383    	if (data) {
7384    		var j = $(data);
7385    		
7386    		ssh.find('#sales-summary-chart').remove();
7387			ssh.find('#sales-summary-totals').remove();
7388			ssh.find('#sales-summary-client-data').remove();
7389    	} else {
7390    		var j = $('#report-sales-summary');
7391    	}
7392    	
7393    	var jchart = j.find('#sales-summary-chart');
7394		var jtotals = j.find('#sales-summary-totals');
7395		var jclient = j.find('#sales-summary-client-data');
7396    	
7397    	ssh.find('#ssh-chart').append(jchart);
7398    	ssh.find('#ssh-totals').append(jtotals);
7399    	ssh.find('#ssh-client-data').append(jclient);
7400    	
7401    	j.find('#sales-summary-more-info').remove();
7402    	
7403    	if (data) { return j.outerHTML(); }
7404    }
7405    
7406    _conRptSales.createSummaryChart = function() {
7407    	if (GLO.Data.Chart === undefined) {
7408    		$('#ssh-chart, #ssh-data').css({ "visibility": "hidden" });
7409    		$('#ss-no-results').css({ "letter-spacing": "1px" });
7410    		return;
7411    	} else {
7412    		$('#ssh-chart, #ssh-data').css({ "visibility": "" });
7413    	}
7414    	
7415    	var mustHidePrevWk = true;
7416    	var xShowLabel = true;
7417    	var len = GLO.Data.Chart.labels.length;
7418    	
7419    	if (GLO.Data.Chart.isBarChart) {
7420    		if (!GLO.Data.Chart.isGroupByWeek && !GLO.Data.Chart.isGroupByMonth) { mustHidePrevWk = false; }
7421    		
7422    		if (len > 14 || (!GLO.Data.Chart.isGroupByMonth && len > 7)) { xShowLabel = false; }
7423    		
7424    		_createBarChart(xShowLabel);
7425    	} else {
7426    		_createLineChart();
7427    	}
7428        
7429        if (GLO.Data.Chart.isMultiYearSearch) {
7430        	$('.ct-chart-guide-prev-year').addClass('hide');
7431        	$('#ssh-chart .ct-chart').addClass('ct-chart-only-search-range');
7432        } else {
7433        	$('.ct-chart-guide-prev-year').removeClass('hide');
7434        	$('#ssh-chart .ct-chart').removeClass('ct-chart-only-search-range');
7435        }
7436        
7437        $('.ct-chart-guide-search-range td:last').text(GLO.Data.Chart.searchR
7437angeLabelShort);
7438        $('#ssh-data > h2').text(GLO.Data.Chart.searchRangeLabel);
7439        _displayPreviousWeek(mustHidePrevWk);
7440        _manageChartLabel();
7441        //$('#sales-summary-data').html('<pre> <b>' + GLO.Data.Chart.labels + '</b> <div>' + GLO.Data.Chart.series + '</div> </pre>');
7442    }
7443    
7444    function _manageChartLabel() {
7445    	var jchart = $('#ssh-chart .ct-chart');
7446    	var width = jchart.width();
7447    	var maxLen, mod = 0, len = GLO.Data.Chart.labels.length;
7448    	
7449    	if (width < 360) {
7450    		maxLen = 7;
7451    	} else if (width < 400) {
7452    		maxLen = 9;
7453    	} else if (width < 500) {
7454    		maxLen = 10;
7455    	} else if (width < 600) {
7456    		maxLen = 13;
7457    	} else if (width < 700) {
7458    		maxLen = 16;
7459    	} else if (width < 800) {
7460    		maxLen = 19;
7461    	} else {
7462    		maxLen = 23;
7463    	}
7464    	
7465    	if (GLO.Data.Chart.isGroupByWeek) {
7466    		maxLen = parseInt(maxLen * .8);
7467    	} else if (!GLO.Data.Chart.isGroupByMonth) {
7468    		maxLen = parseInt(maxLen * 1.4);
7469    	}
7470    	
7471    	if (len > maxLen * 2) {
7472			_chartClearLabels();
7473			
7474			setTimeout(function() {
7475				jchart.find('.ct-labels .ct-horizontal').remove();
7476			}, 100);
7477			
7478			setTimeout(function() {
7479				jchart.find('.ct-labels .ct-horizontal').remove();
7480			}, 1200);
7481		} else if (len > maxLen) {
7482			_setShortChartLabel();
7483		}
7484    	
7485    	//new GLO.Popup.Info('_manageChartLabel() width = ' + width + '; maxLen = ' + maxLen + '; len = ' + len);
7486    }
7487    
7488    function _chartClearLabels() {
7489    	var arr = GLO.Data.Chart.labels;
7490		
7491		for (var i=0; i < arr.length; i++) {
7492			arr[i] = '';
7493    	}
7494    }
7495    
7496    function _setShortChartLabel() {
7497    	var arr = GLO.Data.Chart.labels;
7498		
7499		if (GLO.Data.Chart.isGroupByMonth) {
7500			for (var i=0; i < arr.length; i++) {
7501				arr[i] = arr[i].substring(0,1);
7502	    	}
7503	    } else {
7504	    	for (var i=0; i < arr.length; i++) {
7505				if (i % 2 == 1) {
7506					arr[i] = '';
7507				}
7508	    	}
7509	    }
7510    }
7511    
7512    function _createLineChart() {
7513    	var data = {
7514		  	labels: GLO.Data.Chart.labels,
7515			series: GLO.Data.Chart.series
7516		};
7517		
7518		var options = {
7519			showPoint: false,										// Don't draw the line chart points
7520			lineSmooth: true,										// Disable line smoothing
7521			axisX: {
7522				offset: 60,
7523				showGrid: false,									// disable grid for this axis
7524				showLabel: true										// and also don't show the label
7525			},
7526			axisY: {
7527				offset: 80,											// offset the chart a bit from the labels
7528				
7529				labelInterpolationFnc: function(value) {			//allows modify values used for the labels on each axis
7530					return UTIL.displayMoney(value, false, false, true);
7531				}
7532			}
7533		};
7534		
7535		new Chartist.Line('.ct-chart', data, options);
7536		
7537		$('.ct-chart').addClass('ct-line-chart')
7538    }
7539    
7540    function _createBarChart0() {
7541        $(function() {
7542            new Chartist.Bar('.ct-chart', {
7543                labels: GLO.Data.Chart.labels,
7544                series: GLO.Data.Chart.series
7545            }, {
7546                seriesBarDistance: 10,
7547                axisX: {
7548                    offset: 20
7549                },
7550                axisY: {
7551                    offset: 60,
7552                    labelInterpolationFnc: function (value) {
7553                        return UTIL.displayMoney(value, false, false, true);
7554                    },
7555                    scaleMinSpace: 15
7556                }
7557            });
7558        });
7559    }
7560    
7561    function _createBarChart(xShowLabel) {
7562    	$('.ct-chart').removeClass('ct-line-chart');
7563    	
7564    	new Chartist.Bar('.ct-chart', {
7565                labels: GLO.Data.Chart.labels,
7566                series: GLO.Data.Chart.series
7567            }, {
7568                seriesBarDistance: 10,
7569                axisX: {
7570                    showLabel: xShowLabel,
7571                    showGrid: false,
7572                    offset: 20
7573                },
7574                axisY: {
7575                    offset: 60,
7576                    labelInterpolationFnc: function (value) {
7577                        return UTIL.displayMoney(value, false, false, true);
7578                    },
7579                    scaleMinSpace: 15
7580                }
7581            });
7582    }
7583    
7584    function _displayPreviousWeek(mustHide) {
7585    	if (mustHide) {
7586    		$('.ct-chart-guide-prev-week').addClass('hide');
7587    		$('#sales-summary-chart .ct-chart').removeClass('ct-chart-prev-week');
7588    	} else {
7589    		$('.ct-chart-guide-prev-week').removeClass('hide');
7590    		$('#sales-summary-chart .ct-chart').addClass('ct-chart-prev-week');
7591    	}
7592    }
7593    
7594    _conRptSales.printScreenInit = function() {
7595    	var jtbl = $('#report-sales-history .tablesorter');
7596		var thStaff = jtbl.find('th.column-staff');
7597		
7598		if (thStaff.hasClass('headerSortDown')) {
7599			UI.Print.printOnDevice();
7600		} else {
7601    		thStaff.click();
7602    	
7603			var ojpop = new GLO.Popup.Processing('Printing...');
7604			var delay = 400 + jtbl.find('tr').length;
7605			
7606			setTimeout(function() {
7607				ojpop.close();
7608				UI.Print.printOnDevice();
7609			}, delay);
7610    	}
7611    }
7612    
7613    function _print() {
7614    	
7615    }
7616    
7617    _conRptSales.printScreen = function() {
7618    	UI.Print.printOnDevice();
7619    	
7620		setTimeout(function() { $('#print-report-button > a').click(); }, 100);
7621    }
7622    
7623    _conRptSales.printByStaff = function() {
7624    	var jrpt = $('#report-sales-history');
7625    	var jtbl = jrpt.find('.tablesorter');
7626		var tdStaff = jtbl.find('td.column-staff');
7627		
7628    	if (GLO.Info.roleType < 219) {
7629    		var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
7630    		var start = new Date(jrpt.find('.Report_Begin_dt').val()).getTime();
7631    		var end = new Date(jrpt.find('.Report_End_dt').val()).getTime();
7632    		
7633    		if ((end - start) / oneDay > 14) {
7634    			var fn = function() { 
7635    				UI.highlight( jrpt.find('.Report_Begin_dt').closest('tr') );
7636    			};
7637    			var msg = '<div>Receptionist user role can only print 2 weeks</div><div style="max-width: 500px; margin-top: 24px;">To print more than 2 weeks please login as Manager or Admin</div>';
7638    			
7639    			GLO.Popup.Warning.open(msg, 'Receptionist Permission', fn);
7640    			return;
7641    		}
7642    	}
7643    	
7644		if (tdStaff.length === 0) {
7645			_printByStaffWarning();
7646			return;
7647		}
7648		
7649		var arr = [];
7650		var sid = tdStaff.eq(0).attr('staff_id');
7651		
7652		if (!UTIL.isEmpty(sid)) {
7653			_addStaff(arr, sid, tdStaff, 0);
7654		}
7655		
7656		for (var i=1; i < tdStaff.length; i++) {
7657			var sid = tdStaff.eq(i).attr('staff_id');
7658			
7659			if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) {
7660				_addStaff(arr, sid, tdStaff, i);
7661			}
7662		}
7663		
7664		arr = UTIL.sortArray(arr, "name");
7665		
7666		if (arr.length === 1) {
7667			_conRptSales.printByStaff2(arr[0].id);
7668		} else {
7669			var h1 = '<h1 class="friendly-responsive"><div>Print Staff Summary</div></h1>';
7670			var h1Staff = '<h3 class="friendly-responsive"><div>Select Staff</div></h3>';
7671			var liCSS = 'padding: 8px 0; border-top: 1px solid rgba(20,80,240,.8); font-weight: bold; font-size: 20px; color: #4F81BD; cursor: pointer;';
7672			var ul = '<li onclick="GLO.Report.Sales.printByStaff2()" style="' + liCSS + '">All Staff</li>';
7673			var reportFormatHtm = '';
7674
7675			var reportFormatSelectHeader = document.createElement('h5');
7676			reportFormatSelectHeader.innerHTML = '<div>Select Report Format:</div>';
7677
7678			var reportFormatSelect = document.createElement('select');
7679			reportFormatSelect.name = 'reportFormatSelect';
7680			reportFormatSelect.id = 'reportFormatSelect';
7681
7682			var reportFormats = [
7683			"Receipt Printer",
7684			"Normal",
7685			];
7686
7687			var format_options_str = "";
7688
7689			reportFormats.forEach( function(format) {
7690				format_options_str += '<option value="' + format + '">' + format + '</option>';
7691			});
7692
7693			reportFormatSelect.innerHTML = format_options_str;
7694			reportFormatHtm = reportFormatSelectHeader.outerHTML + reportFormatSelect.outerHTML;
7695
7696			for (var a=0; a < arr.length; a++) {
7697				ul += '<li onclick="GLO.Report.Sales.printByStaff2(' + arr[a].id + ')" style="' + liCSS + '">' + arr[a].name + '</li>';
7698			}
7699			
7700			var ulCSS = 'min-width: 300px; margin: 0; border-bottom: 1px solid rgba(20,80,240,.8);'
7701			var jhtm = $('<div class="friendly-responsive">' + h1 + reportFormatHtm+ h1Staff + '<div id="pop-select-print-staff-sales-summary"><ul style="' + ulCSS + '">' + ul + '</ul></div></div>');
7702			var oj = new GLO.Popup.Custom(jhtm);
7703			var jpop = oj.getPopup().addClass('no-persist');
7704			var jbtn = jpop.find('.pop-buttons').css({ "margin-top": "12px" });
7705			
7706			jpop.find('h1').css({ "margin": "0", "padding-top": "4px", "padding-bottom": "8px", "line-height": "180%", "font-size": "20px" });
7707			jpop.find('.friendly-responsive').css({ "padding-top": "0" });
7708			
7709			jbtn.find('.btnSave').remove();
7710			jbtn.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "0" }).find('>a').css({ "letter-spacing": "2px", "font-size": "large" });
7711		}
7712    }
7713    
7714	_conRptSales.printByStaffFromPOS = function() {
7715    	var jrpt = $('#pos-staff-list');
7716		var tdStaff = jrpt.find('li.pos-staff-cell[staff_id]');
7717    	
7718		if (tdStaff.length === 0) {
7719			_printByStaffWarning();
7720			return;
7721		}
7722		
7723		var arr = [];
7724		var sid = tdStaff.eq(0).attr('staff_id');
7725		
7726		for (var i=0; i < tdStaff.length; i++) {
7727			var sid = tdStaff.eq(i).attr('staff_id');
7728			var staffName = tdStaff.eq(i).find('.pos-staff-name').text();
7729
7730			if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) {
7731				arr.push({ "id": sid, "name": staffName });
7732			}
7733		}
7734		
7735		arr = UTIL.sortArray(arr, "name");
7736		
7737		if (arr.length === 1) {
7738			_conRptSales.printByStaff2(arr[0].id);
7739		} else {
7740			var h1 = '<h1 class="friendly-responsive"><div>Print Staff Summary</div></h1>';
7741			var h1Staff = '<h3 class="friendly-responsive"><div>Select Staff</div></h3>';
7742			var liCSS = 'padding: 8px 0; border-top: 1px solid rgba(20,80,240,.8); font-weight: bold; font-size: 20px; color: #4F81BD; cursor: pointer;';
7743			var ul = '<li onclick="GLO.Report.Sales.printByStaff2()" style="' + liCSS + '">All Staff</li>';
7744			var reportFormatHtm = '';
7745
7746			var reportFormatSelect = document.createElement('select');
7747			reportFormatSelect.name = 'reportFormatSelect';
7748			reportFormatSelect.id = 'reportFormatSelect';
7749			reportFormatSelect.className ='hide';
7750
7751			var reportFormats = [
7752			"Receipt Printer"
7753			];
7754
7755			var format_options_str = "";
7756
7757			reportFormats.forEach( function(format) {
7758				format_options_str += '<option value="' + format + '">' + format + '</option>';
7759			});
7760
7761			reportFormatSelect.innerHTML = format_options_str;
7762			reportFormatHtm = reportFormatSelect.outerHTML;
7763
7764			for (var a=0; a < arr.length; a++) {
7765				ul += '<li onclick="GLO.Report.Sales.printByStaff2(' + arr[a].id + ')" style="' + liCSS + '">' + arr[a].name + '</li>';
7766			}
7767			
7768			var ulCSS = 'min-width: 300px; margin: 0; border-bottom: 1px solid rgba(20,80,240,.8);'
7769			var jhtm = $('<div class="friendly-responsive">' + h1 + reportFormatHtm+ h1Staff + '<div id="pop-select-print-staff-sales-summary"><ul style="' + ulCSS + '">' + ul + '</ul></div></div>');
7770			var oj = new GLO.Popup.Custom(jhtm);
7771			var jpop = oj.getPopup().addClass('no-persist');
7772			var jbtn = jpop.find('.pop-buttons').css({ "margin-top": "12px" });
7773			
7774			jpop.find('h1').css({ "margin": "0", "padding-top": "4px", "padding-bottom": "8px", "line-height": "180%", "font-size": "20px" });
7775			jpop.find('.friendly-responsive').css({ "padding-top": "0" });
7776			
7777			jbtn.find('.btnSave').remove();
7778			jbtn.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "0" }).find('>a').css({ "letter-spacing": "2px", "font-size": "large" });
7779		}
7780    }
7781
7782	_conRptSales.printByReceptionistFromMenu = function() {
7783
7784		var uri = GLO.Link.Object.Provider.Ajax + 'StaffModelList';
7785
7786        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false })
7787            .success(function(data, textStatus, jqXHR) {
7788
7789				//data is invalid
7790				if (!$.trim(data)){ 
7791					_printByStaffWarning();
7792				}
7793
7794				var jrpt = $(data);
7795				var tdStaff = jrpt.find('li');
7796
7797				if (tdStaff.length === 0) {
7798					_printByStaffWarning();
7799					return;
7800				}
7801				
7802				var arr = [];
7803				// var sid = tdStaff.eq(0).attr('staff_id');
7804				
7805				for (var i=0; i < tdStaff.length; i++) {
7806					var sid = tdStaff.eq(i).attr('staff_id');
7807					var staffName = tdStaff.eq(i).find('label>b').text();
7808		
7809					if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) {
7810						arr.push({ "id": sid, "name": staffName });
7811					}
7812				}
7813				
7814				arr = UTIL.sortArray(arr, "name");
7815				
7816				if (arr.length === 1) {
7817					_conRptSales.printByStaff2();
7818				} else {
7819					var h1 = '<h1 class="friendly-responsive"><div>Print Staff Summary</div></h1>';
7820					var h1Staff = '<h3 class="friendly-responsive"><div>Select Staff</div></h3>';
7821					var liCSS = 'padding: 8px 0; border-top: 1px solid rgba(20,80,240,.8); font-weight: bold; font-size: 20px; color: #4F81BD; cursor: pointer;';
7822					var ul = '<li onclick="GLO.Report.Sales.printByStaff2()" style="' + liCSS + '">All Staff</li>';
7823					var reportFormatHtm = '';
7824		
7825					var reportFormatSelect = document.createElement('select');
7826					reportFormatSelect.name = 'reportFormatSelect';
7827					reportFormatSelect.id = 'reportFormatSelect';
7828					reportFormatSelect.className ='hide';
7829		
7830					var reportFormats = [
7831					"Receipt Printer"
7832					];
7833		
7834					var format_options_str = "";
7835		
7836					reportFormats.forEach( function(format) {
7837						format_options_str += '<option value="' + format + '">' + format + '</option>';
7838					});
7839		
7840					reportFormatSelect.innerHTML = format_options_str;
7841					reportFormatHtm = reportFormatSelect.outerHTML;
7842		
7843					for (var a=0; a < arr.length; a++) {
7844						ul += '<li onclick="GLO.Report.Sales.printByStaff2(' + arr[a].id + ')" style="' + liCSS + '">' + arr[a].name + '</li>';
7845					}
7846					
7847					var ulCSS = 'min-width: 300px; margin: 0; border-bottom: 1px solid rgba(20,80,240,.8);'
7848					var jhtm = $('<div class="friendly-responsive">' + h1 + reportFormatHtm+ h1Staff + '<div id="pop-select-print-staff-sales-summary"><ul style="' + ulCSS + '">' + ul + '</ul></div></div>');
7849					var oj = new GLO.Popup.Custom(jhtm);
7850					var jpop = oj.getPopup().addClass('no-persist');
7851					var jbtn = jpop.find('.pop-buttons').css({ "margin-top": "12px" });
7852					
7853					jpop.find('h1').css({ "margin": "0", "padding-top": "4px", "padding-bottom": "8px", "line-height": "180%", "font-size": "20px" });
7854					jpop.find('.friendly-responsive').css({ "padding-top": "0" });
7855					
7856					jbtn.find('.btnSave').remove();
7857					jbtn.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "0" }).find('>a').css({ "letter-spacing": "2px", "font-size": "large" });
7858				}                
7859
7860		}).fail(function(jqXHR, textStatus, errorThrown) {
7861			GLO.UI.Form.resetProcessing(); 		
7862			new GLO.Popup.Error('Could not get the sales detail report data. Please try again.');
7863		});
7864
7865
7866
7867    }
7868
7869    function _addStaff(arr, sid, tdStaff, index) {
7870    	var sname = $.trim(UTIL.directTagOnly(tdStaff.eq(index)));
7871    	arr.push({ "id": sid, "name": sname });
7872    }
7873    
7874    function _printByStaffWarning() {
7875    	var msg1 = '<div>No Sales over selected date range and filter criteria</div>';
7876		var msg2 = '<div>
7876Please change the search filter and press the search button</div>';
7877		var htm = '<div class="friendly-responsive"><h1 class="friendly-responsive">No Sales</h1><div>' + msg1 + msg2 + '</div></div>';
7878		
7879		var fn = function() {
7880			var jfilter = $('#report-sales-history .report-search-header');
7881			UI.highlight(jfilter, 800, 6400, true);
7882		}
7883		
7884		new GLO.Popup.Warning(htm, fn);
7885    }
7886    
7887    _conRptSales.printByStaff2 = function(staffid) {
7888		var jtbl = $('#report-sales-history .tablesorter');
7889		var thStaff = jtbl.find('th.column-staff');
7890
7891		var selectedReportFormat = '';
7892		if (staffid) {
7893			//assume star printer and try printing
7894
7895			selectedReportFormat = 'Receipt Printer';
7896		}
7897		else {
7898			selectedReportFormat = document.querySelector('#reportFormatSelect').value;
7899		}
7900
7901		if (selectedReportFormat == 'Receipt Printer') {
7902			//get report html
7903			var jrpt = $('#report-sales-history');        
7904			var start = jrpt.find('.Report_Begin_dt').val();
7905    		var end = jrpt.find('.Report_End_dt').val();
7906
7907			if (typeof start === "undefined") {
7908				start = new Date().toLocaleDateString();
7909			}
7910
7911			if (typeof end === "undefined") {
7912				end = new Date().toLocaleDateString();
7913			}
7914			var shrUri = '';
7915			if (staffid) {
7916				shrUri = GLO.Link.WebsiteDomain + 'reports/saleshistory?sfilter=' + staffid + '&start=' + start + '&end=' + end + '&inventoryfilter=-1&isemp=1';
7917			}
7918			else {
7919				shrUri = GLO.Link.WebsiteDomain + 'reports/saleshistory?sfilter=&start=' + start + '&end=' + end + '&inventoryfilter=-1&isemp=1';
7920			}
7921
7922			var jqxhr = $.ajax({ type: "GET", url: shrUri, "cache": false, data: null, dataType: 'text' })
7923				.done(function(data, textStatus, jqXHR) {
7924				window.onbeforeunload = null;
7925				if(data!=null && data!== '') {
7926					var reportHtml = data;
7927
7928					var hasHtmlContent =  /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)<\/\1>/.test(data);
7929					//check data
7930					if (hasHtmlContent && $(data).find('#ss-no-results').length > 0) {
7931						_printByStaffWarning();
7932					}
7933					else {
7934
7935
7936						if (SA.App.isWKWebView() && window.webkit.messageHandlers.PrintToStarPrinter) {
7937							//assume star printer and try printing
7938
7939							var jprocessing = $('#pop-printing-report').closest('.glopop');
7940                
7941							if (jprocessing.length === 0) {
7942								var htm = '<div id="pop-printing-report">Printing Report...</div>';
7943								jprocessing = GLO.Popup.Processing.open(htm, 'Report').getPopup();
7944							}
7945
7946							_getSalesDetailRaster(reportHtml,start,end,jprocessing);
7947						}
7948						else {
7949							_generateSalesDetailThermalReceipt(reportHtml,start,end);
7950						}						
7951					}
7952				  } else {
7953					new GLO.Popup.Error('Could not get the sales detail report data');
7954				  }				
7955			})
7956			.fail(function(jqXHR, textStatus, errorThrown) {
7957				GLO.UI.Form.resetProcessing(); 		
7958				new GLO.Popup.Error('Could not get the sales detail report data');
7959			});
7960		}
7961		else {
7962		
7963			if (thStaff.hasClass('headerSortDown')) {
7964				_printByStaff3(staffid);
7965			} else {
7966				thStaff.click();
7967				
7968				var ojpop = new GLO.Popup.Processing('Printing...');
7969				var delay = 400 + jtbl.find('tr').length;
7970				
7971				setTimeout(function() {
7972					ojpop.close();
7973					_printByStaff3(staffid);
7974				}, delay);
7975			}
7976		}	
7977    }
7978
7979
7980	function _generateSalesDetailThermalReceipt(reportHtml,start,end) {
7981
7982		if (reportHtml && reportHtml.length > 100) {
7983
7984			//main receipt element
7985			var reportEl = document.createElement("div");
7986			reportEl.className='receipt';
7987			reportEl.setAttribute("style", "margin:0;");
7988			
7989
7990			//report name
7991			var reportNameEl = document.createElement("div");
7992			reportNameEl.className='headerSubTitle';
7993			reportNameEl.innerHTML='Sales Report';
7994			reportEl.append(reportNameEl);
7995
7996			var staffIds=[];
7997			var staffList=[];
7998
7999			$(reportHtml).find('.service-row').each(function() { 
8000				var staffId = $(this).find('td:first-child').attr("staff_id");
8001				var staffName = $(this).find('.column-staff').text();
8002				if(staffIds.indexOf(staffId) === -1) {
8003					var staff = {
8004						"staffid": staffId,
8005						"name": staffName
8006					  };
8007					staffIds.push(staffId);
8008					staffList.push(staff);
8009					
8010				}
8011			});
8012
8013			if (staffList.length > 0) {
8014				staffList.forEach(function(staff) {
8015					
8016					var staffNameEl = document.createElement("div");
8017					staffNameEl.className='location';
8018					staffNameEl.innerHTML=staff.name;
8019
8020					var dateRangeEl = document.createElement("div");
8021					dateRangeEl.className='headerSubTitle';
8022					dateRangeEl.innerHTML = start + ' - ' + end;
8023
8024					reportEl.append(staffNameEl);
8025					reportEl.append(dateRangeEl);
8026
8027					var flexEl = document.createElement("div");
8028					flexEl.className='flex';
8029					// flexEl.setAttribute("style", "page-break-after: always;");
8030
8031					var itemsWrapperEl = document.createElement("div");
8032					itemsWrapperEl.className='totals';
8033
8034					var itemSectionEl = document.createElement("div");
8035					itemSectionEl.className='section';
8036
8037					//add column names
8038					var headerRowEl = document.createElement("div");
8039					headerRowEl.className='row headerRow'; 
8040					var hCol1El = document.createElement("div");
8041					hCol1El.className='col1';
8042					hCol1El.innerHTML = 'Client';
8043					var hCol2El = document.createElement("div");
8044					hCol2El.className='col2';
8045					hCol2El.innerHTML = 'Service';
8046					var hCol3El = document.createElement("div");
8047					hCol3El.className='col3';
8048					hCol3El.innerHTML = '';
8049					var hCol4El = document.createElement("div");
8050					hCol4El.className='col4';
8051					hCol4El.innerHTML = 'Service';
8052					var hCol5El = document.createElement("div");
8053					hCol5El.className='col5';
8054					hCol5El.innerHTML = 'Comm.';
8055					var hCol6El = document.createElement("div");
8056					hCol6El.className='col6';
8057					hCol6El.innerHTML = 'Tip';
8058
8059					headerRowEl.append(hCol1El);
8060					headerRowEl.append(hCol2El);				
8061					// headerRowEl.append(hCol3El);
8062					if (GLO.Data.provider.report.reportCanViewPrice) {
8063						headerRowEl.append(hCol4El);
8064					}
8065					if (GLO.Data.provider.report.reportCanViewCommission) {
8066						headerRowEl.append(hCol5El);
8067					}
8068					if (GLO.Data.provider.report.reportCanViewTip) {
8069						headerRowEl.append(hCol6El);
8070					}
8071
8072					itemSectionEl.append(headerRowEl);					
8073
8074					var serviceTotal = 0.00, commissionTotal=0.00, tipTotal = 0.00;
8075					$(reportHtml).find('.service-row').each(function() { 
8076
8077						var staffId = $(this).find('td:first-child').attr("staff_id");
8078						if (staff.staffid == staffId) {
8079							var rowEl = document.createElement("div");
8080							rowEl.className='row';
8081							var col1El = document.createElement("div");
8082							col1El.className='col1';
8083							var clientName = $(this).find('.column-buyer a').text();
8084							clientName = clientName.replace(/(\r\n|\n|\r)/gm, "");
8085							col1El.innerHTML = clientName.substring(0,12);
8086							var col2El = document.createElement("div");
8087							col2El.className='col2';
8088							var serviceName = $(this).find('.column-variety').text();
8089							serviceName = serviceName.replace(/(\r\n|\n|\r)/gm, "");
8090							col2El.innerHTML = serviceName.substring(0,11);
8091							var col3El = document.createElement("div");
8092							col3El.className='col3';
8093							col3El.innerHTML = '';
8094							var col4El = document.createElement("div");
8095							col4El.className='col4';
8096							var servicePrice = $(this).find('.column-price').text().replace('$','');
8097							col4El.innerHTML = parseFloat(servicePrice) || ' ';
8098							serviceTotal += parseFloat(servicePrice) || 0;
8099							var col5El = document.createElement("div");
8100							col5El.className='col5';
8101							var commissionAmount = $(this).find('.commission-cell').text().replace('$','');
8102							col5El.innerHTML = parseFloat(commissionAmount) || ' ';
8103							commissionTotal += parseFloat(commissionAmount) || 0;
8104							var col6El = document.createElement("div");
8105							col6El.className='col6';
8106							var tipAmount = $(this).find('.column-tip').text().replace('$','');
8107							col6El.innerHTML = parseFloat(tipAmount) || ' ';
8108							tipTotal += parseFloat(tipAmount) || 0;
8109
8110							rowEl.append(col1El);
8111							rowEl.append(col2El);
8112							// rowEl.append(col3El);
8113							if (GLO.Data.provider.report.reportCanViewPrice) {
8114								rowEl.append(col4El);
8115							}
8116							if (GLO.Data.provider.report.reportCanViewCommission) {
8117								rowEl.append(col5El);
8118							}
8119							if (GLO.Data.provider.report.reportCanViewTip) {
8120								rowEl.append(col6El);
8121							}
8122							
8123							itemSectionEl.append(rowEl);
8124		
8125						}
8126					});
8127
8128					var itemTotalSectionEl = document.createElement("div");
8129					itemTotalSectionEl.className='section';
8130
8131					var totalRowEl = document.createElement("div");
8132					totalRowEl.className='row totalRow'; 
8133					var col1El = document.createElement("div");
8134					col1El.className='col1';
8135					col1El.innerHTML = 'Totals';
8136					var col2El = document.createElement("div");
8137					col2El.className='col2';
8138					col2El.innerHTML = '&nbsp;';
8139					var col3El = document.createElement("div");
8140					col3El.className='col3';
8141					col3El.innerHTML = '';
8142					var col4El = document.createElement("div");
8143					col4El.className='col4';
8144					
8145					if (serviceTotal > 0) {
8146						col4El.innerHTML = UTIL.displayMoney(serviceTotal, false, false, true);
8147					} else {
8148						col4El.innerHTML = '&nbsp;';
8149					}
8150					
8151					var col5El = document.createElement("div");
8152					col5El.className='col5';
8153					
8154					if (commissionTotal > 0) {
8155						col5El.innerHTML = UTIL.displayMoney(commissionTotal, false, false, true);
8156					} else {
8157						col5El.innerHTML = '&nbsp;';
8158					}
8159					
8160					var col6El = document.createElement("div");
8161					col6El.className='col6';
8162					
8163					if (tipTotal > 0) {
8164						col6El.innerHTML = UTIL.displayMoney(tipTotal, false, false, true);
8165					} else {
8166						col6El.innerHTML = '&nbsp;';
8167					}
8168					
8169					totalRowEl.append(col1El);
8170					totalRowEl.append(col2El);
8171					// totalRowEl.append(col3El);
8172					if (GLO.Data.provider.report.reportCanViewPrice) {
8173						totalRowEl.append(col4El);
8174					}
8175					if (GLO.Data.provider.report.reportCanViewCommission) {
8176						totalRowEl.append(col5El);
8177					}
8178					if (GLO.Data.provider.report.reportCanViewTip) {
8179						totalRowEl.append(col6El);
8180					}					
8181					
8182					itemTotalSectionEl.append(totalRowEl);
8183
8184					// itemsWrapperEl.append(staffNameEl);
8185					// itemsWrapperEl.append(dateRangeEl);
8186					itemsWrapperEl.append(itemSectionEl);
8187					itemsWrapperEl.append(itemTotalSectionEl);
8188					itemsWrapperEl.innerHTML += `<div style="break-after:page"></div>`;
8189
8190					flexEl.append(itemsWrapperEl);
8191					reportEl.append(flexEl);
8192				});
8193
8194				var reportWrapperEl = document.querySelector('.thermal-receipt');
8195				reportWrapperEl.innerHTML='';
8196				reportWrapperEl.append(reportEl);
8197
8198
8199				// console.log(reportWrapperEl.innerHTML);
8200				// UI.Print.print(document.documentElement.outerHTML,true,false);
8201				UI.Print.print(document.getElementsByClassName('thermal-receipt')[0].innerHTML,true,false)
8202			} else {
8203				//staff ids in the result set
8204			}
8205		}
8206		else {
8207			//do nothing
8208			//display error message, log error
8209		}
8210	}
8211
8212	//for print from iOS to receipt printer
8213	function _getSalesDetailRaster(reportText,start,end,jprocessing) {
8214
8215		GLO.Popup.closeIfExist(jprocessing);
8216		if ((typeof(reportText) !== 'undefined') && (reportText !== null) && reportText !== '') {
8217			SA.App.sendToiOSStarPrinter(reportText);
8218		}
8219		else {
8220			GLO.Popup.closeIfExist(jprocessing);
8221			GLO.UI.Form.resetProcessing(); 		
8222			new GLO.Popup.Error('Unable to print report to selected printer.');
8223		
8224		}
8225
8226
8227		// var uri = GLO.Link.WebsiteDomain + 'mobilepay/getRasterReceiptText';
8228		// var uri = 'http://www.test2.com/reports/saleshistory?sfilter=&start=04/01/2024&end=5/19/2024&inventoryfilter=-1&isEmp=1';
8229
8230		// var cleanedHtmData= htmData.outerHTML().replace(/ no-cents| line-item-darker| line-item-normal| line-item-smaller| line-item-larger| line-item-big| line-item-very-big/gi, function (x) {
8231		// 	return '';
8232		//   });
8233
8234		// var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, "data":cleanedHtmData, contentType: "application/xml" })
8235		// 	.success(function(data, textStatus, jqXHR) {
8236		// 		console.log(data);
8237		// 		GLO.Popup.closeIfExist(jprocessing);
8238		// 		if ((typeof(data) !== 'undefined') && (data !== null) && data !== '') {
8239		// 			SA.App.sendToiOSStarPrinter(data);
8240		// 		}
8241		// 		else {
8242		// 			GLO.Popup.closeIfExist(jprocessing);
8243		// 			GLO.UI.Form.resetProcessing(); 		
8244		// 			new GLO.Popup.Error('Invalid receipt data. Please try again or Send receipt via email or text.');
8245		// 		}
8246				
8247		// 	})
8248		// 	.error(function(jqXHR, textStatus, errorThrown) {
8249		// 		GLO.Popup.closeIfExist(jprocessing);
8250		// 		GLO.UI.Form.resetProcessing(); 		
8251		// 		new GLO.Popup.Error('Unable to print receipt to selected printer. Please try again or Send receipt via email or text.');
8252		// 	});
8253	}
8254    
8255	function _printByStaff3(staffid) {
8256		GLO.Popup.close($('#pop-select-print-staff-sales-summary').closest('.glopop'));
8257		
8258		var jtbl = $('#report-sales-history .tablesorter');
8259		//var thead = _cleanRow(jtbl.find('thead > tr')).outerHTML();
8260		var tbody = _getPrintByStaff(jtbl, staffid);
8261		
8262		var tbl = '<table class="tablesorter" style="width: 100%;">
8262' + tbody + '</table>';
8263		var ft = '<div id="staff-printout-footer" style="color: #666;"><small>printed </small><i>' + new Date().toPrettyDate(!GLO.Info.isMobile()) + '</i></div>';
8264    	var htm = '<div id="print-receipt" class="hide sales-history">' + tbl + ft + '</div>';
8265		
8266		UI.Print.print(htm, null, false);
8267		setTimeout(function() { $('#print-report-button > a').click(); }, 900);
8268    }
8269    
8270    function _reportDateRange() {
8271    	var j = $('#report-sales-history');
8272    	var start = new Date(j.find('.Report_Begin_dt').val());
8273    	var end = new Date(j.find('.Report_End_dt').val());
8274    	
8275    	if (start.getTime() == end.getTime()) {
8276    		return start.toSADate(true);
8277    	} else {
8278    		return start.toSADate(true) + ' - ' + end.toSADate(true);
8279    	}
8280    }
8281    
8282    function _getPrintByStaff(jtbl, staffid) {
8283    	var trs = jtbl.find('.service-row');
8284    	var trStaffPrint = '', tbody = '', prevStaff = null, priceTotal = 0, tipTotal = 0, isFirst = true;
8285    	var searchDate = _reportDateRange();
8286    	
8287    	for (var i=0; i < trs.length; i++) {
8288    		//var currStaff = UTIL.directTagOnly(trs.eq(i).find('.column-staff'));
8289    		var currStaff = trs.eq(i).find('.column-staff').attr('staff_id');
8290    		
8291    		if (!UTIL.isEmpty(staffid)) {
8292    			if (prevStaff === null && currStaff == staffid) {
8293    				prevStaff = currStaff;
8294    				tbody += _staffHeaderRow(UTIL.directTagOnly(trs.eq(i).find('.column-staff')), searchDate, i, isFirst);
8295    			}
8296    		} else if (prevStaff != currStaff) {
8297    			if (prevStaff !== null) {
8298    				tbody += _staffFooter(trStaffPrint, trs.eq(i), priceTotal, tipTotal);
8299    				trStaffPrint = '';
8300    			}
8301    			
8302    			prevStaff = currStaff;
8303    			tbody += _staffHeaderRow(UTIL.directTagOnly(trs.eq(i).find('.column-staff')), searchDate, i, isFirst);
8304    			isFirst = false;
8305    			priceTotal = tipTotal = 0;
8306    		}
8307    		
8308    		if (UTIL.isEmpty(staffid) || currStaff == staffid) {
8309	    		var price = UTIL.coalesceMoney(trs.eq(i).find('.column-price').text().replace('$', ''));
8310	    		
8311	    		if (GLO.Data.provider.commission_fee_type_cd == 10) {
8312	    			price -= UTIL.coalesceMoney(trs.eq(i).find('.column-staff-fee').text().replace('$', ''));
8313	    			trs.eq(i).find('.column-price').text(UTIL.displayMoney(price));
8314	    		}
8315	    		
8316	    		priceTotal += price;
8317	    		tipTotal += UTIL.coalesceMoney(trs.eq(i).find('.column-tip').text().replace('$', ''));
8318	    		trStaffPrint += _cleanRow(trs.eq(i)).outerHTML();
8319    		}
8320    	}
8321    	
8322    	if (i > 0) {
8323    		tbody += _staffFooter(trStaffPrint, trs.eq(i-1), priceTotal, tipTotal);
8324    	}
8325    	
8326    	return '<tbody>' + tbody + '</tbody>';
8327    }
8328    
8329    function _staffFooter(trStaffPrint, tr, priceTotal, tipTotal) {
8330    	tr = _cleanRow(tr);
8331		tr.css({ "border-top": "1px solid #666" });
8332		
8333		var tds = tr.find('td');
8334		
8335		for (var i=0; i < tds.length; i++) {
8336			var td = tds.eq(i);
8337			
8338			if (td.hasClass('column-price')) {
8339				td.html(UTIL.displayMoney(priceTotal));
8340			} else if (td.hasClass('column-tip')) {
8341				td.html(UTIL.displayMoney(tipTotal));
8342			} else {
8343				td.html('');
8344			}
8345		}
8346		
8347		trStaffPrint = UI.sortTable(trStaffPrint, 'purchase-date');
8348		return trStaffPrint + tr.outerHTML();
8349    }
8350    
8351    function _cleanRow(tr, isHeader) {
8352    	tr = tr.clone();
8353    	
8354    	tr.find('.column-staff').remove();
8355    	tr.find('.column-cost').remove();
8356    	tr.find('.column-profit').remove();
8357    	tr.find('.commission-cell').remove();
8358    	
8359    	return tr;
8360    }
8361    
8362    function _staffHeaderRow(staffName, searchDate, rowNumber, isFirst) {
8363    	var colspan = 3, pt = 80;
8364    	
8365    	if (rowNumber == 0 || isFirst) { pt = 4; }
8366    	var css = 'padding-top: ' + pt + 'px; padding-bottom: 8px; letter-spacing: 1px; text-align: center; font-weight: bold; font-size: large; color: black;';
8367    	
8368    	if (innerWidth >= 360) { ++colspan; }
8369    	if (innerWidth >= 420) { ++colspan; }
8370    	if (innerWidth >= 600) { ++colspan; }
8371    	
8372    	return '<tr> <td colspan="' + colspan + '" style="' + css + '">' + staffName + ': ' + searchDate + '</td></tr>';
8373    }
8374    
8375    function _getPriceLabel(price, discount, addOnFee, split, splitPercent, staffServiceFee, membershipCommissionPriceBase) {
8376    	var priceLabel = 'Price';
8377    	var isBizSplitDiscount = UTIL.coalesceInt(split, GLO.Data.provider.commission_split_discount_cd);			// ($.trim(split).toLowerCase() == 'business');
8378    	var isBizSplitFee = UTIL.coalesceInt(split, GLO.Data.provider.commission_split_fee_cd);
8379    	
8380    	if (membershipCommissionPriceBase > 0) {
8381    		price = UTIL.coalesceMoney(membershipCommissionPriceBase);
8382    		priceLabel += ' <small>(Membership Commission Price Base)</small>';
8383    	} else if (discount > 0 && !isBizSplitDiscount) {
8384    		//if (split != 2) {		//= subtract discount, unless split is from business
8385    		price = UTIL.coalesceMoney(price) - UTIL.coalesceMoney(discount);
8386    		priceLabel += ' <small>after subtracting ' + UTIL.displayMoney(discount) + ' discount</small>';
8387    	}
8388    	
8389    	if (addOnFee > 0 && !isBizSplitDiscount) {
8390    		//if (split != 2) {		//= subtract discount, unless split is from business
8391    		price = UTIL.coalesceMoney(price) + UTIL.coalesceMoney(addOnFee);
8392    		priceLabel += ' <small>after adding ' + UTIL.displayMoney(addOnFee) + ' add-on fee</small>';
8393    	}
8394    	
8395    	if (GLO.Data.provider.commission_fee_type_cd == 10 && UTIL.coalesceMoney(staffServiceFee) !== 0) {
8396    		price = UTIL.coalesceMoney(price) - UTIL.coalesceMoney(staffServiceFee);
8397    		priceLabel += ' <small>after subtracting ' + UTIL.displayMoney(staffServiceFee) + ' staff service fee</small>';
8398    	}
8399    	
8400    	return '<p id="custom-commission-service-price"><label>' + priceLabel + '</label><b>' + UTIL.displayMoney(price, false, false, true) + '</b></p>';
8401    }
8402    _conRptSales.openCustomCommissionFromCellSummary = function() {
8403    	var tr = $('#report-sales-history').find('td.cell-summary-selected').closest('tr');
8404    	
8405    	var scheduleInventoryId = UTIL.coalesceInt(tr.attr('schedule_inventory_id'));
8406    	var scheduleId = UTIL.coalesceInt(tr.attr('schedule_id')), scid = UTIL.coalesceInt(tr.attr('schedule_client_id'));
8407    	var staffName = tr.find('.column-staff').text();
8408    	var serviceName = tr.find('.column-name').text();
8409    	
8410    	var tdCommission = tr.find('.commission-cell');
8411    	var commission = UTIL.coalesceMoney(UTIL.directTagOnly(tdCommission).replace('$', ''));
8412    	var actualCommissionPercent = tdCommission.attr('actual_commission_pct');
8413    	
8414    	//var price = UTIL.coalesceMoney(tr.find('.column-price').text().replace('$', ''));			//cannot use this value as displayed price might be different for different provider settings
8415    	var price = UTIL.coalesceMoney(tr.attr('price_mn'));
8416    	
8417    	var discount = UTIL.coalesceMoney(tr.find('.column-discount').text().replace('$', ''));
8418    	var addOnFee = UTIL.coalesceMoney(tr.find('.column-add-on').text().replace('$', ''));
8419    	var split = tr.attr('commission_split_cd'), splitPercent = tr.attr('commission_split_pct');
8420    	var staffServiceFee = UTIL.coalesceMoney(tr.find('.column-staff-fee').text().replace('$', ''));
8421    	//var isProductSale = UTIL.parseBool(tr.hasClass('product-row'));
8422    	var membershipCommissionPriceBase = UTIL.coalesceMoney(tr.attr('membership_commission_price_base_mn'));
8423    	
8424    	var msg1 = '<p style="text-align: center;">' + staffName + ' ' + serviceName + '</p>';
8425    	var priceHtm = _getPriceLabel(price, discount, addOnFee, split, splitPercent, staffServiceFee, membershipCommissionPriceBase);
8426    	var msg = msg1 + priceHtm;
8427    	
8428    	_openCustomCommission(scheduleId, scid, scheduleInventoryId, msg, commission, staffServiceFee);
8429    }
8430    function _openCustomCommission(scheduleId, scid, scheduleInventoryId, msg, commission, staffServiceFee) {
8431    	var dollarSign = '<span class="dollar-sign" style="margin-left: 12px;">$</span>';
8432    	
8433    	var labelCommission = '<label for="Custom_Commission_mn">Commission</label>';
8434    	var inputCommission = '<input type="text" id="Custom_Commission_mn" value="' + UTIL.displayMoney(commission, true) + '"/>';
8435    	var tr1 =  '<tr><td>' + labelCommission + '</td><td>' + dollarSign + inputCommission + '</td></tr>';
8436    	
8437    	if (!UTIL.isEmpty(scheduleInventoryId)) {
8438    		var tr2 =  '';
8439    	} else {
8440	    	var labelFee = '<label for="Staff_Service_Fee_mn">Staff Service Fee</label>';
8441	    	var inputFee = '<input type="text" id="Staff_Service_Fee_mn" value="' + UTIL.displayMoney(staffServiceFee, true) + '"/>';
8442    		var tr2 =  '<tr><td>' + labelFee + '</td><td>' + dollarSign + inputFee + '</td></tr>';
8443    	}
8444    	
8445    	var tbl = '<table style="margin: auto; margin-bottom: 16px;">' + tr1 + tr2 + '</table>';
8446    	
8447    	var htm = '<div id="pop-custom-commission" schedule_id="' + scheduleId + '" schedule_client_id="' + $.trim(scid) + '" schedule_inventory_id="' + scheduleInventoryId + '">' + msg + tbl + '</div>';
8448    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Custom Commission', GLO.Report.Sales.saveCustomCommission);
8449    	var btnResetLabel = 'Reset';
8450    	
8451    	if (innerWidth > 550) {
8452    		btnResetLabel = 'Reset to Default';
8453    		jpop.find('.pop-buttons').css({ "min-width": "500px" });
8454    	}
8455    	
8456    	if (UTIL.isEmpty(scheduleInventoryId)) {
8457	    	var btnReset = '<span class="btnAdd btnReset" style="position: absolute; right: 4px;"><a onclick="GLO.Report.Sales.resetCustomCommission()">' + btnResetLabel + '</a></span>';
8458	    	jpop.find('.btnSave').css({ "position": "relative", "right": "inherit", "margin": "0" }).after(btnReset);
8459    	}
8460    	
8461    	var price = UTIL.coalesceMoney(jpop.find('#custom-commission-service-price b').text().replace('$', ''));
8462    	var pct = parseInt(UTIL.coalesceMoney(commission/price) * 100);
8463    	var btnPercentCommission = '<span id="btnPercentCommission" class="btnAdd"><a onclick="GLO.Report.Sales.openCustomCommissionChangePercent()">' + pct + '%</a></span>';
8464    	jpop.find('#Custom_Commission_mn').after(btnPercentCommission);
8465    }
8466    
8467    _conRptSales.openCustomCommissionChangePercent = function() {
8468    	var pct = $('#pop-custom-commission #btnPercentCommission > a').text().replace('%', '');
8469    	var htmPercent = '<input id="Custom_Commission_pct" type="number" value="' + pct + '" min="0" max="100" style="width: 50px; letter-spacing: 1px; text-align: center; font-weight: bold;">';
8470    	var htm = '<div id="pop-custom-commission-percent">' + htmPercent + '</div>';
8471    	
8472    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Change Commission Percent for this Service');
8473    	GLO.Popup.Custom.singleButtonNew(jpop, 'Change', GLO.Report.Sales.changeCustomCommissionPercent).find('> a');
8474    }
8475    _conRptSales.changeCustomCommissionPercent = function() {
8476    	var jPopPercent = $('#pop-custom-commission-percent').closest('.glopop');
8477    	var pct = parseInt(jPopPercent.find('#Custom_Commission_pct').val());
8478    	
8479    	var jPopMain = $('#pop-custom-commission').closest('.glopop');
8480    	var price = UTIL.coalesceMoney(jPopMain.find('#custom-commission-service-price b').text().replace('$', ''));
8481    	var newCommission = UTIL.displayMoney(pct/100 * price, true);
8482    	
8483    	jPopMain.find('#Custom_Commission_mn').val(newCommission);
8484    	jPopMain.find('#btnPercentCommission > a').text(pct + '%');
8485    	
8486    	GLO.Popup.close(jPopPercent);
8487    }
8488    
8489    _conRptSales.resetCustomCommission = function() {
8490    	var jpop = $('#pop-custom-commission').closest('.glopop');
8491    	jpop.find('#Custom_Commission_mn').val('');
8492    	jpop.find('#Staff_Service_Fee_mn').val('');
8493    	
8494    	GLO.UI.Form.beginProcessing( jpop.find('.btnReset') );
8495    	_conRptSales.saveCustomCommission(true);
8496    }
8497    _conRptSales.saveCustomCommission = function(isReset) {
8498    	var jpop = $('#pop-custom-commission');
8499    	var scheduleId = jpop.attr('schedule_id'), scid = UTIL.coalesceInt(jpop.attr('schedule_client_id')), scheduleInventoryId = jpop.attr('schedule_inventory_id');
8500    	var commission = jpop.find('#Custom_Commission_mn').val();
8501    	
8502    	if (!UTIL.isEmpty(scheduleInventoryId)) {
8503    		var url = GLO.Link.WebsiteDomain + 'schedule/CustomCommissionProduct?siid=' + scheduleInventoryId;
8504    	} else {
8505    		var url = GLO.Link.WebsiteDomain + 'schedule/CustomCommission?scheduleid=' + scheduleId;
8506    		var fee = jpop.find('#Staff_Service_Fee_mn').val();
8507    		
8508    		if (!UTIL.isEmpty(scid)) {
8509	    		url += '&scid=' + scid;
8510	    	}
8511	    	
8512	    	if (!UTIL.isEmpty(fee)) {
8513	    		url += '&fee=' + UTIL.coalesceMoney(fee);
8514	    	}
8515    	}
8516    	
8517    	if (!UTIL.isEmpty(commission)) {
8518    		url += '&commission=' + UTIL.coalesceMoney(commission);
8519    	}
8520    	
8521    	if (isReset) {
8522    		url += '&isReset=true';
8523    	}
8524    	
8525    	jpop = jpop.closest('.glopop');
8526    	GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
8527		GLO.Popup.close( $('#pop-help-cell-summary').closest('.glopop') );
8528		
8529    	$.ajax({ type: "POST", url: url, "cache": false, data: {} })
8530            .success(function(data, textStatus, jqXHR) {
8531                if (isReset) {
8532	                var msg = '<p>Commission and Staff Service Fee reset to default</p>';
8533	                var tr = $('#report-sales-history').find('tr[schedule_id="' + scheduleId + '"]');
8534                } else {
8535	                commission = UTIL.displayMoney(commission);
8536	                fee = UTIL.displayMoney(fee);
8537	                
8538	                if (commission == '') { commission = '$0'; }
8539	                if (fee == '') { fee = '$0'; }
8540	                
8541	                if (!UTIL.isEmpty(scheduleInventoryId)) {
8542	                	var msg = '<p>Product Commission updated to: ' + commission + '<p>';
8543	                	var tr = $('#report-sales-history').find('tr[schedule_inventory_id="' + scheduleInventoryId + '"]');
8544	                } else {
8545	                	var msg = '<p>Service Commission updated to: ' + commission + '<p><p>Staff Service Fee updated to: ' + fee + '</p>';
8546	                	var tr = $('#report-sales-history').find('tr[schedule_id="' + scheduleId + '"]');
8547                		tr.find('.column-staff-fee').text(fee);
8548	                }
8549                }
8550                
8551                tr.find('.commission-cell').text(commission);
8552                GLO.Popup.close(jpop);
8553                GLO.Popup.Success.open(msg);
8554                GLO.Report.Template.search();
8555            })
8556            .error(function(jqXHR, textStatus, errorThrown) {
8557                GLO.Popup.Error('Unable to customize commission at this time.  Please try again.'); 
8558                GLO.UI.Form.resetProcessing();
8559            });
8560    }
8561    
8562    _conRptSales.openHelpApptvsProductDate = function(element, serviceCount, productCount, apptStartDate, productPurchaseDate) {
8563    	var msg1 = '<h4>Ticket has ' + UTIL.pluralLabel(serviceCount, 'service') + ' and ' + UTIL.pluralLabel(productCount, 'product') + '</h4>';
8564    	var arrow = ' <b class="arrow-right">&#10140;</b> ';
8565    	
8566    	if (serviceCount > 0 && productCount > 0) {
8567    		var header = 'Appointment + Product Purchase Date Different';
8568    		var labelProductPurchaseDate = '<b class="narrow-text">Product Purchase Date</b>';
8569    		var labelApptStartDate = '<b class="narrow-text">Appointment Start Date</b>';
8570    		
8571    		var labelServiceTicketDate = '<b class="narrow-text">Service Ticket Date</b>';
8572    		var labelProductTicketDate = '<b class="narrow-text">Product Ticket Date</b>';
8573    		
8574    		var dtAppt = labelApptStartDate + ' <i>' + apptStartDate + '</i>';
8575    		var dtProd = labelProductPurchaseDate + ' <i>' + productPurchaseDate + '</i>';
8576    		
8577    		var msg2a = dtAppt + ' and ' + dtProd + ' are different';
8578    		var msg2b = 'So the ' + labelServiceTicketDate + ' and ' + labelProductTicketDate + ' are different on this appointment';
8579    		var msg2 = '<p>' + msg2a + arrow + msg2b + '</p>';
8580    		
8581    		var rptSalesSummary = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/sales#tab=sales-summary\')" style="font-weight: bold;">Sales Summary</a>';
8582    		var rptSalesDetail = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/sales#tab=sales-history\')" style="font-weight: bold;">Sales Detail</a>';
8583    		//var rptOther = ' and on the Staff Summary and Staff Goal reports';
8584    		
8585    		var rptException = '<i class="narrow-text">like on the ' + rptSalesSummary + ' and ' + rptSalesDetail + ' reports where the sales will show up on the ' + labelProductPurchaseDate + '</i>';
8586    		var payProductDateExplain = '<span class="narrow-text">(the date the product payment was made)</span>';
8587    		
8588    		var msg3 = '<p style="letter-spacing: 0;">This ticket\'s service sales will show up on reports on the appointment start date</p>';
8589    		var msg4 = '<p>This ticket prouduct sales will show up on some reports on the product sale date ' + payProductDateExplain + rptException + '</p>';
8590    	} else {
8591    		var header = 'Ticket Info';
8592    		var msg2 = '', msg3 = '', msg4 = '';
8593    	}
8594    	
8595    	var htm = '<div id="pop-help-appt-vs-product-date">' + msg1 + msg2 + msg3 + msg4 + '</div>';
8596    	GLO.Popup.Info.open(htm, header);
8597    }
8598    
8599    _conRptSales.changeIncludeUnpaid = function() {
8600    	if ($('#Include_Unpaid_Tickets_fl').prop('checked')) {
8601    		var isIncludeUnpaid = '1';
8602    	} else {
8603    		var isIncludeUnpaid = '0';
8604    	}
8605    	
8606    	UTIL.setCookie('sales-detail-display-pay-warning', isIncludeUnpaid);
8607    	UTIL.setCookie('sales-detail-is-include-unpaid', isIncludeUnpaid);
8608    }
8609    
8610    _conRptSales.helpIncludeUnpaid = function() {
8611    	var msg1 = '<p>When checked all services and products are returned <span class="narrow-text">(that match report filter)</span></p>';
8612    	var msg2 = '<p></p>';
8613    	var msg3 = '<p>When un-checked only tickets that are either checked-out or have a payment <span class="narrow-text">(includes tickets partially paid)</span></p>';
8614    	var msg4 = '<p></p>';
8615    	
8616    	var header = '<b style="white-space: nowrap;">Sales Detail Report:</b> <b style="white-space: nowrap;">Include Un-Paid Tickets</b>';
8617    	var htm = '<div id="pop-help-include-unpaid">' + msg1 + msg2 + msg3 + msg4 + '</div>';
8618    	GLO.Popup.Info.open(htm, );
8619    }
8620    
8621    return _conRptSales;
8622})();
8623
8624
8625GLO.Report.CreditCardMerged = (function() {
8626	function _conRptCC2() { }
8627    
8628    _conRptCC2.init = function() {
8629    	UI.initTableSorter( $('table.tablesorter:visible') );
8630        
8631        GLO.Report.setupFastClick();
8632    }
8633    
8634	return _conRptCC2;
8635})();
8636
8637
8638GLO.Report.CreditCard = (function() {
8639	function _conRptCC() { }
8640    
8641    _conRptCC.currentTab = 1;
8642    _conRptCC.MAX_TAB = 3;
8643    
8644    _conRptCC.init = function() {
8645    	var rptHistory = $('#report-payment-history')
8646    	rptHistory.find('.Payment_Method_cd').val(10).addClass('hide').addClass('use');
8647    	
8648    	$('#report-unsettled-transactions .Merchant_id').attr('onchange', 'GLO.Report.CreditCard.fiterUnSettled(this)');
8649    	
8650    	_conRptCC.postSearch(rptHistory, 'payment-history');
8651        _addBuyerAutoComplete();
8652        
8653        var initTab = GLO.Report.Template.init();				//GLO.Report.setupFastClick();
8654        initTab = _getTabNumber(initTab);
8655        _conRptCC.goToTab(initTab);
8656    }
8657    
8658    function _getTabNumber(tab) {
8659    	tab = String(tab).toLowerCase();
8660            
8661        if (tab === 'unsettled-transactions' || tab == '1') {
8662            tab = 1;
8663        } else if (tab === 'settled-transactions' || tab == '2') {
8664            tab = 2;
8665        } else if (tab === 'refund-history' || tab == '3') {
8666            tab = 3;
8667        } else {
8668        	if (tab > _conRptCC.MAX_TAB) {
8669	            tab = _conRptCC.MAX_TAB;
8670	        } else {
8671        		tab = _conRptCC.currentTab;
8672        	}
8673        }
8674        
8675        return tab;
8676    }
8677    
8678    _conRptCC.goToTab = function(tab) {
8679        $('#report-unsettled-transactions').addClass('hide');
8680        $('#report-settled-transactions').addClass('hide');
8681        $('#report-refund-history').addClass('hide');
8682        
8683        if (tab === 1) {
8684            var hashTab = 'unsettled-transactions';
8685            $('#report-unsettled-transactions').removeClass('hide');
8686        } else if (tab === 2) {
8687            var hashTab = 'settled-transactions';
8688            $('#report-settled-transactions').removeClass('hide');
8689        } else if (tab === 3) {
8690            var hashTab = 'refund-history';
8691            $('#report-refund-history').removeClass('hide');
8692        }
8693
8694        var backColor = $('.shadow-content0').css('backgroundColor');
8695        var jhead = $('#report-portal-header');
8696        var oj = jhead.find('table tr td span b');
8697        
8698        oj.each(function() {
8699            $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent');
8700        });
8701
8702        oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent();
8703        oj.addClass('report-tab');
8704        oj.css('backgroundColor', backColor);
8705
8706        _conRptCC.currentTab = tab;
8707        document.location.hash = 'tab=' + hashTab;
8708    }
8709    
8710    function _addBuyerAutoComplete() {
8711        var jAuto = $('.buyer-autocomplete');
8712        var jselect = $('td.merchant-account-column');
8713        
8714        if (jselect.find('option').length > 2) {
8715        	$('th.merchant-account-column label').html('Merchant Account');
8716        } else {
8717        	$('th.merchant-account-column').remove();
8718        	jselect.remove();
8719        }
8720        
8721        for (var i=0; i < jAuto.length; i++) {
8722        	var jBuyer = jAuto.eq(i);
8723        	
8724        	jBuyer.autocomplete({
8725	                source: GLO.Link.Object.Provider.Ajax + 'ClientAndStaffSearch',
8726	                minLength: 2,
8727	                select: function(event, ui) {
8728	                    jBuyer.attr('buyer_id', ui.item.id);
8729	                }
8730	            });
8731	        
8732	        jAuto.eq(i).data("ui-autocomplete")._renderItem = function(ul, item) {
8733	            var cssClass = "";
8734	            if (item.id.substring(0,1) === 'S') { cssClass = " class='item-staff'"; }
8735	            
8736	            return $("<li" + cssClass + "></li>")
8737			        .data("ui-autocomplete-item", item)
8738			        .append("<a>" + item.label + "</a>")
8739			        .appendTo(ul);
8740	        }
8741        }
8742        
8743        //jAuto.focus();
8744    }
8745    
8746    _conRptCC.changeBuyer = function(element) {
8747    	if (UTIL.isEmpty(element.value)) { $(element).attr('buyer_id', ''); }
8748    }
8749    
8750    _conRptCC.fiterUnSettled = function(select) {
8751    	var rpt = $('.report-container:visible');
8752    	var tr = rpt.find('tbody tr');
8753    	var merchantId = select.value;
8754    	var tip = 0, refund = 0, total = 0;
8755    	
8756    	if (!UTIL.isEmpty(merchantId)) {
8757	    	for (var i=0; i < tr.length; i++) {
8758	    		if (tr.eq(i).attr('merchant_id') == merchantId) {
8759	    			tr.eq(i).removeClass('hide');
8760	    			tip += UTIL.coalesceMoney(tr.eq(i).find('td.tip').text().replace('$', ''));
8761	    			total += UTIL.coalesceMoney(tr.eq(i).find('td.payment').text().replace('$', ''));
8762	    			refund += UTIL.coalesceMoney(tr.eq(i).find('td.refund').text().replace('$', ''));
8763	    		} else {
8764	    			tr.eq(i).addClass('hide');
8765	    		}
8766	    	}
8767    	} else {
8768    		for (var i=0; i < tr.length; i++) {
8769	    		tr.eq(i).removeClass('hide');
8770	    		tip += UTIL.coalesceMoney(tr.eq(i).find('td.tip').text().replace('$', ''));
8771	    		total += UTIL.coalesceMoney(tr.eq(i).find('td.payment').text().replace('$', ''));
8772	    		refund += UTIL.coalesceMoney(tr.eq(i).find('td.refund').text().replace('$', ''));
8773	    	}
8774    	}
8775    	
8776    	var tfoot = rpt.find('tfoot');
8777    	tfoot.find('.tip').text(UTIL.displayMoney(tip));
8778    	tfoot.find('.refund').text(UTIL.displayMoney(refund));
8779    	tfoot.find('.payment').text(UTIL.displayMoney(total));
8780    }
8781    
8782    _conRptCC.movePrev = function() {
8783        GLO.Report.Template.moveDates(-1);
8784        _conRptCC.searchTransaction();
8785    }
8786    
8787    _conRptCC.moveNext = function() {
8788        GLO.Report.Template.moveDates(1);
8789        _conRptCC.searchTransaction();
8790    }
8791
8792    _conRptCC.searchTransaction = function(launchSettleBatch) {
8793    	var jhead = $('.report-search-header:visible');
8794        var jrpt = $('.entire-report:visible');
8795        var rtype = jrpt.attr('id').replace('report-', '');
8796        jrpt = jrpt.find('.report-container');
8797        
8798        var start = UTIL.cleanString(jhead.find('.Report_Begin_dt').val())
8799        var end = UTIL.cleanString(jhead.find('.Report_End_dt').val());
8800        var mid = jhead.find('.Merchant_id').val();
8801        var uhash = 'rtype=' + rtype + '&merchant_id=' + mid;
8802        
8803        if (rtype === 'unsettled-transactions' || rtype === 'batch') {
8804        	
8805        } else if (!_isValidDate(start, end)) {
8806        	return;
8807        } else {
8808        	var buyer = jhead.find('.buyer-autocomplete').attr('buyer_id');
8809        	uhash += '&start=' + start + '&end=' + end;
8810        	
8811        	if (!UTIL.isEmpty(buyer)) {
8812		        if (buyer.substring(0, 1) === 'S') {
8813		        	uhash += '&payment_from_staff_id=' + buyer.substring(1);
8814		        } else {
8815		        	if (buyer.substring(0, 1) === 'C') { buyer = buyer.substring(1); }
8816		        	
8817		        	uhash += '&payment_from_client_id=' + buyer;
8818		        }
8819	        }
8820        }
8821        
8822        var url = GLO.Link.Page.Provider.Home + 'report/SearchCreditTransaction?' + uhash;
8823        var searchBtn = jhead.parent().find('.btnSearch:visible')
8824        GLO.UI.Form.beginProcessing(searchBtn);
8825        
8826        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
8827            .success(function(data, textStatus, jqXHR) {
8828                GLO.UI.Form.resetProcessing();
8829                GLO.Report.CreditCard.searchTransactionLoad(jrpt, data);
8830                
8831                if (launchSettleBatch) {
8832                	GLO.Report.CreditCard.settleBatch();
8833                }
8834            })
8835            .error(function(jqXHR, textStatus, errorThrown) {
8836                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
8837                GLO.UI.Form.resetProcessing();
8838            });
8839    }
8840    
8841    _conRptCC.searchTransactionLoad = function(jrpt, data) {
8842    	GLO.UI.Form.resetProcessing();
8843        
8844        if (!UTIL.isEmpty(data)) {
8845            jrpt.html(data);
8846            UI.initTableSorter( jrpt.find('table.tablesorter:visible') );
8847        } else {
8848            GLO.Popup.Info(SA.Resource.NoResultsFound);
8849        }
8850    }
8851    
8852    function _isValidDate(start, end) {
8853    	if (!UTIL.isDate(start)) {
8854            GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('.Report_Begin_dt:visible'); });
8855            return false;
8856        } else if (!UTIL.isDate(end)) {
8857            GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('.Report_End_dt:visible'); });
8858            return false;
8859        } else if (new Date(start) > new Date(end)) {
8860            GLO.Popup.Warning(SA.Resource.BeginDateWarning2);
8861            return false;
8862        } else {
8863        	return true;
8864        }
8865    }
8866    
8867    _conRptCC.postSearch = function(jrpt, report) {
8868    	jrpt = jrpt.find('table.payment-history');
8869    	jrpt.find('th#payment-header').css({ "text-align": "right" });
8870    	
8871    	if (jrpt.find('th#pay-meth-header').length === 1) { jrpt.find('th:last-child, td:last-child').remove(); }
8872    	jrpt.find('th:last-child, td:last-child').remove();
8873    }
8874    
8875    _conRptCC.settleBatch = function() {
8876    	var jrpt = $('#cc-report');
8877    	var tranCount = jrpt.find('tbody tr:not(.hide)').length;
8878    	var preAuthCount = jrpt.find('tbody tr.cc-pre-auth:not(.hide)').length;
8879    	var merchantName = jrpt.find('.Merchant_id option:selected');
8880    	var mName = '';
8881    	var pmid = $('#report-batch').attr('merchant_id');
8882    	var merchantCo = UserPortal.Price.Payment.getMerchantCompany(pmid, 30);				//UTIL.coalesceInt(GLO.Data.provider.merchant_vendor_cd, 30);
8883    	
8884    	if (merchantName.length > 0) {
8885    		if (merchantName.text() == 'All') {
8886    			mName = ' for all merchant accounts';
8887    		} else {
8888    			mName = ' for ' + merchantName.text();
8889    		}
8890    	}
8891    	
8892    	var msg = '<div id="pop-settle-batch">'
8893    				+ '<h1 class="friendly-msg2" style="margin-bottom: 0; padding-bottom: 1px;">' + SA.Resource.SettleBatch + '?</h1>'
8894    				+ '<div>'
8895    					+ '<div id="pop-settle-batch-warning">' + SA.Resource.AfterSettleBatchCannotAddTips + '</div>'
8896    					+ '<div class="friendly-msg2">' + SA.Resource.Settle + ' ' + tranCount + ' ' + SA.Resource.Transactions + mName + '?</div>'			//(tranCount - preAuthCount)
8897    					+ '<div id="pop-settle-batch-explanation">' + SA.Resource.SettleBatchHelp + '</div>'
8898    				+ '</div>'
8899    			+ '</div>';
8900    	
8901    	if (false && preAuthCount > 0) {			//= no longer support not upgrading auths
8902    		var warnMsg = '<div><h1 class="friendly-quick-msg" style="margin-bottom: 0; padding-bottom: 1px;">' + SA.Resource.AuthorizePayments + '?</h1>'
8903    						+ '<div class="friendly-quick-msg" style="color: Red; line-height: 200%;">';
8904    		
8905    		if (preAuthCount == 1) {
8906    			warnMsg += '1 ' + SA.Resource.PaymentIsNotAuthorized + '<br/>' + SA.Resource.AuthorizeThisPayment + '?</div></div>';
8907    		} else {
8908    			warnMsg += preAuthCount + ' ' + SA.Resource.PaymentsAreNotAuthorized + '<br/>' + SA.Resource.AuthorizeThesePayments + '?</div></div>';
8909    		}
8910    		
8911    		var oj = new GLO.Popup.Warning(warnMsg);
8912    		var jbtn = oj.getPopup().find('.pop-buttons');
8913    		
8914    		var btnNo = jbtn.find('.btnOk').click(function() { GLO.Report.Credit
8914Card.settleBatchQues(msg); })
8915    		btnNo.css({ "float": "none", "position": "absolute", "left": "0", "padding-left": "9px" }).addClass('btnNo').removeClass('btnOk').find('a').text('No');
8916    		
8917    		jbtn.append('<span class="btnSave" onclick="GLO.Report.CreditCard.upgradeBatch()" style="position: absolute; right: 0;"><a>' + SA.Resource.Yes + '</a></span>');
8918    	} else if (merchantCo === 30) {				//= send email only
8919    		_conRptCC.settleBatchConfirmed();
8920    	} else {
8921    		_conRptCC.settleBatchQues(msg);
8922    	}
8923    }
8924    
8925    _conRptCC.settleBatchQues = function(msg) {
8926    	var oj = new GLO.Popup.Confirm(msg, GLO.Report.CreditCard.settleBatchConfirmed);
8927    	var jpop = oj.getPopup();
8928    	
8929    	jpop.find('.msg').css({ "text-align": "center", "padding-right": "20px" });
8930    	
8931    	var jbtn = jpop.find('.pop-buttons');
8932    	jbtn.find('.btnNo').css({ "padding-left": "70px" });
8933    }
8934    
8935    _conRptCC.upgradeBatch = function() {
8936    	var jrpt = $('#report-unsettled-transactions');
8937    	
8938    	if (jrpt.length === 1) {
8939    		var mid = jrpt.find('.Merchant_id').val();
8940    		var jhead = jrpt;
8941    	} else {
8942    		jrpt = $('#report-batch');								//tr.cc-pre-auth
8943    		var jhead = $('.report-search-header:visible');
8944    		var mid = jhead.find('.Merchant_id').val();
8945    	}
8946    	
8947    	var url = GLO.Link.WebsiteDomain + 'payment/UpgradeBatch';
8948    	
8949    	var jWarnPop = $('.pop-warning:visible');
8950    	GLO.UI.Form.beginProcessing( jWarnPop.find('.btnSave') );
8951		
8952    	$.ajax({ type: "POST", url: url, "cache": false, data: { "merchant_id": mid } })
8953            .success(function(data, textStatus, jqXHR) {
8954                GLO.Popup.close(jWarnPop);
8955                GLO.Report.CreditCardBatch.refresh(true);		//GLO.Report.CreditCard.searchTransaction(true);		//$('#report-unsettled-transactions').find('.report-search-header .btnSearch').find('a').click();
8956            })
8957            .error(function(jqXHR, textStatus, errorThrown) {
8958                GLO.Popup.Error('Unable to upgrade these payments at this time.  Please try again.'); 
8959                GLO.UI.Form.resetProcessing();
8960            });
8961    }
8962    
8963    _conRptCC.settleBatchConfirmed = function() {
8964    	var jrpt = $('#report-unsettled-transactions');
8965    	
8966    	if (jrpt.length === 1) {
8967    		var mid = jrpt.find('.Merchant_id').val();
8968    		var jhead = jrpt;
8969    	} else {
8970    		jrpt = $('#report-batch');
8971    		var jhead = $('.report-search-header:visible');
8972    		var mid = jhead.find('.Merchant_id').val();
8973    	}
8974    	
8975    	var url = GLO.Link.WebsiteDomain + 'payment/SettleBatch';
8976    	GLO.UI.Form.beginProcessing( jhead.find('.btnSave') );
8977		
8978    	$.ajax({ type: "POST", url: url, "cache": false, data: { "merchant_id": mid } })
8979            .success(function(data, textStatus, jqXHR) {
8980                _settleBatchCompleted(data, jhead);
8981            })
8982            .error(function(jqXHR, textStatus, errorThrown) {
8983                GLO.Popup.Error('Unable to settle batch at this time.  Please try again later.'); 
8984                GLO.UI.Form.resetProcessing();
8985            });
8986    }
8987    
8988    function _settleBatchCompleted(data, jhead) {
8989    	GLO.UI.Form.resetProcessing();
8990        
8991        var jbatch = $(data).find('batch');
8992        var status, amt = 0, cnt = 0, totalTransactions = 0, nm = '', msgErr = '', msgSuccess = '';
8993        
8994        for (var i=0; i < jbatch.length; i++) {
8995        	amt = UTIL.coalesceMoney(jbatch.eq(i).attr('amount_mn'));
8996        	cnt = UTIL.coalesceInt(jbatch.eq(i).attr('transaction_count_nr'));
8997        	nm = _getMerchantBatchName(jbatch.eq(i), i);
8998        	status = jbatch.eq(i).attr('status');
8999        	totalTransactions += cnt;
9000        	
9001        	if (status.indexOf(';') !== -1) {
9002        		var status0 = status.substring(0, status.indexOf(';'));
9003        	} else {
9004        		var status0 = status;
9005        	}
9006        	
9007        	if (status0 === 'ACCEPTED' || status0 === 'SUCCESS' || status0 === 'APPROVED') {
9008        		if (!UTIL.isEmpty(nm)) { nm = '<b>' + nm + '</b>: '; }
9009        		
9010        		if (amt > 0 && cnt > 0) {
9011        			msgSuccess += '<li class="successful-batch">' + nm + SA.Resource.BatchSuccessfullySettled + ', ' + cnt + ' ' + SA.Resource.transactions_batch_amount + ': ' + _displayBatchAmount(amt) + '</li>';
9012        		}
9013        	} else {
9014        		var err = jbatch.eq(i).html();
9015        		
9016        		if (UTIL.isEmpty(err)) {
9017        			if (status0 !== 'EMPTY' && status0 !== 'ACCEPTED' && status0 !== 'SUCCESS' && status0 === 'APPROVED') {
9018        				err = SA.Resource.ErrorProcessingBatch;
9019        			} else {
9020        				err = SA.Resource.BatchIsEmpty + ', ' + cnt + ' ' + SA.Resource.transactions_batch_amount + ' = ' + _displayBatchAmount(amt) + '</li>';
9021        			}
9022        		}
9023        		
9024        		msgErr += '<li><b>' + nm + '</b>: ' + err + '</li>';
9025        	}
9026        }
9027        
9028        if (i > 1) {
9029        	var ul = '<div><h1 class="friendly-quick-msg">' + SA.Resource.BatchResults + '</h1><ul id="settle-batch-result">';
9030        } else {
9031        	var ul = '<div><h1 class="friendly-quick-msg">' + SA.Resource.BatchResults + '</h1><ul>';
9032        }
9033        
9034        if (!UTIL.isEmpty(msgErr)) {
9035        	if (!UTIL.isEmpty(msgSuccess)) { msgErr = msgSuccess + msgErr; }
9036        	
9037        	if (status0 === 'EMPTY') {
9038        		new GLO.Popup.Warning(ul + msgErr + '</ul></div>');
9039        	} else {
9040        		new GLO.Popup.Error(ul + msgErr + '</ul></div>');
9041        	}
9042        } else if (!UTIL.isEmpty(msgSuccess)) {
9043        	new GLO.Popup.Success(ul + msgSuccess + '</ul></div>');
9044        }
9045        
9046        jhead.find('.btnSearch > a').click();				//if (totalTransactions > 0) { GLO.Report.CreditCard.searchTransaction(); }
9047    }
9048    
9049    function _displayBatchAmount(amt) {
9050    	if (amt == 0) {
9051    		return '$0';
9052    	} else {
9053    		return UTIL.displayMoney(amt);
9054    	}
9055    }
9056    
9057    function _getMerchantBatchName(batch) {
9058    	var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99);
9059    	
9060    	if (GLO.Info.providerPackage !== 1 && mt > 9 && mt < 90) {
9061	    	var nm = batch.attr('mname');
9062			
9063			if (UTIL.isEmpty(nm) && !UTIL.isEmpty(batch.attr('staff_id'))) {
9064				nm = UserPortal.lookupStaffName(batch.attr('staff_id'));
9065			}
9066			
9067			//if (!UTIL.isEmpty(nm)) { nm = ' for ' + nm; }
9068			return nm;
9069		} else {
9070			return '';
9071		}
9072    } 
9073    
9074    return _conRptCC;
9075})();
9076
9077
9078GLO.Report.CreditCardBatch = (function() {
9079	function _conRptCCB() { }
9080    
9081    _conRptCCB.init = function() {
9082    	//$('#header-icon-container').remove();
9083    	var jtbl = $('table#cc-report.tablesorter:visible');
9084    	
9085    	UI.initTableSorter(jtbl);
9086        var mid = GLO.Uri.query('mid');
9087        var jmerchant = $('#report-main .Merchant_id');
9088        
9089        if (!UTIL.isEmpty(mid)) { jmerchant.val(mid); }
9090        
9091        jmerchant.attr('id', 'Merchant_id').change(GLO.Report.CreditCardBatch.changeMerchant);
9092        
9093        $('#report-batch-day').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
9094    										, minDate: "-6m", maxDate: 0, dateFormat: "M d, yy", numberOfMonths: 1, beforeShow: UI.loadDatepicker });
9095    	_onLoad();
9096    	GLO.Report.setupFastClick();
9097        GLO.Report.enableFullPageCheck();
9098        GLO.Report.CellSummary.initReport(jtbl);
9099        $('#doc3').addClass('is-payment-report');
9100    }
9101    
9102    function _onLoad() {
9103    	var jmerchant = $('#bd #report-main .Merchant_id');
9104    	var jhead = $('#bd #report-main .report-search-header')
9105    	var co = jmerchant.find(':selected').attr('merchant_vendor_cd');
9106    	
9107    	if (UTIL.isEmpty(co)) {
9108    		co = GLO.Data.provider.merchant_vendor_cd;
9109    	}
9110    	
9111    	if (co == 30) {
9112    		jhead.find('#report-batch-day, #help-batch-header-card-connect').removeClass('hide');
9113    		jhead.addClass('display-arrows');
9114    	} else {
9115    		jhead.find('#report-batch-day, #help-batch-header-card-connect').addClass('hide');
9116    		jhead.removeClass('display-arrows');
9117    	}
9118    }
9119    
9120    _conRptCCB.changeMerchant = function() {
9121    	_conRptCCB.refresh();
9122    	_onLoad();
9123    }
9124    
9125    _conRptCCB.moveBatchDay = function(moveByDays) {
9126    	var jday = $('#report-batch-day');
9127    	var day = _getSearchDate(jday);
9128        
9129        if (UTIL.isEmpty(day)) {
9130        	return;
9131        }
9132        
9133        day.addDays(moveByDays);
9134        
9135        if (UTIL.isEmpty(day)) {
9136        	var fn = function() {
9137        		$('#report-batch-day').focus();
9138        	}
9139        	
9140        	GLO.Popup.Warning.open('Please Enter Batch Day', 'Batch Day Empty', fn);
9141        	return;
9142        } else if (day > new Date()) {
9143        	var htm = '<p>' + day.toGloDateString(true, true) + ' is in the future</p><p>No Batch Information for Future Days</p>';
9144        	GLO.Popup.Warning.open(htm, 'Invalid Day');
9145        	return;
9146        }
9147        
9148        UI.setDateInput(jday, day);
9149        GLO.Report.CreditCardBatch.refresh();
9150    }
9151    function _getSearchDate(jdt) {
9152    	if (jdt.hasClass('is-sa-date')) {
9153    		var dt = UTIL.fromSADate(jdt.val());
9154    	} else {
9155    		var dt = UTIL.replaceAll(jdt.val(), '-', '/');			//= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone).
9156    	}
9157    	
9158    	if (UTIL.isDate(dt)) {
9159            return new Date(dt);
9160        } else {
9161        	return null;
9162        }
9163    }
9164    
9165    _conRptCCB.refresh = function(launchSettleBatch) {
9166    	var jd = {}, jrpt = $('#report-main');
9167    	var btnRefresh = jrpt.find('#btnRefresh');
9168    	var mid = jrpt.find('#Merchant_id').val();
9169    	var dayText = jrpt.find('#report-batch-day:visible').val();
9170    	var pageTitle = SA.Resource.BatchReport;
9171    	var url = GLO.Link.WebsiteDomain + 'payment/ReportBatch';
9172        
9173        if (!GLO.Report.hasReportPassword(jd)) {
9174	    	return;
9175	    }
9176	    
9177        if (!UTIL.isEmpty(mid)) {
9178        	url = GLO.Uri.addQueryKeyAndValue(url, 'mid=' + mid);
9179        	pageTitle = jrpt.find('#Merchant_id').find(':selected').text() + ' ' + pageTitle;
9180        }
9181        
9182        if (UTIL.isDate(dayText)) {
9183        	var day = UTIL.fromSADate(dayText);
9184        	pageTitle = dayText + ' ' + pageTitle;
9185        	
9186        	if (!UTIL.isToday(day)) {			//if (day.toGloDate() != new Date().toGloDate()) {
9187        		url = GLO.Uri.addQueryKeyAndValue(url, 'day=' + day.toGloDate());
9188        	}
9189        }
9190        
9191        var urlFullScreen = url;
9192        url = GLO.Uri.addQueryKeyAndValue(url, 'ispartial=1');
9193        
9194        GLO.UI.Form.beginProcessing(btnRefresh);
9195        jrpt = jrpt.find('.report-container');
9196        
9197        var ml = (jrpt.width() - 40)/2;
9198    	var throbber = $('.loadingDiv').clone().find('img').css({ "margin": "40px auto", "margin-left": ml });
9199    	jrpt.html(throbber);
9200        
9201        $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd })
9202            .success(function(data, textStatus, jqXHR) {
9203                jrpt.html(data);
9204		        jrpt = jrpt.find('#cc-report:visible')
9205		        
9206		        if (jrpt.length === 1) {
9207		        	UI.initTableSorter(jrpt);
9208		        	GLO.Report.CellSummary.initReport(jrpt);
9209		        }
9210		        
9211                GLO.UI.Form.resetProcessing();
9212                window.history.pushState("", pageTitle, urlFullScreen);			//window.history.pushState({ "pageTitle": pageTitle } , "", urlFullScreen);
9213                document.title = pageTitle;
9214                
9215                if (launchSettleBatch) {
9216                	GLO.Report.CreditCard.settleBatch();
9217                }
9218            })
9219            .error(function(jqXHR, textStatus, errorThrown) {
9220                GLO.UI.Form.resetProcessing();
9221                GLO.Popup.Error('Unable to lookup data at this time.  Please try again.');
9222                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
9223            });
9224    }
9225    
9226    _conRptCCB.addToBatch = function(checkbox) {
9227    	var tr = $(checkbox).closest('tr').addClass('add-to-batch');
9228    	var sptid = tr.attr('transaction_id');
9229    	var svcCount = UTIL.coalesceInt(tr.attr('service_count_nr'), 0);
9230    	var tip = UTIL.coalesceMoney(tr.find('.cc-tip').text().replace('$', ''));
9231    	
9232    	if (svcCount > 0 && tip === 0) {
9233    		new GLO.Popup.Confirm(SA.Resource.AddTipQuestion
9234    			, function() {
9235    				tr.find('.cc-date').find('a').click();
9236    			}
9237    			, function() { GLO.Report.CreditCardBatch.addToBatchConfirmed(sptid); });
9238    	} else {
9239    		_conRptCCB.addToBatchConfirmed(sptid);
9240    	}
9241    }
9242    
9243	_conRptCCB.addToBatchConfirmed = function(transactionId) {
9244    	var url = GLO.Link.WebsiteDomain + 'payment/AddToBatch?transaction_id=' + transactionId;
9245        var btnRefresh = $('#btnRefresh:visible');
9246        
9247        GLO.UI.Form.beginProcessing(btnRefresh);
9248        
9249        $.ajax({ type: "POST", url: url, "cache": false })
9250            .success(function(data, textStatus, jqXHR) {
9251                new GLO.Popup.Success(SA.Resource.AddedToBatch + '!');
9252                
9253                $('#report-batch .add-to-batch').css({ "background-color": "lightgreen" });
9254		        
9255                GLO.UI.Form.resetProcessing();
9256                btnRefresh.find('a').click();
9257            })
9258            .error(function(jqXHR, textStatus, errorThrown) {
9259                GLO.UI.Form.resetProcessing();
9260                GLO.Popup.Error('Unable to add to batch at this time.  Please try again.');
9261                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
9262            });
9263    }
9264    
9265	return _conRptCCB;
9266})();
9267
9268
9269GLO.Report.CreditCard2 = (function() {
9270	function _conRptCC2() { }
9271    
9272    _conRptCC2.init = function() {
9273    	//$('#header-icon-container').remove();
9274    	
9275    	var jhead = $('.report-search-header');
9276        var jmerchant = jhead.find('.Merchant_id');
9277        var jtbl = $('#cc-report.tablesorter, #cc-ticket-report.tablesorter');
9278    	var mid = GLO.Uri.query('mid');
9279        
9280    	UI.initTableSorter(jtbl);
9281        
9282        if (!UTIL.isEmpty(mid)) { jmerchant.val(mid); }
9283        jmerchant.attr('id', 'Merchant_id').change(GLO.Report.CreditCard2.changeMerchant);
9284        
9285        GLO.Report.Template.initDateRange(jhead, false);
9286        GLO.Report.setupFastClick();
9287        GLO.Report.enableFullPageCheck();
9288        _loadCCData();
9289        _conRptCC2.displayFilterArrows();
9290    }
9291    function _initDisplayAll() {
9292    	if (innerWidth > 640) {
9293    		$('#cc-search').find('.btnReportAll, .btnReportFit').remove();
9294    	}
9295    	
9296    	GLO.Report.enableFullPageCheck();
9297    }
9298	function _loadCCData() {
9299		var jtbl = $('#cc-report.tablesorter, #cc-ticket-report.tablesorter');
9300		
9301        UI.initTableSorter(jtbl);
9302        GLO.Report.CellSummary.initReport(jtbl);
9303        GLO.Report.initIcons(jtbl);
9304    }
9305    
9306    _conRptCC2.displayFilterArrows = function() {
9307    	var jfilter = $('#cc-date-range-filter');
9308    	var start = UTIL.fromSADate(jfilter.find('#report-start').val());
9309    	var end = UTIL.fromSADate(jfilter.find('#report-end').val());
9310    	var days = UTIL.dayDiff(start, end) + 1;
9311    	
9312    	if (days < 8) {
9313    		jfilter.addClass('display-arrows');
9314    	} else {
9315    		jfilter.removeClass('display-arrows');
9316    	}
9317    }
9318    _conRptCC2.movePrev = function(isBatch) {
9319        GLO.Report.Template.moveDates(-1);
9320        
9321        if (isBatch) {
9322        	GLO.Report.CreditCardBatch.refresh();
9323        } else {
9324        	_conRptCC2.search();
9325        }
9326    }
9327    _conRptCC2.moveNext = function(isBatch) {
9328        GLO.Report.Template.moveDates(1);
9329        
9330        if (isBatch) {
9331        	GLO.Report.CreditCardBatch.refresh();
9332        } else {
9333        	_conRptCC2.search();
9334        }
9335    }
9336    
9337    _conRptCC2.changeMerchant = function() {
9338    	var jhead = $('.report-search-header:visible');
9339    	var jbkg = jhead.find('#Booking');
9340    	var jstart = jhead.find('#report-start');
9341    	var jend = jhead.find('#report-end');
9342    	
9343    	if (jbkg.length > 0) {
9344    		if (!UTIL.isEmpty(jbkg.val())) {
9345    			_conRptCC2.search();
9346    		}
9347    	} else if (jstart.length > 0) {
9348    		if (!UTIL.isEmpty(jstart.val())) {
9349    			_conRptCC2.search();
9350    		}
9351    	}
9352    }
9353    
9354    _conRptCC2.search = function() {
9355    	var jrpt = $('#report-main');
9356    	var btnSearch = jrpt.find('#btnSearch');
9357    	var mid = jrpt.find('#Merchant_id').val();
9358    	var pageUrl, qstring = '', jd = {};
9359    	
9360    	var jbkg = jrpt.find('#booking:visible');
9361    	var bkg = jbkg.val();
9362    	var start = jrpt.find('#report-start:visible').val();
9363    	var end = jrpt.find('#report-end:visible').val();
9364    	
9365    	if (!UTIL.isEmpty(mid)) {
9366    		var pageTitle = jrpt.find('#Merchant_id').find(':selected').text() + ' ' + SA.Resource.Report;
9367    	} else {
9368    		var pageTitle = SA.Resource.Report;
9369    	}
9370    	
9371    	if (!UTIL.isEmpty(mid)) { qstring += '&mid=' + mid; }
9372        
9373        if (!UTIL.isEmpty(bkg)) {
9374        	pageUrl = 'ReportTicket';
9375        	qstring += '&booking=' + bkg;
9376        } else if (UTIL.isEmpty(start) && UTIL.isEmpty(end) && jbkg.length) {
9377        	var fn = function() { jbkg.focus(); }
9378        	GLO.Popup.Warning.open('Please Enter Booking Number', 'Booking Number Empty', fn);
9379        	return;
9380        } else {
9381        	pageUrl = 'ReportDateRange';
9382        	qstring += '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true);
9383        }
9384        
9385        if (!GLO.Report.hasReportPassword(jd)) {
9386	    	return;
9387	    }
9388	    
9389	    GLO.UI.Form.beginProcessing(btnSearch);
9390        if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); }
9391        
9392        var url = GLO.Link.WebsiteDomain + 'payment/ReportLookupTransactions?' + qstring;
9393        var jRptData = jrpt.find('.report-container');
9394        
9395        $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd })
9396            .success(function(data, textStatus, jqXHR) {
9397                jRptData.html(data);
9398		        _loadCCData();
9399		        
9400                GLO.UI.Form.resetProcessing();
9401                pageUrl = GLO.Link.WebsiteDomain + 'payment/' + pageUrl + '?' + qstring;
9402                window.history.pushState("", pageTitle, pageUrl);
9403            })
9404            .error(function(jqXHR, textStatus, errorThrown) {
9405                GLO.UI.Form.resetProcessing();
9406                GLO.Popup.Error('Unable to lookup data at this time.  Please try again.');
9407                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
9408            });
9409    }
9410    
9411	return _conRptCC2;
9412})();
9413
9414
9415GLO.Report.PaymentSummary = (function() {		//Used by Payment Summary + Gift Card report
9416	function _conRptPaySum() { }
9417    
9418    _conRptPaySum.init = function() {
9419    	_loadPaySummaryData();
9420    	
9421        var jhead = $('.report-search-header');
9422        GLO.Report.Template.initDateRange(jhead, true);
9423        
9424        _setDateMin(jhead, "#report-start", "Jan 1, 2015");
9425        _setDateMin(jhead, "#report-end", "Jan 1, 2015");
9426        //$('#header-icon-container').remove();
9427        
9428        GLO.Report.setupFastClick();
9429        GLO.Report.enableFullPageCheck();
9430        
9431        $('#doc3').addClass('is-payment-report');
9432    }
9433    
9434    function _setDateMin(j, id, minDate) {
9435    	var jdt = j.find(id);
9436    	var val = jdt.val();
9437    	
9438    	jdt.datepicker("option", "minDate", minDate);
9439    	jdt.val(val);
9440    }
9441    
9442    _conRptPaySum.viewGiftCardUseOtherLocation = function(element, event) {
9443    	var tr = $('.gift-history').find('td.cell-summary-selected').closest('tr');
9444    	var minOtherPid = tr.attr('min_other_provider_id'), maxOtherPid = tr.attr('max_other_provider_id');
9445		
9446		GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
9447		
9448		if (!UTIL.isEmpty(minOtherPid)) {
9449			var urlGoTo = GLO.Link.WebsiteDomain + 'reports/saleshistory?isfullpage=1&paymethod=20&giftcard=' + tr.attr('gift_card_id');
9450			var gcnr = tr.find('.gift-column-number').text();
9451			
9452			var locationName = SA.Parent.getLocationName(minOtherPid);
9453			var locationColor = SA.Parent.getLocationColor(minOtherPid);
9454			
9455			if (minOtherPid == maxOtherPid) {
9456				//GLO.Popup.Processing.open('Loading Gift Card Payments at ' + locationName + '...', gcnr + ' Payments');
9457				GLO.Staff.Filter.switchLocation(minOtherPid, locationName, locationColor, urlGoTo);
9458			} else {
9459				var locationName2 = SA.Parent.getLocationName(maxOtherPid);
9460				var locationColor2 = SA.Parent.getLocationColor(maxOtherPid);
9461				
9462				var btn1 = '<p style="margin: 24px 4px; text-align: center;"><span id="btnGiftPay1" class="btnAdd"><a>View Payments at ' + locationName + '</a></span></p>';
9463				var btn2 = '<p style="margin: 24px 4px; text-align: center;"><span id="btnGiftPay2" class="btnAdd"><a>View Payments at ' + locationName2 + '</a></span></p>';
9464				var htm = '<div id="pop-view-payments-at-other-locations">' + btn1 + btn2 + '</div>';
9465				var jpop = GLO.Popup.Custom.openSimple(htm, 'Payments at Other Locations');
9466    			GLO.Popup.Custom.singleButton(jpop, 'Close');
9467				
9468				jpop.find('#btnGiftPay1 > a').click(function() {
9469					GLO.Staff.Filter.switchLocation(minOtherPid, locationName, locationColor, urlGoTo);
9470				});
9471				
9472				jpop.find('#btnGiftPay2 > a').click(function() {
9473					GLO.Staff.Filter.switchLocation(maxOtherPid, locationName2, locationColor2, urlGoTo);
9474				});
9475			}
9476		}
9477    }
9478    
9479    _conRptPaySum.changeGiftReportDate = function(element, event) {
9480    	$('#gift-option-date-range').prop('checked', true).change();
9481    }
9482    _conRptPaySum.changeGiftNumber = function(element, event) {
9483    	$('#gift-option-number').prop('checked', true).change();
9484    }
9485    _conRptPaySum.allGiftCardsWithBalance = function(element, event) {
9486    	$('.report-search-header #btnSearch > a').click();
9487    }
9488    _conRptPaySum.giftByClientName = function() {
9489    	$('#gift-option-client-name').prop('checked', true).change();
9490    	$('.report-search-header #Gift_Client_Name_vc').click();
9491    }
9492    
9493    _conRptPaySum.gotoReport = function(event, url) {
9494    	var j = $('.report-search-header:visible');
9495    	var start = UTIL.fromSADate(j.find('#report-start').val(), true, true);
9496        var end = UTIL.fromSADate(j.find('#report-end').val(), true, true);
9497    	
9498    	url = GLO.Uri.addQueryKeyAndValue(url, 'start=' + start + '&end=' + end);
9499    	GLO.Report.TicketHistory.gotoReport(event, url);
9500    }
9501    
9502    _conRptPaySum.goToReportTotal = function(event, url) {
9503    	var trs = $('#report-payment-summary').find('tbody > tr');
9504    	var sid, sids = '';
9505    	var houseSIDs = GLO.Staff.Filter.getHouseStaff();
9506    	
9507    	for (var i=0; i < trs.length; i++) {
9508    		sid = trs.eq(i).attr('staff_id');
9509    		
9510    		if (!UTIL.isEmpty(sid)) {
9511    			if (sids !== '') { sids += ','; }
9512    			sids += sid;
9513    		}
9514    	}
9515    	
9516    	if (!UTIL.isEmpty(houseSIDs)) {
9517    		if (sids !== '') { sids += ','; }
9518    		sids += ',' + houseSIDs;
9519    	}
9520    	
9521    	url += '&sfilter=' + sids;
9522    	GLO.Report.TicketHistory.gotoReport(event, url);
9523    }
9524    
9525    function _loadPaySummaryData() {
9526    	var jtbl = $('table#report-payment-summary.tablesorter');
9527        UI.initTableSorter(jtbl);
9528        
9529        GLO.Report.hideEmptyColumn(jtbl, 'ps-check-column');
9530        GLO.Report.hideEmptyColumn(jtbl, 'ps-gift-column');
9531        GLO.Report.hideEmptyColumn(jtbl, 'ps-loyalty-column');
9532        GLO.Report.hideEmptyColumn(jtbl, 'ps-other-column');
9533        
9534        GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-check-column');
9535        GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-gift-column');
9536        GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-loyalty-column');
9537        GLO.Report.hideEmptyColumn(jtbl, 'ps-tip-other-column');
9538        
9539        GLO.Report.hideEmptyColumn(jtbl, 'ps-incorrect-column');
9540        
9541    	GLO.Report.CellSummary.initReport(jtbl, true, true);
9542    }
9543    
9544    _conRptPaySum.openHelpDateRange = function() {
9545    	var hTicket = '<h3 style="color: rgb(40, 120, 240);">Ticket Date</h3>';
9546    	var bTicketDate = '<b class="narrow-text" style="color: rgb(40, 120, 240);">Ticket Date</b>';
9547    	var bPayDate = '<b class="narrow-text" style="color: rgba(20,200,20, 1)">Payment Date</b>';
9548    	
9549    	var msgTicket1 = '<p>' + bTicketDate + ' for service tickets is the service start date</p>';
9550    	var msgTicket2 = '<p>' + bTicketDate + ' for product tickets is the product purchase date</p>';
9551    	
9552    	var hPay = '<h3 style="color: rgba(20,200,20, 1)">Payment Date</h3>'
9553    	var msgPay1 = '<p>The ' + bPayDate + ' is the date/time the payment was made</p>';
9554    	
9555    	var divNote = '<div class="help-date-range-note">';
9556    	var payIncorrect = '<span class="narrow-text" style="display: inline;">(except the Incorrect Payment report which uses the checkout date / ticket date)</span>';
9557    	var noteTop = '<p style="text-align: center;">Filter payments by the ' + bTicketDate + ' or ' + bPayDate + '</p>';
9558    	
9559    	var rptPaySummary = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/PaymentSummary\')" style="font-weight: bold;">Payment Summary report</a>';
9560    	var rptPayDetail = '<a class="narrow-text" onclick="SA.Menu.gotoReport(event, this, \'reports/saleshistory?isfullpage=1&paymethod=0\')" style="font-weight: bold;">Payment Detail report</a>';
9561    	
9562    	var noteBottom = '<p style="margin-top: 32px">Payment reports filter by the ' + bPayDate + ' ' + payIncorrect + '</p>';
9563    	noteBottom += '<p>Most other reports filter by the ' + bTicketDate + '</p>';
9564    	noteBottom += '<p style="margin: 20px 0;">The ' + rptPaySummary + ' and ' + rptPayDetail + ' allow filtering by either ' + bTicketDate + ' or ' + bPayDate + '</p>';
9565    	noteBottom = '<div id="help-date-range-note-bottom">' + noteBottom + '</div>';
9566    	
9567    	var htm = '<div id="pop-help-date-range-info">' + divNote + noteTop + '</div>' + hTicket + msgTicket1 + msgTicket2 + hPay + msgPay1 + divNote + noteBottom + '</div> </div>';
9568    	var jpop = GLO.Popup.Info.open(htm, 'Filter Date Range').getPopup();
9569    	
9570    	jpop.find('.msg').css({ "padding-top": 0 });
9571    }
9572    _conRptPaySum.openHelpIncorrect = function() {
9573    	var jDateRange = $('#report-payment-summary-date-range');
9574    	var dateRange = '<b>' + jDateRange.find('#report-start').val() + ' - ' + jDateRange.find('#report-end').val() + '</b>';
9575    	var isPayDateRange = $('#report-payment-summary-select-range #Date_Range_Type_Pay_fl').prop('checked');
9576    	var ticketDateLabel = '<b class="narrow-text" style="color: rgb(40, 120, 240);">Ticket Date</b>';
9577    	
9578    	if (isPayDateRange) {
9579    		var dateLabel = '<b class="narrow-text" style="color: rgba(20,200,20, 1);">Payment Date</b>';
9580    	} else {
9581    		var dateLabel = ticketDateLabel;
9582    	}
9583    	
9584    	var rpt = '<b class="narrow-text">Payment Summary <span style="letter-spacing: 0; color: inherit;">report</span></b>';
9585    	var msg = '<p>The Incorrect payment amount on this ' + rpt + ' looks for past tickets with a ' + dateLabel + ' between ' + dateRange + ' and includes tickets with</p>';
9586    	
9587    	var listIncluded = '<ul> <li><b class="narrow-text">Incorrect payment amount:</b> the amount a ticket was over-paid or under-paid</li> </ul>';
9588    	var headerNot = '<h4 style="text-align: left; color: rgb(255,0,0);">Does Not Include</h4>';
9589    	var listNot = '<ul> <li><b class="narrow-text">Un-paid Ticket amount:</b> ticket has no payment</li> </ul>';
9590    	
9591    	var htm = '<div id="pop-help-incorrect-info">' + msg + listIncluded + headerNot + listNot + '</div>';
9592    	var jpop = GLO.Popup.Info.open(htm, 'Incorrect Payment').getPopup();
9593    }
9594    _conRptPaySum.openHelpTip = function() {
9595    	var msg = '<p>If there is more than one payment method on a ticket, the tip is taken from the payment methods on the ticket in this order:</p>';
9596    	
9597    	var li1 = '<li><b>Cash</b> <i>payment</i></li>';
9598    	var li2 = '<li><b>Credit</b> <i>payment</i></li>';
9599    	var li3 = '<li><b>Check</b> <i>payment</i></li>';
9600    	var li4 = '<li><b>Other</b> <i>payment method</i></li>';
9601    	var li5 = '<li><b>Gift Card</b> <i>payment</i></li>';
9602    	var li6 = '<li><b>Loyalty</b> <i>payment</i></li>';
9603		
9604		var list = '<ol>' + li1 + li2 + li3 + li4 + li5 + li6 + '</ol>';
9605		var ex1 = 'A ticket with a service price of $90 and tip of $10 with a $50 cash payment and $50 credit payment';
9606		var ex2 = 'the $10 tip with come from the cash payment, so will be a <b class="narrow-text">$10 cash tip</b>';
9607		var example = '<p class="example-help"><i>For example,</i> ' + ex1 + ' <b class="arrow-right">&#10140;</b> ' + ex2 + '</p>';
9608		
9609		var htm = '<div id="pop-help-tip-info">' + msg + list + example + '</div>';
9610    	var jpop = GLO.Popup.Info.open(htm, 'Tip Split Across Different Payment Methods on a Ticket').getPopup();
9611    }
9612    
9613    _conRptPaySum.changeFilterDateRangeType = function() {
9614    	if ($('#Date_Range_Type_Ticket_fl').prop('checked')) {
9615    		var filterDateRangeType = 'ticket-date';
9616    	} else if ($('#Date_Range_Type_Pay_fl').prop('checked')) {
9617    		var filterDateRangeType = 'pay-date';
9618    	} else {
9619    		var filterDateRangeType = null;
9620    	}
9621    	
9622    	UTIL.setCookie('Filter_Date_Range_Type_cd', filterDateRangeType);
9623    }
9624    
9625    _conRptPaySum.search = function() {
9626    	var jrpt = $('#report-main');
9627    	var btnSearch = jrpt.find('#btnSearch');
9628    	var jd = {};
9629    	
9630    	var start = jrpt.find('#report-start:visible').val();
9631    	var end = jrpt.find('#report-end:visible').val();
9632    	var isPayDate = jrpt.find('#Date_Range_Type_Pay_fl').prop('checked');
9633    	
9634    	var pageTitle = SA.Resource.PaymentSummary + ': ' + start + ' - ' + end;
9635    	var qstring = '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&ispaydate=' + isPayDate;
9636    	
9637    	GLO.UI.Form.beginProcessing(btnSearch);
9638        if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); }
9639        
9640        var url = GLO.Link.WebsiteDomain + 'report/PaymentSummary?' + qstring;
9641        var jRptData = jrpt.find('.report-container');
9642        
9643        if (!GLO.Report.hasReportPassword(jd)) {
9644	    	return;
9645	    }
9646	    
9647	    $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd })
9648            .success(function(data, textStatus, jqXHR) {
9649                jRptData.html(data);
9650		        _loadPaySummaryData();
9651		        
9652                GLO.UI.Form.resetProcessing();
9653                window.history.pushState("", pageTitle, url);
9654                
9655                if (GLO.Info.isMobile(true) || GLO.Mobile.isTablet) {
9656                	var jlinks = $('#report-payment-summary').find('a');
9657                	GLO.UI.initAnimateLink(jlinks, 4, GLO.UI.pinkify);
9658                }
9659                
9660                //_conRptPaySum.loadGiftCardReport();
9661            })
9662            .error(function(jqXHR, textStatus, errorThrown) {
9663                GLO.UI.Form.resetProcessing();
9664                GLO.Popup.Error('Unable to lookup data at this time.  Please try again.');
9665                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
9666            });
9667    }
9668    
9669    return _conRptPaySum;
9670})();
9671
9672
9673GLO.Report.Payroll = (function() {
9674	function _conRptPayroll() { }
9675    
9676    _conRptPayroll.initByDayPopup = function(staffId) {
9677    	var jpop = $('#report-payroll-days-all-data').closest('.glopop');
9678    	jpop.find('#report-payroll-today').addClass('hideX');
9679    	
9680    	var jpopStatus = jpop.find('#pop-payroll-day-status');
9681    	jpopStatus.find('h2').addClass('hideX');
9682    	jpop.find('#report-payroll-days-header').before(jpopStatus);
9683    	
9684    	var headerText = jpop.find('#report-payroll-days-staff-label').text() + ' <span class="narrow-text">Payroll Today</span>';
9685    	jpop.find('.pop-header > h1').html(headerText);
9686    	
9687    	_loadPayrollByDayData(jpop);
9688    	var width = 320;
9689    	
9690    	/* if (innerWidth >= 1100) {
9691    		width = 1100;
9692    	} else if (innerWidth >= 980) {
9693    		width = 980;
9694    	} else if (innerWidth >= 900) {
9695    		width = 900;
9696    	} else if (innerWidth >= 800) {
9697    		width = 800;
9698    	} else if (innerWidth >= 720) {
9699    		width = 700;
9700    	} else */ if (innerWidth >= 640) {
9701    		width = 600;
9702    	} else if (innerWidth >= 520) {
9703    		width = 500;
9704    	} else if (innerWidth >= 420) {
9705    		width = 400;
9706    	}
9707    	
9708    	jpop.width(width);
9709    	var label = 'Print Today\'s Staff Commission';
9710    	var sname = UserPortal.getStaffName(staffId);
9711    	
9712    	if (!UTIL.isEmpty(sname)) {
9713    		label = 'Print ' + label + ' Commission';
9714    	}
9715    	
9716    	var btnPrint = '<span id="btnPrintStaffCommission" class="btnAdd" title="' + label + '"><a onclick="SA.POS.printTodayCommissionToPrinter(this)">Print</a></span>';
9717    	var jbtns = jpop.find('.pop-buttons').css({ "width": "100%" });
9718    	jbtns.prepend(btnPrint);
9719    	return jpop;
9720    }
9721    _conRptPayroll.initByDay = function() {
9722    	GLO.Info.init();
9723    	GLO.Report.portalName = 'payroll-days';
9724    	GLO.Staff.Filter.isReportPortal = true;
9725    	
9726    	if (!GLO.Report.Sales.initStaffFilter()) {
9727			GLO.Report.Template.initStaffFilter(true);
9728		}
9729    	
9730		var jRptData = $('#report-main').find('.report-container');
9731		var jhead = $('.report-search-header');
9732        
9733		GLO.Report.Template.initDateRange(jhead, true, true);
9734        GLO.Report.initReportPassword(jRptData);
9735        
9736        var start = UTIL.fromSADate(jhead.find('#report-start').val(), true, true);
9737        var end = UTIL.fromSADate(jhead.find('#report-end').val(), true, true);
9738		
9739		_loadPayrollByDayData(jRptData, start, end);
9740    	_initPayrollUri();
9741    	
9742    	setTimeout(function() { UI.highlightStaffFilter(1200); }, 3200);
9743    }
9744    _conRptPayroll.init = function() {
9745    	GLO.Info.init();
9746    	GLO.Report.portalName = 'payroll';
9747    	
9748    	GLO.Staff.Filter.isReportPortal = true;
9749    	
9750    	if (!GLO.Report.Sales.initStaffFilter()) {
9751			GLO.Report.Template.initStaffFilter(true);
9752		}
9753    	
9754    	var jRptData = $('#report-payroll');
9755    	_loadPayrollData(jRptData);
9756    	
9757        var jhead = $('.report-search-header');
9758        GLO.Report.Template.initDateRange(jhead, true);
9759        GLO.Report.setupFastClick();
9760        GLO.Report.enableFullPageCheck();						//$('body').addClass('report-full-page');
9761        GLO.Report.initReportPassword(jRptData);
9762        
9763        GLO.Provider.Commission.initPayrollSchedule();
9764        _initPayrollUri();
9765        
9766        setTimeout(function() {
9767        	_initMissingValue();
9768        }, 1500);
9769    }
9770    function _initMissingValue() {
9771    	var payrollSchedule = $('#report-payroll-date-range').attr('value');
9772    	
9773    	if (UTIL.isEmpty(payrollSchedule) && $('.glopop .msg').length === 0 && $('#simplemodal-container').length === 0) {
9774    		GLO.Provider.Commission.openPayrollDateRange();
9775    	}
9776    }
9777    function _initPayrollUri() {
9778    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
9779    	var step = UTIL.cleanString(GLO.Uri.url('step')).toLowerCase();
9780    	var column = UTIL.cleanString(GLO.Uri.url('column')).toLowerCase();
9781    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
9782    	var staffId = UTIL.cleanString(GLO.Uri.url('staff'));
9783    	
9784    	if (open == 'print') {
9785    		GLO.Report.Payroll.openPrintReport();
9786    	} else if (open == 'help') {
9787    		GLO.Provider.Commission.openReportHelp(step);
9788    	} else if (open == 'export') {
9789    		GLO.Report.Payroll.exportReport();
9790    	} else if (open == 'automatic-commission') {
9791    		GLO.Provider.Commission.openReportHelp(22);
9792    	} else if (open == 'save') {
9793    		GLO.Report.Payroll.saveHistoryPopup();
9794    	} else if (open == 'history') {
9795    		GLO.Report.Payroll.viewHistoryPopup();
9796    	} else if (!UTIL.isEmpty(column)) {
9797			var jtbody = $('#report-payroll-summary-container tbody');
9798			
9799			if (!UTIL.isEmpty(staffId)) {
9800				var tr = jtbody.find('tr[staff_id="' + staffId + '"]');
9801			} else {
9802				var tr = jtbody.find('tr').eq(0);
9803			}
9804			
9805			var jcolumn = tr.find('td.' + column + '-column');
9806			
9807			if (jcolumn.length && !jcolumn.is(':visible') && !$('body').hasClass('report-full-page')) {
9808				GLO.Report.enableFullPage(true);
9809			}
9810			
9811			jcolumn.click();
9812			
9813			if (highlight == 'print') {
9814				var jhighlight = $('#pop-help-report-list');
9815				
9816				if (jhighlight.length > 0) {
9817	    			UI.highlight(jhighlight, 800, 6400, true);
9818	    		}
9819	    		
9820	    		return;
9821			}
9822		}
9823		
9824		if (!UTIL.isEmpty(highlight)) {
9825			var jrpt = $('#report-payroll');
9826			var jhigh = jrpt.find('#' + highlight);
9827			
9828			if (jhigh.length === 0) {
9829				jhigh = jrpt.find('.' + highlight);
9830			}
9831			
9832			if (jhigh.length && !jhigh.is(':visible') && !$('body').hasClass('report-full-page')) {
9833				GLO.Report.enableFullPage(true);
9834			}
9835			
9836			UI.highlight(jhigh, 800, 6400, true);
9837		}
9838    }
9839    function _initHideEmptyColumns() {
9840    	var j = $('#report-payroll-summary');
9841    	var tdPlusMin = j.find('td.plus-min-column');
9842    	
9843    	if (tdPlusMin.length > 0 && GLO.Report.Template.hideEmptyColumn(j, 'plus-min-column')) {
9844    		var td = j.find('tr#report-payroll-header2 .group-commission-dollar');
9845    		
9846    		if (td.length > 0) {
9847	    		var cols = parseInt(td.attr('colspan')) - 1;
9848	    		td.attr('colspan', cols);
9849    		}
9850    	}
9851    }
9852    function _historyReportHideEmptyColumns(j) {
9853    	GLO.Report.Template.hideEmptyColumn(j, 'product-percent-column');
9854    	GLO.Report.Template.hideEmptyColumn(j, 'product-percent-actual-column');
9855    	
9856    	GLO.Report.Template.hideEmptyColumn(j, 'hourly-rate-column');
9857    	GLO.Report.Template.hideEmptyColumn(j, 'paid-vacation-column');
9858    	GLO.Report.Template.hideEmptyColumn(j, 'paid-sick-column');
9859    	GLO.Report.Template.hideEmptyColumn(j, 'full-days-column');
9860    	
9861    	GLO.Report.Template.hideEmptyColumn(j, 'sale-product-column');
9862    	GLO.Report.Template.hideEmptyColumn(j, 'product-dollar-column');
9863    	GLO.Report.Template.hideEmptyColumn(j, 'plus-min-column');
9864    	
9865    	GLO.Report.Template.hideEmptyColumn(j, 'service-fee-column');
9866    	GLO.Report.Template.hideEmptyColumn(j, 'credit-fee-column');
9867    	GLO.Report.Template.hideEmptyColumn(j, 'supply-fee-column');
9868    	GLO.Report.Template.hideEmptyColumn(j, 'clean-fee-column');
9869    	
9870    	GLO.Report.Template.hideEmptyColumn(j, 'adjust-column');
9871    	GLO.Report.Template.hideEmptyColumn(j, 'adjust-note');
9872    	
9873    	GLO.Report.Template.hideEmptyColumn(j, 'hourly-wage-column');
9874    	GLO.Report.Template.hideEmptyColumn(j, 'overtime-column');
9875    	GLO.Report.Template.hideEmptyColumn(j, 'gift-card-column');
9876    	GLO.Report.Template.hideEmptyColumn(j, 'tip-column');
9877    	
9878    	GLO.Report.Template.hideEmptyColumn(j, 'early-column');
9879    	GLO.Report.Template.hideEmptyColumn(j, 'normal-column');
9880    	GLO.Report.Template.hideEmptyColumn(j, 'profit-column');
9881    }
9882    
9883    _conRptPayroll.openFirstIncompleteTicket = function() {
9884    	var smid = $('#report-payroll-days').find('tr.has-incomplete-tickets').attr('first_incomplete_smid');
9885    	var jsonPostOpen = { "processing_message_vc": "Retrieving first incomplete ticket..." };
9886    	
9887		UserPortal.Edit.get(null, smid, true, false, false, jsonPostOpen);
9888    }
9889    _conRptPayroll.openIncompleteTicket1 = function() {
9890    	var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr');
9891    	var smid = tr.attr('first_incomplete_smid');
9892    	_openIncompleteTicket(tr, smid);
9893    }
9894    _conRptPayroll.openIncompleteTicket2 = function() {
9895    	var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr');
9896    	var smid = tr.attr('last_incomplete_smid');
9897    	_openIncompleteTicket(tr, smid);
9898    }
9899    function _openIncompleteTicket(tr, smid) {
9900    	UserPortal.Edit.get(null, smid, true);
9901    }
9902    
9903    _conRptPayroll.moveDateRange = function(up) {
9904    	var jhead = $('.report-search-header');
9905    	var jstart = jhead.find('.Begin_dt'), jend = jhead.find('.End_dt');
9906    	
9907    	var dt1 = new Date(UTIL.fromSADate(jstart.val(), true, true));
9908    	var dt2 = new Date(UTIL.fromSADate(jend.val(), true, true));
9909    	var oneDay = 24*60*60*1000; 						//hours * minutes * seconds * milliseconds.
9910    	
9911    	if (GLO.Report.Template.isMonthRange(dt1, dt2)) {
9912        	var monthCount = up * (dt2.getMonth() - dt1.getMonth() + (12 * (dt2.getFullYear() - dt1.getFullYear())) + 1);
9913        	dt1 = new Date(dt1.setMonth(dt1.getMonth() + monthCount));
9914        	dt2 = GLO.Report.Template.addMonthsToEndDate(dt2, monthCount);
9915        } else if (_isBiWeeklyDateRange(dt1, dt2)) {
9916        	if (up > 0) {
9917	        	if (dt1.getDate() == 1) {
9918	        		dt1 = new Date(dt1.getFullYear(), dt1.getMonth(), 16);
9919	        		dt2 = new Date(dt2.getFullYear(), dt2.getMonth() + 1, 0);
9920	        	} else if (dt1.getDate() == 16) {
9921	        		dt1 = new Date(dt1.getFullYear(), dt1.getMonth() + 1, 1);
9922	        		dt2 = new Date(dt2.getFullYear(), dt2.getMonth() + 1, 15);
9923	        	}
9924	        } else {
9925	        	if (dt1.getDate() == 1) {
9926	        		dt2 = new Date(dt1).addDays(-1);
9927	        		dt1 = new Date(dt1.getFullYear(), dt1.getMonth() - 1, 16);
9928	        	} else if (dt1.getDate() == 16) {
9929	        		dt1 = new Date(dt1.getFullYear(), dt1.getMonth(), 1);
9930	        		dt2 = new Date(dt2.getFullYear(), dt2.getMonth(), 15);
9931	        	}
9932	        }
9933        } else {			//= advance 
9934            var moveBy = Math.round(Math.abs((dt2.getTime() - dt1.getTime())/(oneDay))) + 1;
9935    		
9936    		dt1.setDate(dt1.getDate() + (moveBy * up));
9937		    dt2.setDate(dt2.getDate() + (moveBy * up));
9938    	}
9939    	
9940    	jstart.val(dt1.toGloDate());
9941    	jend.val(dt2.toGloDate());
9942    	
9943    	_conRptPayroll.search();
9944    }
9945    function _isBiWeeklyDateRange(start, end) {
9946    	var payrollSchedule = $('#report-payroll-date-range').attr('value');
9947    	
9948    	if (payrollSchedule == 10) {
9949    		if (start.getMonthDiff(end) === 0) {
9950    			if ( (start.getDate() == 1 && end.getDate() == 15) || (start.getDate() == 16 && end.getDate() == new Date(end.getFullYear(), end.getMonth() + 1, 0).getDate()) ) {
9951    				return true;
9952    			}
9953    		}
9954    	}
9955    	
9956    	return false;
9957    }
9958    function _isAllowPayrollSearch(jd, btnSearch) {
9959    	var fnReload = function() {
9960    			location.reload();
9961    		};
9962    	
9963    	if ($('#payroll-report-date-period .btnPayrollPeriods').find('.btnAdd.selected').hasClass('btnProcessing4')) {
9964    		GLO.Popup.Processing.open('Re-loading page to complete this request', 'Processing Multiple Request');
9965    		setTimeout(fnReload, 1500);
9966    		return false;
9967    	} else if (btnSearch.hasClass('btnProcessing4')) {
9968    		GLO.Popup.Processing.open('Re-loading page to complete this request', 'Processing Report Request');
9969    		setTimeout(fnReload, 1500);
9970    		return false;
9971    	} else if (!GLO.Report.hasReportPassword(jd, true)) {
9972        	return false;
9973        }
9974        
9975        return true;
9976    }
9977    _conRptPayroll.search = function(isPrint) {
9978    	var jd = {}, jrpt = $('#report-main');
9979    	var btnSearch = jrpt.find('#btnSearch');
9980    	
9981    	if (!_isAllowPayrollSearch(jd, btnSearch)) { return; }
9982        
9983        var start = jrpt.find('#report-start:visible').val();
9984    	var end = jrpt.find('#report-end:visible').val();
9985    	var pageTitle = SA.Resource.PayrollReport + ': ' + start + ' - ' + end;
9986    	var qstring = '&start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&sfilter=' + GLO.Uri.query('sfilter');
9987    	
9988    	if (jrpt.find('.block-container #report-payroll-summary').length > 0) {
9989        	var msg = '<div> <h1 class="friendly-msg3">Upgrade Required</h1> <div class="friendly-msg3">Please upgrade to the Silver or Gold Package to use the Payroll Report</div> </div>';
9990        	new GLO.Popup.Info(msg);
9991        	return;
9992        }
9993        
9994        GLO.UI.Form.beginProcessing(btnSearch);
9995        if (qstring.substring(0,1) === '&') { qstring = qstring.substring(1); }
9996        
9997        var jRptData = jrpt.find('.report-container');
9998        var url = GLO.Link.WebsiteDomain + 'report/payroll?' + qstring;
9999        
10000        if (GLO.Report.portalName == 'payroll-days') {
10001        	url = GLO.Link.WebsiteDomain + 'report/payrollDays?' + qstring + '&period=' + UTIL.cleanString(jrpt.find('.btnMultiChild .btnAdd.selected').parent().attr('value'));
10002        }
10003        
10004        $.ajax({ type: "POST", url: url, "cache": false, "data": jd })
10005            .success(function(data, textStatus, jqXHR) {
10006                jRptData.html(data);
10007                
10008                if (GLO.Report.portalName == 'payroll-days') {
10009                	_loadPayrollByDayData(jRptData, start, end);
10010                	var warningHtm = UTIL.cleanString($('#report-header-warning').remove().html());
10011                	
10012                	$('#daily-payroll-report-header-help').html(warningHtm);
10013                	//$('#report-header-warning').remove();
10014                } else {
10015		        	_loadPayrollData(jRptData, start, end);
10016		        }
10017		        
10018		        GLO.UI.Form.resetProcessing();
10019                window.history.pushState("", pageTitle, url);
10020                
10021                if (isPrint) {
10022                	$('#btnPrintPayrollByDay').find('>a').click();
10023                }
10024            })
10025            .error(function(jqXHR, textStatus, errorThrown) {
10026                GLO.UI.Form.resetProcessing();
10027                GLO.Popup.Error('Unable to lookup data at this time.  Please try again.');
10028                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
10029            });
10030    }
10031    
10032    function _getHistorySettings(tr) {
10033    	var servicePct = UTIL.coalesceMoney(tr.find('.expected-percent-column').text().replace('%', ''));
10034    	var serviceEarlyPct = UTIL.coalesceMoney(tr.attr('service_commission_early_pct'));
10035		var productPct = UTIL.coalesceMoney(tr.find('.expected-percent-column').text().replace('%', ''));
10036		var hourlyWage = UTIL.coalesceMoney(tr.find('.hourly-rate-column').text().replace('$', ''));
10037		
10038		var minWeek = UTIL.coalesceMoney(tr.attr('minWeek'));
10039		var minDay = UTIL.coalesceMoney(tr.attr('minDay'));
10040		var minHr = UTIL.coalesceMoney(tr.attr('minHour'));
10041		
10042		var minDayHours = UTIL.coalesceMoney(tr.attr('minDayHours'));
10043		var minDayHalfHours = UTIL.coalesceMoney(tr.attr('minDayHalfHours'));
10044		var minWeekDays = UTIL.coalesceMoney(tr.attr('minWeekDays'));
10045		var minIncludesTip = UTIL.coalesceMoney(tr.attr('minIncludeTip'));
10046		
10047		var minAndFeeStart = UTIL.cleanString(tr.attr('minAndFeeStart'));
10048		var minOvertimePerHr = UTIL.coalesceMoney(tr.attr('minOvertimePerHour'));
10049		var overtimePerHr = UTIL.coalesceMoney(tr.attr('overtimePerHour'));
10050		
10051		return { "ServiceCommission": servicePct, "ServiceCommissionEarlyPercent": serviceEarlyPct, "ProductCommission": productPct, "HourlyRate": hourlyWage
10052			, "MinHour": minHr, "MinDay": minDay, "MinWeek": minWeek
10053			, "MinHoursPerDay": minDayHours, "MinHoursPerHalfDay": minDayHalfHours, "MinDaysPerWeek": minWeekDays, "MinIncludesTip": minIncludesTip
10054			, "MinAndFeeStart": minAndFeeStart, "MinOvertimePerHr": minOvertimePerHr, "OvertimePerHr": overtimePerHr };
10055    }
10056    function _getHistoryTotals(tr) {
10057    	var sid = tr.attr('staff_id');
10058		var hrs = UTIL.coalesceMoney(tr.find('.hours-worked-column').text());
10059		var days = UTIL.coalesceMoney(tr.find('.actual-days-column').text());
10060		var fullDays = UTIL.coalesceMoney(tr.find('.full-days-column').text());
10061		var serviceDays = UTIL.coalesceMoney(tr.attr('days_worked_service_sr'));
10062		
10063		var total = UTIL.coalesceMoney(tr.find('.total-column').text().replace('$', ''));			//profit-column
10064		var timesheet = UTIL.coalesceMoney(tr.find('.hourly-wage-column').text().replace('$', ''));
10065		var overtime = UTIL.coalesceMoney(tr.find('.overtime-column').text().replace('$', ''));
10066		var servicePayment = UTIL.coalesceMoney(tr.find('.sale-service-payment-column').text().replace('$', ''));
10067		var profit = UTIL.coalesceMoney(tr.find('.profit-column > span').text().replace('$', ''));
10068		
10069		var actualHourlyRate = UTIL.coalesceMoney(tr.find('.actual-hourly-rate-column').text().replace('$', ''));
10070		var actualServicePct = UTIL.coalesceMoney(tr.find('.service-percent-actual-column').text().replace('%', ''));
10071		var actualProductPct = UTIL.coalesceMoney(tr.find('.product-percent-actual-column').text().replace('%', ''));
10072		
10073		var productCommission = UTIL.coalesceMoney(tr.find('.product-dollar-column').text().replace('$', ''));
10074		var serviceCommission = UTIL.coalesceMoney(tr.find('.service-dollar-column').text().replace('$', ''));
10075		var early = UTIL.coalesceMoney(tr.find('.early-column').text().replace('$', ''));
10076		var normal = UTIL.coalesceMoney(tr.attr('normal_commission_mn'));							//tr.find('.normal-column').text().replace('$', '')
10077		
10078		var tipCommission = UTIL.coalesceMoney(tr.find('.tip-column').text().replace('$', ''));
10079		var paymentTip = UTIL.coalesceMoney(tr.attr('payment_tip_mn'));
10080		var paymentTipCredit = UTIL.coalesceMoney(tr.attr('payment_tip_credit_mn'));
10081		
10082		var serviceSales = UTIL.coalesceMoney(tr.find('.sale-service-column').text().replace('$', ''));
10083		var productSales = UTIL.coalesceMoney(tr.find('.sale-product-column').text().replace('$', ''));
10084		var tipTotal = UTIL.coalesceMoney(tr.attr('tip_mn'));
10085		
10086		var vacation = UTIL.coalesceMoney(tr.find('.paid-vacation-column').text().replace('$', ''));
10087		var sick = UTIL.coalesceMoney(tr.find('.paid-sick-column').text().replace('$', ''));
10088		var plusMin = UTIL.coalesceMoney(tr.find('.plus-min-column').text().replace('$', ''));
10089		var adjustment = UTIL.coalesceMoney(tr.find('.adjust-input').val());
10090		
10091		var serviceFee = Math.abs(UTIL.coalesceMoney(tr.find('.service-fee-column > span').text().replace('$', '')));
10092		var ccFee = UTIL.coalesceMoney(tr.find('.credit-fee-column').text().replace('$', ''));
10093		
10094		var supplyFee = UTIL.coalesceMoney(tr.find('.supply-fee-column span').text().replace('-$', ''));	//UTIL.coalesceMoney(days * UTIL.coalesceMoney(tr.attr('day_supply_fee_mn')));
10095		var cleanFee = UTIL.coalesceMoney(tr.find('.clean-fee-column span').text().replace('-$', ''));		//UTIL.coalesceMoney(days * UTIL.coalesceMoney(tr.attr('day_clean_fee_mn')));
10096		
10097		var withheld = UTIL.coalesceMoney(tr.attr('total_withheld_mn'));			//federal_tax_mn, wage_after_tax_mn
10098		var socialSecurity = UTIL.coalesceMoney(tr.attr('social_security_mn'));
10099		var medicare = UTIL.coalesceMoney(tr.attr('medicare_mn'));
10100		var employmentInsurance = UTIL.coalesceMoney(tr.attr('employment_insurance_mn'));
10101		var note = UTIL.htmlEncode(tr.find('.payroll-adjust-note > a').text());
10102		
10103		return { "StaffId": sid, "HoursWorked": hrs, "DaysWorked": days, "FullDaysWorked": fullDays, "DaysWorkedService": serviceDays
10104				, "ActualHourlyRate": actualHourlyRate, "ActualServiceCommissionPercent": actualServicePct, "ActualProductCommissionPercent": actualProductPct
10105				, "TotalWage": total, "Timesheet": timesheet, "Overtime": overtime, "ServicePayment": servicePayment, "Profit": profit
10106				, "ProductCommission": productCommission, "ServiceCommission": serviceCommission, "ServiceCommissionEarly": early, "ServiceCommissionNormal": normal
10107				, "TipCommission": tipCommission, "PaymentTip": paymentTip, "PaymentTipCredit": paymentTipCredit
10108				
10109				, "Vacation": vacation, "Sick": sick, "MinAdded": plusMin, "Adjustment": adjustment
10110				, "ServiceSales": serviceSales, "ProductSales": productSales, "TipTotal": tipTotal
10111				, "ServiceFee": serviceFee, "CreditCardFee": ccFee, "SupplyFee": supplyFee, "CleaningFee": cleanFee
10112				, "Withheld": withheld, "SocialSecurity": socialSecurity, "Medicare": medicare, "EmploymentInsurance": employmentInsurance, "Note": note };
10113    }
10114    function _createSaveHistoryJson() {
10115    	var trs = $('#report-payroll-summary').find('tbody > tr');
10116    	var jsonStaffList = [];
10117    	
10118    	for (var i=0; i < trs.length; i++) {
10119    		//if (i > 0) { jsonStaffList += ', '; }
10120    		
10121    		var tr = trs.eq(i);
10122    		var jsonStaff = _getHistoryTotals(tr);
10123    		var settings = _getHistorySettings(tr);
10124    		
10125    		jsonStaff.Settings = settings;
10126    		jsonStaffList.push(jsonStaff);
10127    	}
10128    	return { "StaffList": jsonStaffList };
10129    }
10130    _conRptPayroll.saveHistory = function(isOverride) {
10131    	var jpayroll = $('#report-payroll-summary');
10132    	var start = jpayroll.attr('start_d');
10133    	var end = jpayroll.attr('end_d');
10134    	
10135    	var jsonStaffList = { "payrollPeriod": _createSaveHistoryJson() };						//_getIOSBookingResult(jd);
10136    	var url = GLO.Link.WebsiteDomain + 'report/PayrollPeriodInsert?start=' + start + '&end=' + end;
10137		
10138		if (isOverride) {
10139			url += '&override=1';
10140		}
10141		
10142		GLO.UI.Form.beginProcessing($('.btnSavePayrollHistory'));
10143		
10144		$.ajax({ type: "POST", url: url, "cache": false, data: jsonStaffList })
10145	        .success(function(data, textStatus, jqXHR) {
10146	            var jdata = $(data);
10147	            GLO.UI.Form.resetProcessing();
10148	            
10149	            if (jdata.hasClass('success')) {
10150	            	GLO.Popup.closeIfExist($('#pop-payroll-history-duplicates').closest('.glopop'));
10151	            	GLO.Popup.Success.open(data, 'Payroll History Saved!', 69000);
10152	            } else {
10153	            	_displayDuplicateWarning(data);
10154	            }
10155	        })
10156	        .error(function(jqXHR, textStatus, errorThrown) {
10157                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
10158            });
10159    }
10160    function _displayDuplicateWarning(data) {
10161    	var ojpop = GLO.Popup.Warning.open(data, 'Save Payroll History Failed');
10162    	var jpop = ojpop.getPopup();
10163    	var tblDup = jpop.find('#payroll-history-duplicate-table');
10164    	
10165    	jpop.find('.msg').css({ "padding": "0" });
10166    	UI.initTableSorter(tblDup);
10167    	GLO.Popup.Custom.singleButton(jpop, 'Close');
10168    	
10169    	var btnSave = '<span class="btnSave btnSavePayrollHistory" style="margin-left: 200px; font-size: 18px;"><a onclick="GLO.Report.Payroll.saveHistory(true)">Override + Save</a></span>';
10170    	jpop.find('.btnSA').after(btnSave);
10171    	
10172    	if (!GLO.Info.isMobile() && jpop.height() + 50 >
10172 innerHeight) {
10173    		var topHeight = jpop.find('#payroll-history-warning').height() + jpop.find('.pop-header').height();
10174    		var bottomHeight = jpop.find('.pop-buttons-parent').height();
10175    		var tableHeight = parseInt(innerHeight - topHeight - bottomHeight - 100) + 'px';
10176    		
10177    		jpop.find('#payroll-history-duplicate-data').css({ "max-height": tableHeight, "overflow-y": "auto" });
10178    	}
10179    	
10180    	ojpop.realign();
10181    }
10182    _conRptPayroll.saveHistoryPopup = function(isViewOnly, message) {
10183    	var jrpt = $('#report-payroll-summary');
10184    	var start = jrpt.attr('start_d'), end = jrpt.attr('end_d');
10185    	
10186    	var helpIcon = '<b class="question-icon" onclick="GLO.Report.Payroll.openHelpHistory(this)" style="margin-left: 4px;">?</b>';
10187    	var cssSmaller = 'letter-spacing: 0; line-height: 1.4; font-size: 93%; font-family: arial; font-stretch: condensed;';
10188    	var htmHelp = '<p style="' + cssSmaller + '">When you do payroll, we recommend saving your payroll information in the payroll history ' + helpIcon + '</p>';
10189    	var msg = '<p style="padding-bottom: 24px; ' + cssSmaller + '">' + UTIL.cleanString(message) + '</p>';
10190    	
10191    	if (UTIL.parseBool(isViewOnly)) {
10192    		return '<div id="info-save-payroll-history">' + htmHelp + msg + '</div>';
10193    	}
10194    	
10195    	var htmWarn = _getSaveHistoryWarning(jrpt, start, end);
10196    	var h1 = 'Save Payroll Period: ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true);
10197    	
10198    	var labelSave = '<b>Save payroll for ' + jrpt.find('tbody > tr').length + ' staff ?</b>';
10199    	var btnSave = '<span class="btnSave btnSavePayrollHistory"><a onclick="GLO.Report.Payroll.saveHistory()">Save</a></span>';
10200    	var htmSave = '<div id="pop-save-payroll-history-summary">' + labelSave + btnSave + '</div>';
10201    	
10202    	var about = '<p style="margin-top: 40px; text-align: center;"><a onclick="GLO.Provider.Commission.openReportHelp(21)">About Payroll History</a></p>';
10203    	var htm = '<div id="pop-save-payroll-history">' + htmWarn + htmSave + about + htmHelp + msg + '</div>';
10204    	var jpop = GLO.Popup.Custom.openSimple(htm, h1);
10205    	GLO.Popup.Custom.singleButton(jpop, 'Close');
10206    }
10207    function _getSaveHistoryWarning(jrpt, start, end) {
10208    	var sfilter = GLO.Uri.url('sfilter');
10209    	var jStaffLabel = $('#staffFilter .hello-bar-label > span');	//.html();
10210    	var htmWarn = _verifyIsSameDateRange(start, end);
10211    	
10212    	if (!UTIL.isEmpty(sfilter) || jStaffLabel.length > 0) {
10213    		htmWarn += '<p class="warning-emphasis" style="text-align: center;">Staff filter limiting current payroll report to ' + jrpt.find('tbody > tr').length + ' staff</p>';
10214    	}
10215    	
10216    	return htmWarn;
10217    }
10218    function _verifyIsSameDateRange(start, end) {
10219    	var dtStart = new Date(start), dtEnd = new Date(end);
10220    	var dayDiff = UTIL.dayDiff(dtStart, dtEnd) + 1;
10221    	var payrollSchedule = $('#report-payroll-date-range').attr('value');		//.attr('last_period_end_dt')
10222    	var p1 = '<p class="warning-emphasis">';
10223    	var dateRange = '<b class="narrow-text">' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true) + '</b>';
10224    	var warnMsg = '<i>Current Date Range</i> ' + dateRange + ' <i>does not match your normal payroll schedule</i> <b class="narrow-text">';
10225    	
10226    	if (UTIL.isEmpty(payrollSchedule)) {
10227    		var btnPaySchedule = '<span id="btnPayrollDateRangePop" class="btnAdd"><a onclick="GLO.Provider.Commission.openPayrollDateRange()">Payroll Schedule</a></span>';
10228    		return p1 + 'Before saving, please press ' + btnPaySchedule + ' button to set your normal payroll schedule</p>';
10229    	} else if (payrollSchedule == 10) {		//= 2/mo
10230    		if (dtStart.getMonthDiff(dtEnd) != 0 
10231    				&& !( (dtStart.getDate() == 1 && dtEnd.getDate() == 15) || !(dtStart.getDate() == 16 && dtEnd.getDate() == new Date(dtEnd.getFullYear(), dtEnd.getMonth() + 1, 0).getDate()) )) {
10232    			return p1 + warnMsg + ' twice a month</b> </p>';
10233    		}
10234    	} else if (payrollSchedule == 20) {
10235    		if (dtStart.getMonthDiff(dtEnd) != 0 || !(dtStart.getDate() == 1 && dtEnd.getDate() == new Date(dtEnd.getFullYear(), dtEnd.getMonth() + 1, 0).getDate())) {
10236    			return p1 + warnMsg + ' once a month</b> </p>';
10237    		}
10238    	} else if (payrollSchedule > 29 && payrollSchedule < 40) {
10239    		if (dayDiff != 14) {
10240    			return p1 + warnMsg + ' every 2 weeks</b> </p>';
10241    		} else if (payrollSchedule % 10 != dtStart.getDay() + 1) {
10242    			return p1 + warnMsg + ' starting on ' + UTIL.getWeekDayName(payrollSchedule % 10 - 1) + '</b> </p>';
10243    		}
10244    	} else if (payrollSchedule > 39 && payrollSchedule < 50) {
10245    		if (dayDiff != 7) {
10246    			return p1 + warnMsg + ' once a week</b> </p>';
10247    		} else if (payrollSchedule % 10 != dtStart.getDay() + 1) {
10248    			return p1 + warnMsg + ' starting on ' + UTIL.getWeekDayName(payrollSchedule % 10 - 1) + '</b> </p>';
10249    		}
10250    	}
10251    	
10252    	return '';
10253    }
10254    
10255    _conRptPayroll.viewHistoryPopup = function() {
10256    	var url = GLO.Link.WebsiteDomain + 'report/PayrollHistorySummary?sfilter=' + UTIL.cleanString(GLO.Uri.url('sfilter'));
10257		GLO.UI.Form.beginProcessing($('#btnViewPayrollHistory'));
10258		
10259		$.ajax({ type: "GET", url: url, "cache": false })
10260	        .success(function(data, textStatus, jqXHR) {
10261	            var jdata = $(data);
10262	            GLO.UI.Form.resetProcessing();
10263	            
10264	            var ojpop = GLO.Popup.Custom.open(data, 'Payroll History Summary');
10265		    	var jpop = ojpop.getPopup().addClass('no-persist').css({ "padding-bottom": "0" });
10266		    	var tbl = jpop.find('#payroll-history-summary-table');
10267		    	
10268		    	var msg = 'Press any period below for Payroll Period History';
10269		    	var htmHelp = _conRptPayroll.saveHistoryPopup(true, msg);
10270		    	tbl.before(htmHelp);
10271		    	
10272		    	var cssAbout = 'position: absolute; left: 0; bottom: 0; padding: 8px 8px 6px; border-bottom-left-radius: 6px; border-top-left-radius: 0; border-bottom-right-radius: 0;';
10273		    	var lblAbout = 'About <i>Payroll History</i>';
10274		    	var btnAbout = '<span class="btnAboutPayrollHistory btnAdd"><a onclick="GLO.Provider.Commission.openReportHelp(21)" style="' + cssAbout + '">' + lblAbout + '</a></span>';
10275		    	jpop.find('.pop-buttons').append(btnAbout);
10276		    	
10277		    	jpop.find('.msg').css({ "padding": "0" });
10278		    	UI.initTableSorter(tbl);
10279		    	GLO.Popup.Custom.singleButton(jpop, 'Close');
10280		    	
10281		    	if (!GLO.Info.isMobile() && jpop.height() + 50 >
10281 innerHeight) {
10282		    		var topHeight = jpop.find('.pop-header').height();
10283		    		var bottomHeight = jpop.find('.pop-buttons-parent').height();
10284		    		var tableHeight = parseInt(innerHeight - topHeight - bottomHeight - 100) + 'px';
10285		    		
10286		    		jpop.find('#payroll-history-summary-data').css({ "max-height": tableHeight, "overflow-y": "auto" });
10287		    	}
10288		    	
10289		    	ojpop.realign();
10290	        })
10291	        .error(function(jqXHR, textStatus, errorThrown) {
10292                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
10293            });
10294    }
10295    _conRptPayroll.viewHistoryPeriod = function(tr) {
10296    	var jtr = $(tr);
10297    	var start = jtr.attr('start_d'), end = jtr.attr('end_d'), sfilter = UTIL.cleanString(GLO.Uri.url('sfilter'));
10298    	
10299    	_conRptPayroll.viewHistoryPeriod2(sfilter, start, end, false);
10300    }
10301    _conRptPayroll.viewHistoryPeriod2 = function(sfilter, start, end, isExport) {
10302    	var url = GLO.Link.WebsiteDomain + 'report/PayrollHistory?sfilter=' + sfilter + '&start=' + start + '&end=' + end;
10303    	var header = 'Payroll History: ' + start + ' - ' + end;
10304    	
10305    	if (isExport) {
10306    		url += '&export=1';
10307    		
10308    		var btnExport = $('#pop-view-payroll-history-period').closest('.glopop').find('#btnExportHistory');
10309        	GLO.UI.Form.beginProcessing(btnExport);
10310        	
10311        	window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 4500);
10312        	
10313        	var childWindow = UI.openChildWindow(url, '', true);
10314        	return;
10315    	}
10316    	
10317    	GLO.Popup.closeIfExist($('#pop-payroll-history-summary').closest('.glopop'));
10318    	var ojprocessing = GLO.Popup.Processing.open('Loading Payroll History for the Period: ' + start + ' - ' + end + '...', header);
10319		//GLO.UI.Form.beginProcessing($('#btnViewPayrollHistory'));
10320		
10321		$.ajax({ type: "GET", url: url, "cache": false })
10322	        .success(function(data, textStatus, jqXHR) {
10323	            ojprocessing.close();
10324	            var msg = '';
10325	            
10326	            if ($('#report-main #payroll-history-diff-warning').length) {
10327	            	var link = '<a onclick="GLO.Report.Template2.goToReport(\'Payroll Report\', \'reports/payroll\')">Payroll Report</a>';
10328	            	var btnSavePayroll = '<span class="btnSave"><a>Save</a></span>';
10329	            	var warnStyle = ' style="margin-bottom: 20px; padding: 8px; text-align: center;"';
10330	            	
10331	            	msg = '<p' + warnStyle + '>To re-save payroll go to the ' + link + ' and press the ' + btnSavePayroll + ' button</p>';
10332	            }
10333	            
10334	            var htm = '<div id="pop-view-payroll-history-period">' + msg + data + '</div>';
10335	            var ojpop = GLO.Popup.Custom.open(htm, header);
10336		    	var jpop = ojpop.getPopup().addClass('no-persist');
10337		    	var tbl = jpop.find('#report-payroll-history-detail');
10338		    	
10339		    	GLO.Popup.Custom.singleButton(jpop, 'Close');
10340		    	jpop.find('.msg').css({ "padding": "0" });
10341		    	UI.initTableSorter(tbl);
10342		    	
10343		    	_historyReportHideEmptyColumns(tbl);
10344		    	
10345		    	if (!GLO.Info.isMobile()) {
10346		    		var fnExport = 'GLO.Report.Payroll.viewHistoryPeriod2(\'' + sfilter + '\', \'' + start + '\', \'' + end + '\', true)';
10347		    		var cssExport1 = 'position: absolute; right: 0; bottom: 0;';
10348		    		var cssExport2 = 'display: inline-block; padding: 6px 8px 4px; letter-spacing: 1px; font-size: 18px; border-radius: 10px; border-bottom-left-radius: 0; border-top-right-radius: 0;';
10349		    		var btnExport = '<span id="btnExportHistory" class="btnAdd" style="' + cssExport1 + '"><a onclick="' + fnExport + '" style="' + cssExport2 + '">Export</a></span>';
10350		    		
10351		    		jpop.find('.pop-buttons-parent').css({ "position": "relative" }).append(btnExport);
10352		    		jpop.css({ "max-width": (parseInt(innerWidth - 50) + "px"), "padding-bottom": 0 });
10353		    		
10354		    		if (jpop.height() + 50 >
10354 innerHeight) {
10355			    		var topHeight = jpop.find('.pop-header').height();
10356			    		var bottomHeight = jpop.find('.pop-buttons-parent').height();
10357			    		var tableHeight = parseInt(innerHeight - topHeight - bottomHeight - 100) + 'px';
10358			    		
10359			    		jpop.find('#payroll-history-detail-view').css({ "max-height": tableHeight });			//, "overflow-y": "auto"
10360			    	}
10361		    	}
10362		    	
10363		    	ojpop.realign();
10364		    	//GLO.UI.Form.resetProcessing();
10365	        })
10366	        .error(function(jqXHR, textStatus, errorThrown) {
10367                ojprocessing.close();
10368                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
10369            });
10370    }
10371    _conRptPayroll.openHelpHistory = function() {
10372    	var htm = _getHistoryHelpInfo();
10373    	GLO.Popup.Info.open(htm, 'About Payroll History');
10374    }
10375    function _getHistoryHelpInfo() {
10376    	return $('#pop-payroll-history-help').outerHTML();
10377    }
10378    
10379    _conRptPayroll.processPayrollFromRow = function(that, isFindFirstDay) {
10380    	if (UTIL.parseBool(isFindFirstDay)) {
10381    		var tr = $('#report-payroll-days').find('tr.has-unprocessed-tickets');			//has-incomplete-tickets
10382    	} else {
10383    		var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr');
10384    	}
10385    	
10386    	var day = tr.attr('day_d');
10387    	var label = tr.find('.payroll-column-day').attr('popupName');
10388    	var htm = '<div id="pop-processing-run-payroll">Running Payroll for ' + day + '...</div>';
10389    	var jpop = tr.closest('.glopop');
10390    	
10391    	if (jpop.length) {			//is staff-preview popup
10392    		var btnProcessPayroll = jpop.find('#pop-payroll-day-status-buttons .btnSave > a');
10393    		
10394    		if (btnProcessPayroll.length) {
10395    			GLO.Popup.closeIfExist( $('#pop-help-cell-summary').closest('.glopop') );
10396    			btnProcessPayroll.click();
10397    			return;
10398    		}
10399    	}
10400    	
10401    	GLO.Popup.Processing.open(htm, label);
10402    	_conRptPayroll.processPayroll(day);
10403    }
10404    _conRptPayroll.openProcessingPayrollPopup = function(isOpenPopup, customMessage, isInfoPopup) {
10405    	var dtUTC = new Date(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDay());
10406		dtUTC.setSimpleTime(5, 50, 0);				//= payroll automatically processed at 5:50 am UTC = [9:50 pm PST / 10:50 MT / 11:50 pm CST / 12:50 EST] (not during daylight savings)
10407    	
10408    	// if (dt.getHours() > 9) { dt = new Date().addDays(1); }
10409    	var dtLocalPayrollTime = dtUTC.toLocalTime(true);
10410    	var msg0 = '', arrow = '<b class="arrow-right">&#10140;</b>';
10411    	var icon = '<b class="question-icon" onclick="GLO.Report.Payroll.openHelpHistory(this)" style="margin-left: 4px;">?</b>';
10412    	
10413    	if (customMessage) {
10414    		msg0 = '<p style="margin-bottom: 24px; text-align: center; font-weight: bold; color: #4F81BD;">' + customMessage + '...</p>';
10415    	}
10416    	
10417    	var msg1 = '<p>Payroll is processed every night at ' + dtLocalPayrollTime.toGloTime() + '</p>';
10418    	var msg2 = '<p>Payroll can be manually processed earlier <span class="narrow-text">(for example, to print a staff\'s commission details)</span></p>';
10419    	var msg3 = '<p style="font-stretch: condensed;">After payroll is processed, if a ticket is changed ' + arrow + ' payroll must be manually re-processed' + icon + '</p>';
10420    	var htm = '<div id="pop-processing-payroll">' + msg0 + msg1 + msg2 + msg3 + '</div>';
10421    	
10422    	if (isOpenPopup) {
10423    		var ojpop = GLO.Popup.Processing.open(htm, 'Processing Payroll...');
10424    		var jpop = ojpop.getPopup();
10425    		
10426    		if (isInfoPopup) {
10427    			jpop.css({ "background-image": "none" });
10428    			jpop.find('.pop-header h1').text('Payroll Processing');
10429    		}
10430    		
10431    		return ojpop;
10432    	} else {
10433    		return htm;
10434    	}
10435    }
10436    _conRptPayroll.processPayroll = function(day, staffId) {
10437    	var isSingleStaff = false, url = GLO.Link.WebsiteDomain + 'report/PayrollProcess?sfilter=';
10438    	var reportPassword = $.trim($('#report-password-container #Report_Password_vc').val());
10439        var jdPost = { "report_password_vc": reportPassword };
10440    	
10441    	if (!UTIL.isEmpty(staffId)) {
10442    		url += staffId;
10443    		isSingleStaff = true;
10444    	} else {
10445    		url += UTIL.cleanString(GLO.Uri.url('sfilter'));
10446    	}
10447    	
10448    	GLO.Popup.closeIfExist($('#pop-processing-run-payroll').closest('.glopop'));
10449        GLO.UI.Form.beginProcessing($('#btnViewPayrollByDay, #btnProcessPayrollByDay'));
10450        var ojProcessing = _conRptPayroll.openProcessingPayrollPopup(true);
10451        
10452        if (UTIL.isDate(day)) {
10453        	url += '&day=' + new Date(day).toGloDate();
10454        }
10455        
10456        $.ajax({ type: "POST", url: url, "cache": false, "data": jdPost })
10457            .success(function(data, textStatus, jqXHR) {
10458                GLO.Popup.closeIfExist($('.pop-processing.glopop'));
10459                GLO.Popup.closeIfExist($('.pop-help-cell-summary').closest('.glopop'));
10460                ojProcessing.close();
10461                GLO.UI.Form.resetProcessing();
10462                
10463                var fnReload = null, jdata = $(data);
10464                
10465                if (GLO.Report.portalName == 'payroll-days') {
10466	                fnReload = function() {
10467	                	//GLO.Popup.Processing.open('Re-Loading Daily Payroll Report...');
10468	                	location.reload();
10469	                }
10470                } else if (isSingleStaff) {
10471                	fnReload = function() {
10472	                	SA.POS.printTodayCommissionByStaff(null, staffId, true);
10473	                }
10474                }
10475                
10476                if (!UTIL.isEmpty(jdata.attr('warning_cd')) || jdata.hasClass('warning')) {
10477                	var jpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Unable to Process Payroll').getPopup();
10478                	var btnLookupPass = jpop.find('#enter-report-password .btnSearchWithReportPassword.btnAdd > a');
10479                	
10480                	if (btnLookupPass.length) {
10481                		btnLookupPass.attr('onclick', 'GLO.Report.Payroll.processPayroll("' + day + '", "' + UTIL.cleanString(staffId) + '")');
10482                		//btnLookupPass.off('click').on('click', 'GLO.Report.Payroll.processPayroll(' + day + ', "' + UTIL.cleanString(staffId) + '")');
10483                	}
10484                } else if (jdata.hasClass('success')) {
10485                	GLO.Popup.closeIfExist($('#report-payroll-days-full-page').closest('.glopop'));
10486                	
10487                	var htm = '<div id="pop-processing-payroll">' + jdata.outerHTML() + '<p>Re-Loading Daily Payroll... </p></div>';
10488	                var jpop = GLO.Popup.Processing.open(htm, 'Payroll Processed Successfully');
10489	                
10490	                setTimeout(fnReload, 2000);
10491                } else {
10492                	_displayDaySummary(jdata);
10493                }
10494            })
10495            .error(function(jqXHR, textStatus, errorThrown) {
10496                GLO.UI.Form.resetProcessing();
10497                GLO.Popup.Error('Unable to lookup data at this time - Please try again');
10498                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
10499            });
10500    }
10501    
10502    function _loookupDaySummary(day) {
10503    	var sfilter = UTIL.coalesceString($('#report-payroll-days-all-data').attr('sfilter'), GLO.Uri.url('sfilter'))
10504    	var url = GLO.Link.WebsiteDomain + 'report/PayrollDayStatus?sfilter=' + sfilter;
10505        
10506        GLO.Popup.closeIfExist($('#report-payroll-days-full-page').closest('.glopop'));
10507    	
10508        if (day) {
10509        	url += '&day=' + day;
10510        } else {
10511        	GLO.UI.Form.beginProcessing($('#btnViewPayrollByDay'));
10512        }
10513        
10514        $.ajax({ type: "GET", url: url, "cache": false })
10515            .success(function(data, textStatus, jqXHR) {
10516                var jdata = $(data);
10517                _displayDaySummary(jdata);
10518                
10519                GLO.Popup.closeIfExist($('#pop-processing-view-payroll-day-summary').closest('.glopop'));
10520                GLO.UI.Form.resetProcessing();
10521            })
10522            .error(function(jqXHR, textStatus, errorThrown) {
10523                GLO.Popup.closeIfExist($('#pop-processing-view-payroll-day-summary').closest('.glopop'));
10524                GLO.UI.Form.resetProcessing();
10525                GLO.Popup.Error.open('Unable to lookup data at this time - Please try again', 'Process Payroll Failed');
10526                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
10527            });
10528    }
10529    _conRptPayroll.viewDaySummaryFromRow = function() {
10530    	var tr = $('#report-payroll-days').find('td.cell-summary-selected').closest('tr');
10531    	var day = tr.attr('day_d');
10532    	var label = tr.find('.payroll-column-day').attr('popupName');
10533    	var htm = '<div id="pop-processing-view-payroll-day-summary">Looking up Payroll Summary for ' + day + '...</div>';
10534    	
10535    	GLO.Popup.closeIfExist($('#pop-help-cell-summary').closest('.glopop'));
10536    	GLO.Popup.Processing.open(htm, label);
10537    	
10538    	_loookupDaySummary(day);
10539    }
10540    _conRptPayroll.viewToday = function() {
10541    	var jrpt = $('#report-payroll-days-all-data');
10542    	//var dtLastProcess = jrpt.attr('process_dt');
10543    	var jpopDayStatus = jrpt.find('#report-payroll-day-status #pop-payroll-day-status');
10544    	
10545    	if (jpopDayStatus.length) {
10546    		_displayDaySummary(jpopDayStatus);
10547    		jpopDayStatus.remove();
10548    	} else {
10549    		_loookupDaySummary();
10550    	}
10551    }
10552    function _displayDaySummary(jpopDayStatus, fnOnClose) {
10553    	var jheader = jpopDayStatus.find('#pop-payroll-day-status-header');
10554    	var htmHeader = jheader.html();
10555    	jheader.remove();
10556    	
10557    	var htm = jpopDayStatus.outerHTML();
10558    	var jpop = GLO.Popup.Custom.openSimple(htm, htmHeader);
10559    	GLO.Popup.Custom.singleButton(jpop, 'Close', fnOnClose);
10560    }
10561    
10562    function _loadPayrollByDayData(jRptData, start, end) {
10563    	var jtables = jRptData.find('table.tablesorter');
10564    	var isPopup = $('.quick-report.glopop #report-payroll-days-all-data').length;
10565    	
10566    	for (var i=0; i < jtables.length; i++) {
10567    		var jtbl = jtables.eq(i);
10568    		UI.initTableSorter(jtbl);
10569    	}
10570    	
10571    	if (isPopup) {
10572    		
10573    	} else {
10574	    	_setHeaderPeriod('payroll-report-by-day', start, end);
10575	    	GLO.Report.enableFullPageCheck();
10576	    	
10577	    	var jwarn = $('#payroll-history-diff-warning:visible');
10578	    	var jfix = $('#report-payroll-warning-fix');
10579	    	
10580	    	if (jwarn.length && jfix.find('li').length) {
10581	    		var htm = '<div id="report-payroll-warning-fix-all"> <h4>Fix Differences</h4>' + jfix.removeClass('hideX').outerHTML() + '</div>';
10582	    		jwarn.append(htm);
10583	    	}
10584	    	
10585	    	jfix.remove();
10586    	}
10587    	
10588    	GLO.Report.CellSummary.initReport(jRptData, true, true);
10589    }
10590    function _loadPayrollData(jRptData, start, end) {
10591    	var jtbl = jRptData.find('table.tablesorter');
10592		var sortArray = [1,0];			//= sort by employee, then staff
10593		UI.initTableSorter(jtbl, sortArray);
10594		
10595		_initHideEmptyColumns();
10596		_conRptPayroll.Adjust.loadDisplayAdjustment(jtbl);
10597		_loadFooter(jtbl);
10598		_initHeader(jtbl);
10599		_setHeaderPeriod('main-payroll-report', start, end);
10600		
10601		GLO.Report.CellSummary.initReport(jRptData, true, true);
10602		GLO.Report.enableFullPageCheck();
10603    }
10604    
10605	_conRptPayroll.setPreviousPeriod = function(isMainPayrollReport) {
10606		_setPeriodAndSearch('previous', isMainPayrollReport);
10607	}
10608	_conRptPayroll.setCurrentPeriod = function(isMainPayrollReport) {
10609		_setPeriodAndSearch('current', isMainPayrollReport);
10610	}
10611	_conRptPayroll.setCustomPeriod = function(isMainPayrollReport) {
10612		_setPeriodAndSearch('other', isMainPayrollReport);
10613	}
10614	function _setPeriodAndSearch(period, isMainPayrollReport) {
10615		var jDatePeriod = $('#payroll-report-date-period');
10616		var jDateRange = $('#payroll-report-date-range');
10617		
10618		if (!isMainPayrollReport) {
10619			jDateRange.addClass('hide');
10620		}
10621		
10622		jDatePeriod.find('.btnMultiChild .btnAdd.selected').removeClass('selected');
10623		var btn = jDatePeriod.find('.btnMultiChild[value="' + period + '"]').find('.btnAdd').addClass('selected');
10624		
10625		if (period == 'previous') {
10626			var start = jDatePeriod.attr('previous_start_d');
10627			var end = jDatePeriod.attr('previous_end_d');
10628		} else if (period == 'current') {
10629			var start = jDatePeriod.attr('current_start_d');
10630			var end = jDatePeriod.attr('current_end_d');
10631		} else if (period == 'other') {
10632			jDateRange.removeClass('hide');
10633			jDatePeriod.find('#report-start').focus();
10634			return;
10635		}
10636		
10637		jDateRange.find('#report-start').val(start).change();
10638		jDateRange.find('#report-end').val(end).change();
10639		
10640		GLO.Report.Payroll.search();
10641		GLO.UI.Form.beginProcessing(btn);
10642	}
10643    
10644    function _initHeader(jtbl) {
10645    	//var tr = jtbl.find('#report-payroll-header1');
10646    	
10647    	_initColumnGroup(jtbl, 'service-percent', 'commission-percent');
10648    	_initColumnGroup(jtbl, 'hourly-rate', 'hourly', 'hours-worked');
10649    	//_initColumnGroup(jtbl, 'min-weekly', 'day');
10650    	_initColumnGroup(jtbl, 'sale-product', 'sale', 'sale-service');
10651    	
10652    	_initColumnGroup(jtbl, 'product-dollar', 'commission-dollar', 'service-dollar');
10653    	_initColumnGroup(jtbl, 'service-fee', 'fee', 'supply-fee');
10654    	//_initColumnGroup(jtbl, 'adjust', 'adjust', 'adjust-note');
10655    	_initColumnGroup(jtbl, 'hourly-wage', 'total', 'total');
10656    	
10657    	_initColumnGroup(jtbl, 'full-days', 'day', 'actual-days');
10658    }
10659    
10660    function _setHeaderPeriod(reportClass, start, end) {
10661    	if (UTIL.isDate(start) && UTIL.isDate(end)) {
10662    		var jperiod = $('#report-main.' + reportClass + ' #payroll-report-date-period');
10663    		var btnPrev = jperiod.find('.btnMultiPreviousPeriod .btnAdd');
10664    		var btnCurr = jperiod.find('.btnMultiCurrentPeriod .btnAdd');
10665    		
10666    		var prevStart = new Date(jperiod.attr('previous_start_d')).toGloDate();
10667    		var prevEnd = new Date(jperiod.attr('previous_end_d')).toGloDate();
10668    		
10669    		var currStart = new Date(jperiod.attr('current_start_d')).toGloDate();
10670    		var currEnd = new Date(jperiod.attr('current_end_d')).toGloDate();
10671    		
10672    		var searchStart = new Date(start).toGloDate();
10673    		var searchEnd = new Date(end).toGloDate();
10674    		
10675    		if (searchStart == prevStart && searchEnd == prevEnd) {
10676    			btnPrev.addClass('selected');
10677    			btnCurr.removeClass('selected');
10678    		} else if (searchStart == currStart && searchEnd == currEnd) {
10679    			btnPrev.removeClass('selected');
10680    			btnCurr.addClass('selected');
10681    		} else {
10682    			btnPrev.removeClass('selected');
10683    			btnCurr.removeClass('selected');
10684    		}
10685    	}
10686    }
10687    function _initColumnGroup(jtbl, column, columnGroup, columnCheck) {
10688    	var jgroup = jtbl.find('.group-' + columnGroup);
10689    	var jtd = jtbl.find('tr#report-payroll-header1 .group-' + columnGroup + ':first'); //jtbl.find('tr#report-payroll-header1 .' + column + '-column');
10690    	
10691    	var jtd2 = jtbl.find('tr#report-payroll-header2 .group-' + columnGroup);
10692    	var title = UTIL.coalesceString(jtd2.text(), columnGroup.replace('-', ' '));
10693    	
10694    	var isHide = SA.Help.getCookieItem('payroll-table', 'group-' + columnGroup);
10695    	//var arrowOpen = '<span class="open-columns-icon"><b onclick="GLO.Report.Payroll.displayColumnGroup(true, \'' + column + '\', \'' + columnGroup + '\')">&harr;</b></span>';
10696    	var closeIcon = '<span class="close-columns-icon" title="' + title + '"><b onclick="GLO.Report.Payroll.displayColumnGroup(false, \'' + column + '\', \'' + columnGroup + '\')">&#10006;</b></span>';
10697    	
10698    	if (!isHide) {
10699	    	isHide = true;
10700	    	
10701	    	if (columnGroup === 'adjust') {
10702	    		var jcheck = jtbl.find('.adjust-input');
10703	    		var jnote  = jtbl.find('.adjust-note .payroll-adjust-note');
10704	    		
10705	    		if (jnote.length) {
10706	    			isHide = false;
10707	    		} else {
10708		    		for (var i=0; i < jcheck.length; i++) {
10709		    			if (UTIL.isEmpty(jcheck.eq(i).val())) {
10710		    				isHide = false;
10711		    				break;
10712		    			}
10713		    		}
10714	    		}
10715	    	} else {
10716	    		var jcheck = jtbl.find('.' + column + '-column, .' + columnCheck + '-column');
10717	    		
10718	    		for (var i=0; i < jcheck.length; i++) {
10719	    			if (UTIL.isEmpty(jcheck.eq(i).text())) {
10720	    				isHide = false;
10721	    				break;
10722	    			}
10723	    		}
10724	    	}
10725    	}
10726    	
10727    	jtd.html(closeIcon);
10728    	
10729    	if (isHide) {
10730    		_conRptPayroll.displayColumnGroup(false, column, columnGroup, true);
10731    	}
10732    }
10733    _conRptPayroll.enableFullPage = function() {
10734    	var cookie = $.cookies.get('payroll-table');		//if cookie exists -> reload page
10735    	
10736    	UTIL.setCookie('payroll-table', null);
10737    	GLO.Report.enableFullPage(true);
10738    	
10739    	if (!UTIL.isEmpty(cookie)) {
10740    		GLO.Popup.Processing.open('Reloading to display all columns', 'Display All Columns');
10741    		
10742    		setTimeout(function() {
10743    			location.reload();
10744    		}, 100);
10745    	}
10746    }
10747    _conRptPayroll.displayColumnGroup = function(isDisplay, column, columnGroup, isInit) {
10748    	var jtbl = $('#report-payroll-summary');
10749    	var jgroup = jtbl.find('.group-' + columnGroup);
10750    	var jcolumn = jtbl.find('.' + column + '-column');
10751    	
10752    	jtbl.find('.narrow-column.group-' + columnGroup).remove();
10753    	
10754    	if (isDisplay) {
10755    		if (!isInit) {
10756    			SA.Help.setCookieItem('payroll-table', 'group-' + columnGroup, true);
10757    		}
10758    		
10759    		jgroup.removeClass('hideX');
10760    	} else {
10761    		if (!isInit) {
10762    			SA.Help.setCookieItem('payroll-table', 'group-' + columnGroup);
10763    		}
10764    		
10765    		jgroup.addClass('hideX');
10766    		
10767    		var innerIcon = '<b onclick="GLO.Report.Payroll.displayColumnGroup(true, \'' + column + '\', \'' + columnGroup + '\')">&harr;</b>';
10768    		var title = UTIL.coalesceString(jgroup.closest('thead').find('tr#report-payroll-header2 .group-' + columnGroup).text(), columnGroup.replace('-', ' '));
10769    		var icon = '<span class="open-columns-icon" title="' + title + '">' + innerIcon + '</span>';
10770    		
10771    		var tdStart = '<td class="group-' + columnGroup + ' narrow-column">';
10772    		var jtd = jtbl.find('tr').find('th.group-' + columnGroup + ':first, td.group-' + columnGroup + ':first');
10773    		
10774    		for (var i=0; i < jtd.length; i++) {
10775    			if (!jtd.eq(i).hasClass('hideX')) {
10776	    			if (i === 0) {
10777	    				jtd.eq(i).before(tdStart + icon + '</td>');
10778	    			} else {
10779	    				jtd.eq(i).before(tdStart + '</td>');
10780	    			}
10781    			}
10782    		}
10783    	}
10784    }
10785    function _loadFooter(jtbl) {
10786    	var tfoot = jtbl.find('tfoot');
10787    	var staffCount = UTIL.coalesceInt(tfoot.attr('staff_count_sr'));
10788    	var hourlyCount = UTIL.coalesceInt(tfoot.attr('staff_hourly_count_sr')), commissionCount = UTIL.coalesceInt(tfoot.attr('staff_commission_count_sr'));
10789    	
10790    	if (staffCount > hourlyCount + commissionCount || (hourlyCount > 0 && commissionCount > 0)) {
10791    		jtbl.addClass('style-staff-type');
10792    	} else {
10793    		jtbl.find('tr .staff-type-column').remove();
10794    	}
10795    }
10796    
10797    _conRptPayroll.changeDateRange = function(start, end) {
10798    	$('.report-search-header #report-start').val(start);
10799    	$('.report-search-header #report-end').val(end);
10800    	
10801    	GLO.Report.Payroll.search();
10802    	_conRptPayroll.highlightDateRange();
10803    }
10804    
10805    _conRptPayroll.highlightDateRange = function() {
10806    	GLO.Popup.close();
10807    	UI.highlight($('.report-search-header > ul'), null, null, true);
10808    }
10809    
10810    function _getPayrollLink(start) {
10811    	var end = new Date(start).addDays(7).toGloDate();
10812    	var link = 'reports/payroll?start=' + start + '&end=' + end;
10813    	var dt = new Date(start).getWeekDayString() + ' ' + new Date(start).toSADate(true);
10814    	
10815    	return '<a onclick=\'GLO.Report.Payroll.changeDateRange("' + start + '", "' + end + '")\'>Starting ' + dt + '</a>';
10816    }
10817    
10818    _conRptPayroll.printReport = function() {
10819    	//GLO.Report.enableFullPage(false);
10820    	GLO.Popup.close($('#pop-print-payroll').closest('.glopop'));
10821    	UI.Print.printOnDevice();
10822    }
10823    _conRptPayroll.openPrintReport = function() {
10824    	var jdt = $('#payroll-report-date-range');
10825    	var start = UTIL.fromSADate(jdt.find('#report-start').val(), true, true);
10826    	var end = UTIL.fromSADate(jdt.find('#report-end').val(), true, true);
10827    	var urlPayrollByDay = 'report/payrollDays?print=1&start=' + start + '&end=' + end + '&sfilter=' + GLO.Uri.query('sfilter');
10828    	
10829    	var btn1 = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUri(\'' + urlPayrollByDay + '\', this, event, true)">Daily Payroll</a></span>';
10830    	var btn2 = '<span class="btnAdd"><a onclick="GLO.Report.Payroll.printReport()">Payroll Report</a></span>';
10831    	var btn3 = '<span class="btnAdd"><a onclick="GLO.Report.Payroll.gotoPrintReport()">Sales History</a></span>';
10832    	
10833    	var htm = '<div id="pop-print-payroll"><div style="margin-top: 24px;">' + btn1 + '</div><div style="margin: 24px;">' + btn2 + '</div></div>';
10834    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Print');
10835    	GLO.Popup.Custom.singleButton(jpop, 'Close');
10836    }
10837    _conRptPayroll.gotoPrintReportByStaff = function() {
10838    	var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr');
10839    	var sid = tr.attr('staff_id');
10840		var sname = tr.find('.staff-column').text();
10841		
10842		_conRptPayroll.gotoPrintReport(sid, sname);
10843    }
10844    _conRptPayroll.gotoPrintReport = function(sid, sname) {
10845    	GLO.Popup.close($('#pop-print-payroll').closest('.glopop'));
10846    	
10847    	var msg = '', jrpt = $('#doc3 #report-main');
10848    	var start = UTIL.fromSADate(jrpt.find('#report-start:visible').val(), true, true);
10849    	var end = UTIL.fromSADate(jrpt.find('#report-end:visible').val(), true, true);
10850    	
10851    	var url = 'reports/saleshistory?isfullpage=1&open=print&start=' + start + '&end=' + end;		//toDo: pass -> daily fees (supply, cleaning) | '+ min'
10852    	var title = UTIL.coalesce(title, 'Print Sales');
10853    	
10854    	if (!UTIL.isEmpty(sid)) {
10855    		url += '&sfilter=' + sid;
10856    	}
10857    	
10858    	if (!UTIL.isEmpty(sname)) {
10859    		msg = 'Printing Sales report for ' + sname + '<br/><br/>';
10860    	}
10861    	
10862    	GLO.Popup.Processing.open(msg + 'Loading Printable Report...', title);
10863    	GLO.Report.CellSummary.gotoReport(url, null, event);
10864    }
10865    _conRptPayroll.exportReport = function() {
10866    	//var tbody = document.getElementById('report-payroll-summary-container');
10867    	var jrpt = $('#report-payroll-summary');
10868    	var trs = jrpt.find('tr'); 
10869    	var fileName = 'Payroll ' + new Date(jrpt.attr('start_d')).toGloDate(true) + ' - ' +  new Date(jrpt.attr('end_d')).toGloDate(true);
10870    	
10871    	_exportExcel(trs, fileName);
10872    	//exportTableToExcel('report-payroll-summary-container', filename = '');
10873    }
10874    
10875    function exportTableToExcel(tableID, filename = '') {
10876	    var downloadLink;
10877	    var dataType = 'application/vnd.ms-excel';
10878	    var tableSelect = document.getElementById(tableID);
10879	    var tableHTML = tableSelect.outerHTML.replace(/ /g, '%20');
10880	    
10881	    filename = filename ? filename + '.xls' : 'excel_data.xls';			//Specify file name
10882	    downloadLink = document.createElement("a");							//Create download link element
10883	    document.body.appendChild(downloadLink);
10884	    
10885	    if (navigator.msSaveOrOpenBlob) {
10886	        var blob = new Blob(['\ufeff', tableHTML], {
10887	            type: dataType
10888	        });
10889	        navigator.msSaveOrOpenBlob(blob, filename);
10890	    } else {
10891	        downloadLink.href = 'data:' + dataType + ', ' + tableHTML;		//Create a link to the file
10892	    	downloadLink.download = filename;
10892								//Setting the file name
10893	        downloadLink.click();											//triggering the function
10894	    }
10895	}
10896    
10897    function _exportExcel(trs, fileName) {
10898	    var htm = '<table border="2px">';
10899	    var textRange, j=0, rowCount = 0;
10900	    
10901	    for (a=0 ; a < trs.length ; a++) {
10902	        var tr = trs.eq(a);
10903	        
10904	        if (!tr.hasClass('ignore-export')) {
10905	        	if (tr.parent().is('thead')) {
10906	        		var css = 'text-align: center; font-weight: bold; background-color: rgb(180,200,255);';
10907	        	} else if (tr.parent().is('tfoot')) {
10908	        		var css = 'background-color: rgb(200,200,200);';
10909	        	} else {
10910	        		if (rowCount % 2 === 1) {
10911	        			var css = 'background-color: rgb(250,250,250);';
10912	        		} else {
10913	        			var css = '';
10914	        		}
10915	        		
10916	        		++rowCount;
10917	        	}
10918	        	
10919	        	htm += '<tr style="' + css + '">';
10920	        	var tds = trs.eq(a).find('th,td');
10921		        
10922		        for (var b=0; b < tds.length; b++) {
10923		        	var td = tds.eq(b);
10924		        	
10925		        	if (!td.hasClass('ignore-export')) {
10926		        		td = td.clone();
10927		        		td.find('.btnAdd, .btnSave').remove();
10928		        		
10929		        		if (td.find('input').length) {
10930		        			var jinput = td.find('input');
10931		        			td.append(jinput.val());
10932		        			jinput.remove();
10933		        		}
10934		        		
10935		        		htm += td.outerHTML();
10936		        	}
10937		        }
10938		        
10939	        	htm += '</tr>';
10940	        }
10941	    }
10942		
10943	    htm += '</table>';
10944	    htm = htm.replace(/<A[^>]*>|<\/A>/g, '');				//remove if u want links in your table
10945	    htm = htm.replace(/<img[^>]*>/gi, ''); 					//remove if u want images in your table
10946	    //htm = htm.replace(/<input[^>]*>|<\/input>/gi, ''); 		//removes input params
10947		
10948	    var ua = window.navigator.userAgent;
10949	    var msie = ua.indexOf("MSIE "); 
10950		
10951		if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {      // If Internet Explorer
10952	        txtArea1.document.open("txt/html","replace");
10953	        txtArea1.document.write(htm);
10954	        txtArea1.document.close();
10955	        txtArea1.focus();
10956	        sa = txtArea1.document.execCommand('SaveAs', true, fileName);
10957	    } else {
10958	    	//sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(htm));
10959	    	
10960	    	var downloadLink = $('#btnExportLink')[0];
10961	    	downloadLink.href = 'data:application/vnd.ms-excel,' + encodeURIComponent(htm);
10962	    	downloadLink.download = fileName;
10963	        downloadLink.click();
10964	    }
10965		
10966	    //return (sa);
10967	}
10968	
10969	_conRptPayroll.openDailyPrintSettings = function() {
10970		var header = 'Daily Payroll Print which sections?';
10971		var msg = '<p>What sections would you like to print?</p>';
10972		var list = '<ul>'
10973				+ '<li style="margin-bottom: 8px;"> <input type="checkbox" id="Payroll_Daily_Print_cd10" value="M"> <label for="Payroll_Daily_Print_cd10">Main Daily summary</lable> </li>'
10974				+ '<li> <input type="checkbox" id="Payroll_Daily_Print_cd20" value="C"> <label for="Payroll_Daily_Print_cd20">Cash Drawer</lable> </li>'
10975				
10976				+ '<li> <input type="checkbox" id="Payroll_Daily_Print_cd110" value="D"> <label for="Payroll_Daily_Print_cd110">Discount</lable> </li>'
10977				+ '<li> <input type="checkbox" id="Payroll_Daily_Print_cd120" value="P"> <label for="Payroll_Daily_Print_cd120">Payment Type</lable> </li>'
10978				+ '<li style="margin-bottom: 8px;"> <input type="checkbox" id="Payroll_Daily_Print_cd130" value="T"> <label for="Payroll_Daily_Print_cd130">Tip</lable> </li>'
10979				+ '<li> <input type="checkbox" id="Payroll_Daily_Print_cd140" value="S"> <label for="Payroll_Daily_Print_cd140">Early/Normal Service Commission</lable> </li>'
10980				+ '<li> <input type="checkbox" id="Payroll_Daily_Print_cd150" value="F"> <label for="Payroll_Daily_Print_cd150">Fee</lable> </li>'
10981				+ '<li> <input type="checkbox" id="Payroll_Daily_Print_cd160" value="W"> <label for="Payroll_Daily_Print_cd160">Total Wage</lable> </li>'
10982			+ "</ul>";
10983		
10984		var htm = '<div id="pop-daily-payroll-print">' + msg + list + '</div>';
10985		var jpop = GLO.Popup.Custom.openSimple(htm, header, GLO.Report.Payroll.
10985saveDailyPrintSettings);
10986		var arr = $('#report-payroll-days-full-page').attr('payrollDailyPrint').split(',');
10987		var isAll = (arr.length === 0 || (arr.length === 1 && (arr[0] === '' || arr[0] === 'A')));
10988		
10989		if (isAll) {
10990			jpop.find(':checkbox').prop('checked', true);
10991		} else {
10992			for (var i=0; i < arr.length; i++) {
10993				jpop.find(':checkbox[value = "' + arr[i] + '"]').prop('checked', true);
10994			}
10995		}
10996	}
10997	_conRptPayroll.saveDailyPrintSettings = function() {
10998		var settings = '', jpop = $('#pop-daily-payroll-print').closest('.glopop');
10999		var jbox = jpop.find(':checkbox:checked');
11000		
11001		for (var i=0; i < jbox.length; i++) {
11002			if (i > 0) { settings += ','; }
11003			
11004			settings += jbox.eq(i).val();
11005		}
11006		
11007        var url = GLO.Link.WebsiteDomain + 'report/PayrollDailyPrint?settings=' + settings;
11008        
11009        GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
11010        
11011        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
11012            .success(function(data, textStatus, jqXHR) {
11013                GLO.UI.Form.resetProcessing();
11014                GLO.Popup.close(jpop);
11015                GLO.Popup.Processing.open('Reloading Print Settings...', 'Print Settings Saved');
11016                
11017                setTimeout(function() {
11018                	location.reload();
11019                }, 100);
11020            })
11021            .error(function(jqXHR, textStatus, errorThrown) {
11022                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
11023            });
11024	}
11025	
11026	_conRptPayroll.openDailyPayrollWarning = function() {
11027		var htmWarn = $($('#daily-payroll-report-header-help #payroll-history-diff-warning').outerHTML()).removeClass('hide').removeClass('hideX').outerHTML();
11028		var htmFix = $($('#report-payroll-warning-fix').outerHTML()).removeClass('hide').removeClass('hideX').outerHTML();
11029		var fixHeader = '<h4>Fix Differences</h4>';
11030		var htm = '<div id="pop-warn-payroll-daily">' + htmWarn + fixHeader + htmFix + '</div>';
11031		
11032		var ojpop = GLO.Popup.Warning.open(htm, 'Current Payroll Report vs Payroll History');
11033		var jpop = ojpop.getPopup();
11034		
11035		GLO.Popup.Custom.singleButton(jpop, 'Close');
11036	}
11037	
11038	_conRptPayroll.printToday = function() {
11039		GLO.Report.Payroll.setCustomPeriod();
11040		var now = new Date().toSADate() + ', ' + new Date().getFullYear();
11041		var jhead = $('#payroll-report-header');
11042		
11043		jhead.find('#report-start').val(now).change();
11044		jhead.find('#report-end').val(now).change();
11045		
11046		GLO.Popup.closeIfExist( $('#pop-payroll-day-status').closest('.glopop') );
11047		GLO.Report.Payroll.search();		//http://www.test3.com/report/payrollDays?start=8/23/2026&end=8/23/2026&sfilter=&period=other
11048	}
11049	
11050    
11051    _conRptPayroll.Adjust = (function() {
11052    	function _cAdjust() {};
11053    	
11054    	_cAdjust.loadDisplayAdjustment = function(jtbl) {
11055	    	var hasAdjustment = false, isManager = (GLO.Info.roleType > 219);
11056	    	var columns = jtbl.find('tbody .adjust-column');
11057			
11058			if (isManager) {
11059				for (var i=0; i < columns.length; i++) {
11060					_colorAdjust(columns.eq(i));
11061				}
11062				
11063				columns.removeClass('hide-on-load');
11064			} else {
11065				for (var i=0; i < columns.length; i++) {
11066					var amt = $.trim(columns.eq(i).text()).replace('$', '');
11067					var amt = UTIL.coalesceMoney(amt);
11068					
11069					if (amt !== 0) {
11070						hasAdjustment = true;
11071					}
11072				}
11073				
11074				if (hasAdjustment) {
11075					columns.removeClass('hide-on-load');
11076				}
11077			}
11078    	}
11079	    function _colorAdjust(td) {
11080	    	var amt = UTIL.coalesceMoney(td.find('input').val());
11081	    	
11082	    	if (amt > 0) {
11083	    		td.addClass('positive-amount').removeClass('negative-amount');
11084	    	} else if (amt < 0) {
11085	    		td.addClass('negative-amount').removeClass('positive-amount');
11086	    	} else {
11087	    		td.removeClass('negative-amount').removeClass('positive-amount');
11088	    	}
11089	    }
11090	    _cAdjust.changeAmount = function(inputElement) {
11091	    	if (!GLO.Report.allowReportChange()) { return; }
11092	    	
11093	    	var td = $(inputElement).closest('td').addClass('unsaved-update');				//.find('.btnSave').removeClass('hide');
11094	    	_colorAdjust(td);
11095	    }
11096	    _cAdjust.openFromPopup = function(element) {
11097	    	var jpop = $('#pop-adjust-list');				//.closest('.glopop');
11098	    	var staffId = jpop.attr('staff_id');
11099	    	var staffName = jpop.find('.adjust-staff').text();
11100	    	
11101	    	var li = $(element).closest('li');
11102	    	var payrollId = li.attr('id'), start = li.attr('start_d'), end = li.attr('end_d');
11103    		var amount = li.find('.adjust-amount').text().replace('$', '');
11104	    	var note = li.find('.adjust-note').text();
11105    		
11106    		_cAdjust.openNote(payrollId, amount, note, start, end, staffId, staffName);
11107	    }
11108	    _cAdjust.openFromRow = function(element) {
11109    		if (!GLO.Report.allowReportChange()) { return; }
11110    		
11111    		var tr = $(element).closest('tr');				//$('#report-payroll-summary').find('tr[staff_id="' + staffid + '"]');
11112    		var adjustCount = UTIL.coalesceInt(tr.attr('adjust_count_sr'));
11113    		var staffName = tr.find('.staff-column').text(), staffId = tr.attr('staff_id');
11114    		
11115    		if (adjustCount > 1) {
11116    			_getAdjustments(staffId, staffName);
11117    		} else {
11118	    		var amount = tr.find('.adjust-column').find('input').val();
11119	    		var note = tr.find('.payroll-adjust-note').text();
11120	    		var payrollId = tr.attr('adjust_id');
11121	    		var start = tr.attr('adjust_start_d'), end = tr.attr('adjust_end_d');
11122	    		
11123	    		_cAdjust.openNote(payrollId, amount, note, start, end, staffId, staffName);
11124    		}
11125    	}
11126    	_cAdjust.openNote = function(payrollId, amount, note, start, end, staffId, staffName) {
11127	    	var tbl = $('#report-payroll-summary');
11128	    	var dt1 = UTIL.coalesceDate(start, tbl.attr('start_d')).toGloDate(), dt2 = UTIL.coalesceDate(end, tbl.attr('end_d')).toGloDate();
11129	    	var id = UTIL.cleanString(payrollId);
11130	    	var h1 = 'Payroll Adjust Amount / Note'
11131	    	
11132	    	var msg = '<p id="pop-payroll-adjust-message">' + staffName + ': ' + new Date(dt1).toSADate(true) + ' - ' + new Date(dt2).toSADate(true) + '</p>';
11133	    	msg += '<div id="pop-display-hourly">Hourly: <b></b>/hour</div>';
11134	    	msg += '<div id="pop-display-total" > Total: <b></b></div>';
11135	    	
11136	    	var labelAmount = '<label for="Adjustment_mn" style="margin: 0;">Adjust <b class="dollar-sign">$</b></label>';
11137	    	var inputAmount = '<input id="Adjustment_mn" type="text" maxlength="7" value="' + UTIL.displayMoney(amount, true) + '" onkeypress="UI.numberOnly(event, true)" onkeyup="GLO.Report.Payroll.Adjust.keyupAmount()">';
11138	    	var htmAmount = '<div>' + labelAmount + inputAmount + '</div>';
11139	    	
11140	    	var textarea = '<div><textarea id="Note_vcl" maxlength="4000" placeholder="Note">' + note + '</textarea></div>';
11141	    	
11142	    	var htm = '<div id="pop-edit-adjust" payroll_id="' + id + '" staff_id="' + staffId + '" start_d="' + dt1 + '" end_d="' + dt2 + '">' + msg + htmAmount + textarea + '</div>';
11143	    	var jpop = GLO.Popup.Custom.open(htm, h1, GLO.Report.Payroll.Adjust.saveAdjust).getPopup().addClass('no-persist');
11144	    	var jsave = jpop.find('.pop-buttons').addClass('pop-buttons2').find('.btnSave');
11145	    	
11146	    	jsave.after('<span class="btnDelete" style="position: absolute; right: 4px; margin: 0;"><a onclick="GLO.Report.Payroll.Adjust.deleteAsk()">Delete</a></span>');
11147	    	jsave.css({ "position": "relative", "right": "inherit", "margin": "0" });
11148	    	_cAdjust.keyupAmount();
11149	    }
11150	    _cAdjust.keyupAmount = function() {
11151	    	var jpop = $('#pop-edit-adjust');				//.closest('.glopop')
11152	    	var sid = jpop.attr('staff_id');
11153	    	var newAdjust = UTIL.coalesceMoney(jpop.find('#Adjustment_mn').val());
11154	    	
11155	    	var tr = $('#report-payroll-summary').find('tr.row-commission[staff_id=' + sid + ']');
11156	    	var total = UTIL.coalesceMoney(tr.find('.total-column').text().replace('$', ''));
11157	    	var currAdjust = UTIL.coalesceMoney(tr.find('.adjust-column').attr('orig_adjust_mn'));
11158	    	var hrs = Math.round(parseInt(tr.find('.hours-worked-column').attr('minutes_worked_sr'))/60, 2);
11159	    	
11160	    	var newTotal = UTIL.coalesceMoney(total - currAdjust + newAdjust);
11161	    	var newHourly = UTIL.displayMoney(newTotal/hrs);
11162	    	
11163	    	var jtotal = jpop.find('#pop-display-total b').removeClass('is-negative'), jhr = jpop.find('#pop-display-hourly b').removeClass('is-negative');
11164	    	
11165	    	if (newTotal < 0) {
11166	    		jtotal.addClass('is-negative');
11167	    		jhr.addClass('is-negative');
11168	    	}
11169	    	
11170	    	jtotal.text(UTIL.displayMoney(newTotal, false, false, true));
11171	    	jhr.text(newHourly);
11172	    }
11173	    function _getAdjustments(staffId, staffName) {
11174	    	var tbl = $('#report-payroll-summary');
11175	    	var start = tbl.attr('start_d'), end = tbl.attr('end_d');
11176	    	var url = GLO.Link.WebsiteDomain + 'report/GetPayrollAdjustment?staffid=' + staffId + '&start=' + start + '&end=' + end;
11177	    	
11178	        var msg = 'Payroll Adjustments and Notes for <b class="adjust-staff">' + staffName + '</b> between ' + new Date(start).toSADate(true) + ' - ' + new Date(end).toSADate(true);
11179	        var jprocessing = GLO.Popup.Processing.open('Loading ' + msg + '...', 'Payroll Adjustments & Notes');
11180	        
11181	        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
11182	            .success(function(data, textStatus, jqXHR) {
11183	                var ul = '<ul>';
11184	                var jdata = $(data);
11185	                var lis = jdata.find('#payroll-adjust-list li');
11186	                
11187	                for (var i=0; i < lis.length; i++) {
11188	                	var li = lis.eq(i), amtColor = '';
11189	                	var amt = UTIL.displayMoney(li.attr('adjustment_mn'), true), id = li.attr('staff_payroll_id');
11190	                	var dt1 = li.attr('start_d'), dt2 = li.attr('end_d')
11191	                	var note = li.text();
11192	                	
11193	                	if (amt > 0) {
11194	                		amtColor = 'green';
11195	                	} else if (amt < 0) {
11196	                		amtColor = 'rgb(240,0,0)';
11197	                	}
11198	                	
11199	                	var adjustRange = '<span class="date-range">' + new Date(dt1).toSADate(true) + ' - ' + new Date(dt2).toSADate(true) + '</span>';
11200	                	var money = '<b class="adjust-amount" style="color: ' + amtColor + ';">' + UTIL.displayMoney(amt) + '</b>';
11201	                	var noteHtm = '<i class="adjust-note">' + note + '</i>';
11202	                	
11203	                	ul += '<li onclick="GLO.Report.Payroll.Adjust.openFromPopup(this)" id="' + id + '" start_d="' + dt1 + '" end_d="' + dt2 + '">' + adjustRange + money + noteHtm + '</li>';
11204	                }
11205	                
11206	                jprocessing.close();
11207	                msg = '<p style="padding-left: 8px; padding-right: 4px;">' + msg + '</p>';
11208	                var msgSmall = '<p style="text-align: center;"><small style="color: #666;">Press any row below to edit the note or amount</small></p>';
11209	                var htm = '<div id="pop-adjust-list" staff_id="' + staffId + '">' + msg + msgSmall + ul + '</ul> </div>';
11210	                var jpop = GLO.Popup.Custom.openSimple(htm, staffName + ' Adjust Amount / Notes');
11211	                GLO.Popup.Custom.singleButton(jpop, 'Close');
11212	            })
11213	            .error(function(jqXHR, textStatus, errorThrown) {
11214	                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
11215	            });
11216	    }
11217	    
11218	    _cAdjust.deleteAsk = function() {
11219	    	//var jpop = $('#pop-edit-adjust').closest('.glopop');
11220	    	
11221	    	var msg = 'Are you sure you want to delete?';
11222	    	var jpop = GLO.Popup.Confirm.open(msg, 'Confirm Delete', GLO.Report.Payroll.Adjust.deleteConfirmed).getPopup();
11223	    }
11224	    _cAdjust.deleteConfirmed = function() {
11225	    	var jadjust = $('#pop-edit-adjust');
11226	    	var jpop = jadjust.closest('.glopop');
11227	    	var id = UTIL.cleanString(jadjust.attr('payroll_id')), staffid = jadjust.attr('staff_id');
11228	    	
11229	    	var url = GLO.Link.WebsiteDomain + 'report/RemovePayrollAdjustment?staffid=' + staffid + '&id=' + id;
11230	        var tr = $('#report-payroll-summary').find('tr[staff_id="' + staffid + '"]');
11231	        
11232	        GLO.UI.Form.beginProcessing(jpop.find('.btnDelete'));
11233	        
11234	        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
11235	            .success(function(data, textStatus, jqXHR) {
11236	                var cnt = parseInt(tr.attr('adjust_count_sr')) - 1;
11237	                var prevAdjust = UTIL.coalesceMoney(tr.find('.adjust-column').attr('orig_adjust_mn'));
11238	                tr.attr('adjust_count_sr', cnt);
11239	                
11240	                if (cnt === 0 && prevAdjust == 0) {
11241	                	tr.attr('adjust_count_sr', '0').removeAttr('adjust_id');
11242	                	tr.find('.adjust-column').find('input').val('');
11243    					tr.find('.adjust-note').html('<span class="btnAdjust btnAdd"><a onclick="GLO.Report.Payroll.Adjust.openFromRow(this)">add</a></span>');
11244	                } else {
11245	                	setTimeout(function() { location.reload(); }, 400);
11246	                }
11247	                
11248	                GLO.UI.Form.resetProcessing();
11249	                GLO.Popup.close(jpop);
11250	                GLO.Popup.Success.open('Adjustment Amount and Note Deleted for ' + tr.find('.staff-column').text(), 'Delete Completed');
11251	                
11252	                var tdAdjust = tr.find('.adjust-column').removeClass('unsaved-update');
11253	                _colorAdjust(tdAdjust);
11254	            })
11255	            .error(function(jqXHR, textStatus, errorThrown) {
11256	                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
11257	            });
11258	    }
11259	    
11260	    _cAdjust.saveAdjust = function() {
11261	    	var jadjust = $('#pop-edit-adjust');
11262	    	var jpop = jadjust.closest('.glopop');
11263	    	var amount = UTIL.coalesceMoney(jadjust.find('#Adjustment_mn').val(), true);
11264	    	var id = UTIL.cleanString(jadjust.attr('payroll_id')), staffid = jadjust.attr('staff_id'), start = jadjust.attr('start_d'), end = j
11264adjust.attr('end_d');
11265	    	var note = UTIL.htmlEncode(jadjust.find('#Note_vcl').val());
11266	    	
11267	    	var url = GLO.Link.WebsiteDomain + 'report/SavePayrollAdjustment?staffid=' + staffid + '&amount=' + amount + '&start=' + start + '&end=' + end + '&id=' + id;
11268	        var tr = $('#report-payroll-summary').find('tr[staff_id="' + staffid + '"]');
11269	        
11270	        GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
11271	        GLO.UI.Form.beginProcessing(tr.find('.btnSave'));
11272	        
11273	        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": { "note": note } })
11274	            .success(function(data, textStatus, jqXHR) {
11275	                var cnt = UTIL.coalesceInt(tr.attr('adjust_count_sr'), 0);
11276	                var adjustId = $(data).attr('staff_payroll_id');
11277	                
11278	                var prevAmount = UTIL.coalesceMoney(tr.find('.adjust-column').attr('orig_adjust_mn'));
11279	                var msg = 'Adjustment Saved for ' + tr.find('.staff-column').text();
11280	                
11281	                if (cnt < 2) {
11282	                	if (!UTIL.isEmpty(note)) {
11283	                		var htmNote = '<span class="payroll-adjust-note"><a onclick="GLO.Report.Payroll.Adjust.openFromRow(this)">' + note + '</a></span>';
11284	                	} else {
11285	                		var htmNote = '<span class="btnAdjust btnAdd"><a onclick="GLO.Report.Payroll.Adjust.openFromRow(this)">add</a></span>';
11286	                	}
11287	                	
11288	                	tr.attr('adjust_count_sr', '1').attr('adjust_id', adjustId);
11289	                	tr.find('.adjust-column').find('input').val(amount);
11290    					tr.find('.adjust-note').html(htmNote);
11291	                }
11292	                
11293	                GLO.UI.Form.resetProcessing();
11294	                GLO.Popup.close(jpop);
11295	                GLO.Popup.close($('#pop-adjust-list').closest('.glopop'));
11296	                
11297	                if (cnt > 1 || prevAmount != amount) {
11298	                	setTimeout(function() { location.reload(); }, 400);
11299	                	
11300	                	msg += '<br/><br/>Re-Loading Payroll Report with new amount...';
11301	                }
11302	                
11303	                GLO.Popup.Success.open(msg, 'Save Successful');
11304	                
11305	                var tdAdjust = tr.find('.adjust-column').removeClass('unsaved-update');
11306	                _colorAdjust(tdAdjust);
11307	            })
11308	            .error(function(jqXHR, textStatus, errorThrown) {
11309	                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
11310	            });
11311	    }
11312    	
11313		return _cAdjust;
11314	})();
11315    
11316	return _conRptPayroll;
11317})();
11318
11319
11320GLO.Report.Timesheet = (function() {
11321    function _conRptTimesheet() { }
11322	var _timeoutUpdateInProgress = null, _bonusCount = 0;
11323	
11324    _conRptTimesheet.init = function() {
11325        GLO.Info.init();
11326        GLO.Report.portalName = 'timesheet';
11327        GLO.Report.init();
11328        GLO.Report.Sales.initStaffFilter();
11329        GLO.Report.isInit = true;
11330        GLO.Report.setupFastClick();
11331        
11332        var j = $('.appt-list-search');
11333        j.find('#report-header-search').click(GLO.Report.Timesheet.search);
11334        
11335        j.find('#Week_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
11336                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths()
11337                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.Timesheet.datePickerOnSelect });
11338        
11339        var jbegin = $('#timesheet-header').find('.Begin_dt');
11340        var dt = new Date(jbegin.val());
11341        var firstDayOfWeek = jbegin.datepicker('option', 'firstDay');			//= first day of the week in the datepicker (likely 'Sunday' = 0 or 'Monday' = 1)
11342        _setWeekDateRange(dt, firstDayOfWeek);
11343        
11344        _initView(j);
11345        GLO.Report.isInit = false;
11346        
11347        if (GLO.Info.roleType === undefined) { GLO.Info.init(); }
11348        
11349        if (GLO.Info.roleType > 199 && GLO.Info.roleType < 220 && GLO.Data.Staff.role_report_cd == 0) {			//= receptionists can only see their own data.
11350        	$('#top-staffName').remove();
11351        } else if (GLO.Info.roleType > 219) {
11352        	_initSFilter();
11352			//$('#top-staffName #staff-filter').val(GLO.Info.StaffId);
11353        	_initClockInIcon();
11354        }
11355        
11356        _loadApprovalType();
11357        _loadDayTable(true);
11358        _initUriTimesheet();
11359    }
11360    function _initUriTimesheet() {
11361    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
11362    	
11363    	if (!UTIL.isEmpty(open)) {
11364    		if (open === 'approve') {
11365    			GLO.Report.Timesheet.openApproveSetting();
11366    		} else if (open === 'more') {
11367    			GLO.Report.Timesheet.displayMoreHelp(true);
11368    			UI.highlight($('#report-header-help'), 100, 4500);
11369    		}
11370    	}
11371    }
11372    function _postSearchSetHeader() {
11373    	var jheader = $('#bd #timesheet-report-header.report-header').find('.report-header-text');
11374		var jrpt = $('#bd #report-main').find('table.tablesorter');
11375		var staffName = jrpt.find('tbody').find('td.staff-column:first').text();
11376		
11377		jheader.find('.display-on-print').remove();
11378		
11379		if (!UTIL.parseBool(jheader.attr('hasMultipleStaffFilter')) && !UTIL.isEmpty(staffName)) {
11380			jheader.html('<b class="display-on-print">' + staffName + '</b> ' + jheader.text());
11381		}
11382    }
11383    
11384    function _loadApprovalType() {
11385    	var jtbl = $('#report-timesheet-day');
11386    	var approveType = jtbl.attr('timesheet_type_cd');
11387    	
11388    	if (approveType == 2 || approveType == 10) {
11389    		jtbl.find('.approve_fl').removeClass('hideX');
11390    	}
11391    }
11392    
11393    function _loadWeekTable() {
11394    	var jtbl = $('#report-timsheet-week');
11395		GLO.Report.CellSummary.initReport(jtbl, true, true);
11396    }
11397    
11398    function _loadDayTable(isInit) {
11399    	if (GLO.Info.isMobile()) {
11400    		if (isInit) {
11401	        	$('#header-icon-container').remove();
11402        	}
11403        	
11404	        setTimeout(function() {
11405	        	var jtbl = $('#report-timesheet-day');
11406		        var tr1 = jtbl.find('#report-timesheet-day-top-header');
11407		        
11408		        if (!$('body').hasClass('report-full-page')) {
11409		        	jtbl.find('.column-schedule-3').attr('colspan', '1');
11410			        jtbl.find('.column-actual-3').attr('colspan', '1');
11411			        jtbl.find('.column-update').attr('colspan', '1');
11412			        
11413			        tr1.addClass('adjust-for-phone');
11414		        }
11415	        }, 1200);
11416        }
11417        
11418        var jtbl = $('#report-timesheet-day');
11419        var jbonus = jtbl.find('input.bonus_mn');
11420        
11421        GLO.Report.CellSummary.initReport(jtbl, true, true);
11422        _checkApproveAllStatus();
11423        _bonusCount = 0;
11424        
11425        for (var i=0; i < jbonus.length; i++) {
11426        	if (UTIL.coalesceMoney(jbonus.val(), 0) !== 0) {
11427        		++_bonusCount;
11428        	}
11429        }
11430        
11431        var btnUnApproveAll = $('#report-timesheet-day-save .btnUnApproveAll');
11432		
11433		if (btnUnApproveAll.length > 0) {
11434			jtbl.find('.btnApproveAll').replaceWith(btnUnApproveAll.outerHTML());
11435		} else {
11436			jtbl.find('.btnApproveAll').removeClass('hide');
11437		}
11438    }
11439    
11440    function _initClockInIcon() {
11441    	if (!GLO.Info.isMobile()) {
11442	    	var jsearch = $('#top-searchBox').addClass('include-clock-out-icon');
11443	    	jsearch.after('<span id="clock-out-icon" class="sa-sprite" onclick="UserPortal.Edit.ClockIn.open(this)" title="Clock In and Out"> <a style="color: rgb(255, 255, 255);"></a> </span>');
11444    	}
11445    }
11446    
11447    function _initSFilter() {
11448    	var sids = UserPortal.getStaffWhoDoInternalService();
11449    	
11450    	var sfilter = $('#staff-filter');
11451    	var sfilterOptions = sfilter.find('#staff-filter-s option');
11452    	
11453    	sfilter.find('#staff-filter-sg').remove();
11454    	sfilter.find('#staff-filter-custom-group option[value!="all"]').remove();
11455    	
11456    	for (var i=1; i < sfilterOptions.length; i++) {				//i=1 --> do NOT remove 'All'
11457    		if (!sids.has(sfilterOptions.eq(i).attr('value'))) {
11458    			sfilterOptions.eq(i).remove();
11459    		}
11460    	}
11461    	
11462    	GLO.Report.initStaffFilter();
11463    	
11464    	/*
11465    	if (GLO.Info.isMobile()) {
11466	    	var sfilter = GLO.Uri.url('sfilter');
11467	    	if (sfilter.indexOf(',') > -1) { sfilter = ''; }
11468	    	
11469	    	sfilterOptions.parent().prepend('<option value="all">All</option>');
11470	    	sfilterOptions.parent().val(sfilter);
11471    	}
11472    	*/
11473    }
11474    
11475    function _initView(j) {
11476    	j.find('#timesheet-view-options input:radio').change(GLO.Report.setViewType);
11477        
11478        var view = String(GLO.Uri.query('view')).toLowerCase();
11479        
11480        if (view === 'week') {
11481            j.find('#timesheet-weekly').click();
11482        } else if (view === 'month') {
11483            j.find('#timesheet-monthly').click();
11484        } else if (view === 'avg-week') {
11485            j.find('#timesheet-avg-week').click();
11486        } else {									// if (view === 'day') {
11487            j.find('#timesheet-daily').click();
11488            _approveAll();
11489        }
11490    }
11491    
11492    _conRptTimesheet.clickSelectWeek = function(element) {
11493    	$('#Week_dt').datepicker('show');
11494    }
11495    
11496    _conRptTimesheet.datePickerOnSelect = function(dateText, inst) {
11497        var jInput = $(inst.input);
11498        var dt = new Date(dateText);
11499        
11500        _conRptTimesheet.datePickerOnSelect2(dt);
11501    }
11502    
11503    _conRptTimesheet.datePickerOnSelect2 = function(dt) {
11504        var jhead = $('#timesheet-header');
11505        var jbegin = jhead.find('.Begin_dt'), jend = jhead.find('.End_dt');
11506        var firstDayOfWeek = jbegin.datepicker('option', 'firstDay');			//= first day of the week in the datepicker (likely 'Sunday' = 0 or 'Monday' = 1)
11507        var dts = _setWeekDateRange(dt, firstDayOfWeek);
11508        
11509        jbegin.val(dts.begin_dt.toGloDate(GLO.Info.isMobile()));
11510	    jend.val(dts.end_dt.toGloDate(GLO.Info.isMobile()));
11511        
11512        GLO.UI.Form.beginProcessing( $('.timesheet-search-week .btnAdd') );
11513        _conRptTimesheet.search();
11514    }
11515    
11516    _conRptTimesheet.print = function() {
11517    	var jrpt = $('table#report-timesheet-day');
11518		
11519		GLO.Report.Template.hideEmptyColumn(jrpt, 'time-column-bonus', true, 'hidePrint');
11520		GLO.Report.Template.hideEmptyColumn(jrpt, 'total_mn', false, 'hidePrint');
11521		
11522		UI.Print.simplePrint(GLO.Report.Timesheet.printOnComplete);
11523    }
11524    _conRptTimesheet.printOnComplete = function() {
11525    	var jrpt = $('table#report-timesheet-day');
11526    	jrpt.find('.hidePrint').removeClass('hidePrint');
11527    }
11528    
11529    function _setWeekDateRange(dt, firstDayOfWeek) {
11530    	var dtStart = GLO.Report.firstDayOfWeek(dt, firstDayOfWeek);
11531    	var dtEnd = new Date(dtStart).addDays(6);
11532    	var dtRange = _conRptTimesheet.getWeekDateRange(dtStart, dtEnd);
11533        
11534        $('.timesheet-search-week #week-date-range').text(dtRange);
11535        return { "begin_dt": dtStart, "end_dt": dtEnd };
11536    }
11537    
11538    _conRptTimesheet.getWeekDateRange = function(dt1, dt2) {
11539    	if (dt1.getMonth() === dt2.getMonth()) {
11540        	var dtRange = dt1.getMonthString(true) + ' ' + dt1.getDate() + ' - ' + dt2.getDate();
11541        } else {
11542        	var dtRange = dt1.getMonthString(true) + ' ' + dt1.getDate() + ' - ' + dt2.getMonthString(true) + ' ' + dt2.getDate();
11543        }
11544        
11545        if (dt2.getFullYear() !== new Date().getFullYear()) { dtRange += ', ' + dt2.getFullYear(); }
11546        return dtRange;
11547    }
11548    
11549    function _approveAll() {
11550    	var jrpt = $('#report-timesheet-day');
11551    	var boxes = jrpt.find('tbody').find('.approve_fl input[type="checkbox"]');
11552    	var allApproved = true;
11553    	
11554    	for (var i=0; i < boxes.length; i++) {
11555	    	if (!boxes.eq(i).prop('checked')) {
11556	    		allApproved = false;
11557	    		break;
11558	    	}
11559    	}
11560    	
11561    	jrpt.find('#Approve_All').prop('checked', allApproved);
11562    }
11563    
11564    _conRptTimesheet.search = function() {
11565        clearTimeout(_timeoutUpdateInProgress);
11566        
11567        var jd = {}, fieldset = $('fieldset.appt-list-search');
11568        var url = GLO.Link.WebsiteDomain + 'report/timesheet?';
11569        
11570        var start = fieldset.find('.Begin_dt').val();
11571        var end = fieldset.find('.End_dt').val();
11572
11573        if (!UTIL.isDate(start)) {
11574            GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .Begin_dt'); });
11575        } else if (!UTIL.isDate(end)) {
11576            GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .End_dt'); });
11577        } else if (new Date(start) > new Date(end)) {
11578            GLO.Popup.Warning(SA.Resource.BeginDateWarning2);
11579            return;
11580        } else if (!GLO.Report.hasTimesheetAccess(jd)) {
11581        	return;
11582        }
11583        
11584        var sfilter = GLO.Uri.query('sfilter');
11585        var vw = fieldset.find('input[name=timesheet-view]:checked').val();
11586        
11587        url += 'sfilter=' + sfilter + '&view=' + vw + '&start=' + start + '&end=' + end;
11588        
11589        var svcId = fieldset.find('.Service_Filter').val();
11590        if (!UTIL.isEmpty(svcId)) { url += '&service=' + svcId; }
11591
11592        try {
11593            window.history.pushState("", "Report Portal", url);
11594        } catch (e) { }
11595        
11596        if (this.toString().indexOf('_conRptTimesheet') === -1) {
11597        	GLO.UI.Form.beginProcessing( $(this) );
11598        }
11599        
11600        url += '&ispartial=1';
11601        
11602        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jd })
11603            .success(function(data, textStatus, jqXHR) {
11604                GLO.UI.Form.resetProcessing();
11605                var jrpt = $('#report-main .report-container');
11606                
11607                if ($(data).hasClass('no-results')) {
11608                	var jhead = $('#timesheet-header');
11609                	
11610                	var dt1 = UTIL.replaceAll(jhead.find('.Begin_dt').val(), '-', '/');			//= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone).
11611                	dt1 = new Date(dt1).toGloDateString(true, true, true, true);
11612                	
11613                	var dt2 = UTIL.replaceAll(jhead.find('.End_dt').val(), '-', '/');			//= JS does NOT handle dates with dashes well (which is what is returned from time picker on mobile phone).
11614                	dt2 = new Date(dt2).toGloDateString(true, true, true, true);
11615                	
11616                	if (GLO.Info.isMobile()) {
11617                		var msg = '<div style="width: 96%; margin: 10px auto; padding-bottom: 20px; line-height: 200%; text-align: center; color: black;">' + SA.Resource.NoResultsFoundForDateRange + '<br/>' + dt1 + ' - ' + dt2 + '</div>';
11618                	} else {
11619                		var msg = '<div style="width: 600px; margin: 32px auto; padding-bottom: 16px; color: black; line-height: 1.4;">' + SA.Resource.NoResultsFoundForDateRange + ' ' + dt1 + ' - ' + dt2 + '</div>';
11620                	}
11621                	
11622                	jrpt.html(msg);
11623                	_postSearchSetHeader();
11624                } else {			// if (!UTIL.isEmpty(data)) {
11625                    jrpt.html(data);
11626                    UI.initTableSorter( $('table.tablesorter:visible') );
11627                    
11628                    if (vw === 'day') {
11629                    	_approveAll();
11630                    	_loadDayTable(false);
11631                    } else if (vw === 'week') {
11632                    	_loadWeekTable();
11633                    }
11634                }
11635                
11636                GLO.Report.enableFullPageCheck();
11637                _postSearchSetHeader();
11638            })
11639            .error(function(jqXHR, textStatus, errorThrown) {
11640                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
11641                GLO.UI.Form.resetProcessing();
11642            });
11643    }
11644    
11645    _conRptTimesheet.openMoreHelp = function(header, helpPath) {
11646    	var htm = '<div class="reset-list">' + $('#timesheet-report').find(helpPath).html() + '</div>';
11647    	GLO.Popup.Info.open(htm, header);
11648    }
11649    
11650    _conRptTimesheet.displayMoreHelp = function(isDisplay) {
11651    	var j = $('#report-header-help');
11652    	var jhelp = j.find('.more-help');
11653    	var jmore = j.find('#timesheet-help-display-more');
11654    	var jless = j.find('#timesheet-help-display-less');
11655    	
11656    	if (isDisplay) {
11657    		jhelp.removeClass('hide');
11658    		jmore.addClass('hide');
11659    		jless.removeClass('hide');
11660    	} else {
11661    		jhelp.addClass('hide');
11662    		jmore.removeClass('hide');
11663    		jless.addClass('hide');
11664    	}
11665    }
11666    
11667    function _saveTimesheetComplete(tr, isApproved, isUnApproved, totalWage, sTimeId) {
11668    	_resetRowCSS(tr, isApproved, isUnApproved, totalWage);
11669    	
11670    	if (isApproved == 0) {
11671    		totalWage = '';
11672    	} else if (UTIL.coalesceMoney(totalWage) > 0) {
11673        	totalWage = '<span title="' + SA.Resource.Saved + '">' + UTIL.displayMoney(totalWage, false, true) + '</span>';
11674        } else if (isApproved == 1) {
11675        	totalWage = '<img src="' + GLO.Data.cdnDirectory + 'image/icon/green-checkbox.png" alt="saved" title="' + SA.Resource.SavedNoHourlyWageSpecified + '" style="height: 25px;"/>';
11676        }
11677        
11678        tr.attr('schedule_timesheet_id', sTimeId);
11679        tr.find('.total_mn').html(totalWage);
11680        
11681        _calculateTotalRow();
11682        _approveAll();
11683        _checkApproveAllStatus();
11684    }
11685    
11686    function _resetRowCSS(tr, isApproved, isUnApproved, totalWage) {
11687    	var css = _getRowCSS(tr, isApproved, isUnApproved, totalWage);
11688    	
11689    	tr.removeClass('timecard-un-approved').removeClass('timecard-good').removeClass('timecard-good-no-wage').removeClass('timecard-no-clock-out').removeClass('timecard-future').removeClass('timecard-no-clock-in');
11690    	tr.addClass(css);
11691    	
11692    	var jcheck = tr.find('td.approve_fl').find('input').parent().removeClass('approve-container').removeClass('un-approve-container');
11693    	
11694    	if (UTIL.parseBool(isApproved)) {
11695    		jcheck.addClass('approve-container');
11696    	} else if (UTIL.parseBool(isUnApproved)) {
11697    		jcheck.addClass('un-approve-container');
11698    	}
11699    	
11700    	var htmRefresh = '<span class="refresh-icon"><b onclick="GLO.Report.Timesheet.refresh()">&#x21bb;</b></span>';
11701        $('#timesheet-summary').find('ul').replaceWith(htmRefresh);
11702    }
11703    
11704    function _getRowCSS(tr, isApproved, isUnApproved, totalWage) {
11705    	if (isUnApproved) {
11706    		return "timecard-un-approved";
11707    	}
11708    	
11709    	var isAutoApproval = ($('#report-timesheet-day').attr('timesheet_type_cd') != 2);
11710    	var hasActual = (UTIL.coalesceInt(UTIL.cleanString(tr.find('.clock-actual-hours').text()).replace(' hours', ''), 0) > 0);
11711    	var hasSchedule = (UTIL.coalesceInt(UTIL.cleanString(tr.find('td.notify-cell-right.clock-scheduled').text()).replace(' hours', ''), 0) > 0);
11712    	
11713    	if ((hasActual && (isApproved || isAutoApproval)) || (isApproved && hasSchedule)) {
11714    		if (totalWage > 0) {
11715    			return "timecard-good";
11716    		} else {
11717				return "timecard-good-no-wage";
11718			}
11719		}
11720		
11721		var day = tr.find('.day-column').text();
11722		var scheduleStart = tr.find('td.notify-cell-left.clock-scheduled').text();
11723		var clockIn = tr.find('.column-actual-start').text();
11724		var clockOut = tr.find('.column-actual-end').text();
11725		
11726		var isFutureTimecard = (UTIL.isEmpty(clockIn) && !UTIL.isEmpty(scheduleStart) && new Date(day + ' ' + scheduleStart) > new Date());
11727		
11728		if (!UTIL.isEmpty(clockIn) && UTIL.isEmpty(clockOut)) {
11729			return "timecard-no-clock-out";
11730		} else if (isFutureTimecard) {
11731			return "timecard-future";
11732		} else if (UTIL.isEmpty(clockIn)) {
11733			return "timecard-no-clock-in";
11734		}
11735    }
11736    
11737    function _calculateTotalRow() {
11738    	var trs = $('#report-timesheet-day tbody tr');
11739    	var bonus = 0, total = 0;
11740    	
11741    	for (var i=0; i < trs.length; i++) {
11742    		bonus += UTIL.coalesceMoney(trs.eq(i).find('.bonus_mn').val());
11743    		total += UTIL.coalesceMoney(trs.eq(i).find('.total_mn').text().replace('$', '').replace(' ', ''));
11744    	}
11745    	
11746    	bonus = UTIL.displayMoney(bonus, false, true);
11747    	total = UTIL.displayMoney(total, false, true);
11748    	
11749    	var tfoot = $('#report-timesheet-day tfoot');
11750    	tfoot.find('#total_bonus_mn').text(bonus);
11751    	tfoot.find('.total_mn').text(total);
11752    }
11753    
11754    _conRptTimesheet.approve = function(checkbox) {
11755        clearTimeout(_timeoutUpdateInProgress);
11756        checkbox = $(checkbox);
11757
11758        if (checkbox.prop('checked')) {
11759            var updStatus = 20;
11760            var orderBy = '1';
11761        } else {
11762            var updStatus = 22;
11763            var orderBy = '0';
11764        }
11765        
11766        var tr = checkbox.closest('tr');
11767        var timesheetId = tr.attr('schedule_timesheet_id');
11768        var scheduleId = tr.attr('schedule_id');
11769        var bonus = tr.find('.bonus_mn').val();
11770    	var fnUncheck = function No() {
11771            checkbox.prop('checked', !checkbox.prop('checked'));
11772        };
11773    	
11774    	if (orderBy == '1' && UTIL.isEmpty(tr.find('.clock-actual-hours').text())) {
11775    		if (!UTIL.isEmpty(tr.find('.clock-scheduled').text())) {
11776	    		var msg = '<div>' + SA.Resource.NoActualHoursExist + '</div>';
11777	    		
11778	    		GLO.Popup.Confirm(msg, function Yes() {
11779	                _conRptTimesheet.approveConfirmed(tr, timesheetId, scheduleId, bonus, updStatus, orderBy);
11780	            }, fnUncheck);
11781	        } else {
11782	        	var msg = 'Please Clock Out ' + tr.find('.staff-column').text();
11783	    		fnUncheck();
11784	    		GLO.Popup.Warning.open(msg, 'No Hours To Approve');
11785	        }
11786    	} else {
11787    		GLO.Report.Timesheet.approveConfirmed(tr, timesheetId, scheduleId, bonus, updStatus, orderBy);
11788    	}
11789    }
11790    
11791    _conRptTimesheet.approveConfirmed = function(tr, timesheetId, scheduleId, bonus, updStatus, isApproved) {
11792        clearTimeout(_timeoutUpdateInProgress);
11793        
11794        var url = GLO.Link.WebsiteDomain + 'report/ApproveClockInOut';
11795        GLO.UI.Form.beginProcessing( $('#timesheet-report .btnSave') );
11796        
11797        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { schedule_timesheet_id: timesheetId, schedule_id: scheduleId, update_status_cd: updStatus, bonus_mn: bonus } })
11798            .success(function(data, textStatus, jqXHR) {
11799                GLO.UI.Form.resetProcessing();
11800                tr.find('.approve_fl').attr('order_by', isApproved);
11801                
11802                var totalWage = $(data).attr('total_wage_mn');
11803                var sTimeId = $(data).attr('schedule_timesheet_id');
11804                
11805                isApproved = UTIL.parseBool(isApproved);
11806                _saveTimesheetComplete(tr, isApproved, !isApproved, totalWage, sTimeId);
11807                
11808                $("table.tablesorter:visible").trigger("update");
11809            })
11810            .error(function(jqXHR, textStatus, errorThrown) {
11811                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
11812            });
11813    }
11814    
11815    _conRptTimesheet.refresh = function() {
11816    	var j = $('#timesheet-report');
11817    	j.find('.btnSearch > a').click();
11818    	GLO.UI.Form.beginProcessing(j.find('.refresh-icon'));
11819    }
11820	
11821	_conRptTimesheet.approveAll = function(isApproveAll) {
11822		var cnt = $('#report-timesheet-day').find('tbody > tr').length;
11823		
11824		if (isApproveAll) {
11825			var h1 = 'Approve All';
11826			var bgcolor = 'rgba(20,255,40, .8)';
11827		} else {
11828			var h1 = 'Un-Approve All';
11829			var bgcolor = 'rgba(255,20,40, .8)';
11830		}
11831		
11832		var msg = '<div style="margin-top: 12px; font-size: 24px; font-weight: bold; color: black;">' + h1 + ' ' + cnt + ' Timecards?</div>';
11833		var fn = function() { GLO.Report.Timesheet.approveAllConfirmed(isApproveAll); }
11834		var jpop = GLO.Popup.Confirm.open(msg, h1, fn).getPopup();
11835		
11836		jpop.css({ "background-color": bgcolor });
11837		jpop.find('.btnNo > a').css({ "padding": "4px 8px", "border": "2px solid black", "border-radius": "20px", "font-weight": "bold", "font-size": "large", "color": "black" });
11838	}
11839	
11840    _conRptTimesheet.approveAllConfirmed = function(isApproveAll) {
11841        clearTimeout(_timeoutUpdateInProgress);
11842        
11843        if (isApproveAll) {
11844            var updStatus = 20;
11845            var orderBy = '1';
11846            var isChecked = true;
11847        } else {
11848            var updStatus = 22;
11849            var orderBy = '0';
11850            var isChecked = false;
11851        }
11852        
11853        var trs = $('#timesheet-report .tablesorter tbody tr');
11854        var warnCount = 0, errorCount = 0;
11855        
11856        if (isChecked) {
11857	        for (var i=0; i < trs.length; i++) {
11858	        	if (UTIL.isEmpty(trs.eq(i).find('.clock-actual-hours').text())) {
11859	        		if (!UTIL.isEmpty(trs.eq(i).find('.clock-scheduled').text())) {
11860	        			++warnCount;
11861	        			trs.eq(i).addClass('highlightWarning2');
11862	        		} else {
11863	        			++errorCount;
11864	        			trs.eq(i).addClass('highlightWarningRed');
11865	        		}
11866	        	}
11867	        }
11868        }
11869        
11870        if (errorCount > 0) {
11871        	var msg = 'Cannot Approve All Timecards because ' + UTIL.pluralLabel(errorCount, 'timecard') + ' has No Scheduled or Actual hours';
11872        	GLO.Popup.Error.open(msg, 'Approve Cancelled');
11873        	
11874        	//$('#timesheet-report .tablesorter tbody tr.highlightWarning2').removeClass('highlightWarning2');
11875        	return;
11876        } else {
11877        	//$('#timesheet-report .tablesorter tbody tr.highlightWarningRed').removeClass('highlightWarningRed');
11878        }
11879        
11880        for (var i=0; i < trs.length; i++) {
11881            trs.eq(i).find(':checkbox').prop('checked', isChecked).parent().attr('order_by', orderBy);
11882        }
11883        
11884        if (warnCount > 0) {
11885        	if (warnCount === 1) {
11886        		var msg = '<div>' + SA.Resource.ApproveScheduleHoursQuestion2 + '</div>';
11887			} else {
11888				var msg = '<div>' + SA.Resource.NoActualHoursExistFor + ' ' + warnCount + ' ' + SA.Resource.Rows.toLowerCase() + '.  ' + SA.Resource.ApproveScheduleHoursQuestion + '?</div>';
11889			}
11890			
11891			GLO.Popup.Confirm(msg, function Yes() {
11892	            $('#timesheet-report .tablesorter tr.highlightWarning2').removeClass('highlightWarning2');
11893	            $("table.tablesorter:visible").trigger("update");
11894	            
11895        		GLO.Report.Timesheet.save(true);
11896	        }, function No() {
11897	            var jrpt = $('#timesheet-report');
11898	            var trs = jrpt.find('.tablesorter tr.highlightWarning2');
11899	            
11900	            for (var i=0; i < trs.length; i++) {
11901	            	trs.eq(i).removeClass('highlightWarning2')
11902	            	trs.eq(i).find(':checkbox').prop('checked', false);
11903	            }
11904	            
11905	            jrpt.find("table.tablesorter:visible").trigger("update");
11906	        	_conRptTimesheet.save(true);
11907	        });
11908        } else {
11909	        $("table.tablesorter:visible").trigger("update");
11910	        _conRptTimesheet.save(true);
11911        }
11912    }
11913    
11914    _conRptTimesheet.updateInProgress = function(element, event) {
11915    	var jinput = $(element);
11916    	
11917    	if (UTIL.coalesceMoney(element.value, 0) === UTIL.coalesceMoney(jinput.attr('startvalue'), 0)) {
11918    		if (jinput.hasClass('unsaved-change')) {
11919    			jinput.removeClass('unsaved-change');
11920    			clearTimeout(_timeoutUpdateInProgress);
11921    		}
11922    		
11923    		return;
11924    	}
11925    	
11926    	clearTimeout(_timeoutUpdateInProgress);
11927    	_timeoutUpdateInProgress = setTimeout(GLO.Report.Timesheet.saveStart, 4800);
11928    	
11929    	var jrpt = $('#timesheet-report');
11930    	 jrpt.find('.btnApproveAll').addClass('hide');
11931    	 jrpt.find('.btnSaveBonus').removeClass('hide');
11932    	
11933    	jinput.addClass('unsaved-change');
11934    }
11935    
11936    function _checkApproveAllStatus() {
11937    	var jrpt = $('#timesheet-report');
11938    	
11939    	if (jrpt.find('#Approve_All').prop('checked')) {
11940    		jrpt.find('.btnApproveAll').addClass('btnUnApprove').find('a').text('Un-Approve All');
11941    	} else {
11942    		jrpt.find('.btnApproveAll').removeClass('btnUnApprove').find('a').text('Approve All');
11943    	}
11944    }
11945    
11946    _conRptTimesheet.saveStart = function(isApproveAll) {
11947    	clearTimeout(_timeoutUpdateInProgress);
11948    	
11949    	if ($('.glopop').length > 0) { return; }
11950    	
11951    	if (isApproveAll) {
11952    		$('#timesheet-report #Approve_All').click();
11953    	} else {
11954    		var bonusChangeCount = $('#timesheet-report').find('.bonus_mn.unsaved-change').length;
11955    		
11956    		if (bonusChangeCount === 0) {
11957    			if (_bonusCount === 0) {
11958    				return;
11959    			} else if (_bonusCount === 1) {
11960    				var msg = 'Remove Bonus?';
11961    			} else {
11962    				var msg = 'Remove Bonuses?';
11963    			}
11964    		} else if (bonusChangeCount === 1) {
11965    			var msg = 'Do you want to Save Bonus?';
11966    		} else {
11967    			var msg = 'Do you want to Save Bonuses?';
11968    		}
11969    		
11970    		GLO.Popup.Confirm.open(msg, 'Save Bonus?', GLO.Report.Timesheet.save);
11971    	}
11972    }
11973    
11974    _conRptTimesheet.save = function() {
11975        clearTimeout(_timeoutUpdateInProgress);
11976        
11977        var tbl = $('#timesheet-report .tablesorter tbody');
11978        var trs = tbl.find('tr');
11979        var sTimeId, bonus, updStatus, xml = '';
11980        
11981        for (var i=0; i < trs.length; i++) {
11982            scheduleId = trs.eq(i).attr('schedule_id');
11983            sTimeId = trs.eq(i).attr('schedule_timesheet_id');
11984            bonus = trs.eq(i).find('.bonus_mn').val();
11985            
11986            if (trs.eq(i).find(':checkbox').prop('checked')) {
11987            	updStatus = 20;
11988            } else {
11989            	updStatus = 22;
11990            }
11991            
11992            xml += "<li schedule_id='" + scheduleId + "' schedule_timesheet_id='" + sTimeId + "' update_status_cd='" + updStatus + "' bonus_mn='" + bonus + "'/>";
11993        }
11994        
11995        xml = UTIL.htmlEncode("<ul>" + xml + "</ul>");
11996        var url = GLO.Link.WebsiteDomain + 'report/SaveTimesheet';
11997        GLO.UI.Form.beginProcessing( $('#timesheet-report .btnSave') );
11998        
11999        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "timesheet_xml": xml } })
12000            .success(function(data, textStatus, jqXHR) {
12001                GLO.UI.Form.resetProcessing();
12002                var tr, isApproved, totalWage, sTimeId;
12003                var list = $(data).find('li');
12004                
12005                for (var i=0; i < list.length; i++) {
12006                	tr = tbl.find('tr[schedule_id="' + list.eq(i).attr('schedule_id') + '"]');
12007                	isApproved = list.eq(i).attr('approved_fl');
12008                	totalWage = list.eq(i).attr('total_wage_mn');
12009                	sTimeId = list.eq(i).attr('schedule_timesheet_id');
12010                	
12011                	_saveTimesheetComplete(tr, isApproved, null, totalWage, sTimeId);
12012                	
12013                	var jTimeHeader = $('#timesheet-header');
12014                	var jDailySearch = jTimeHeader.find('#report-header-search:visible');
12015                	
12016                	if (jDailySearch.length > 0) {
12017                		jDailySearch.click();
12018                	} else {
12019                		//could lookup date in range + call _conRptTimesheet.datePickerOnSelect2(dt), but don't really need to because update button only on daily timesheet.
12020                	}
12021                }
12022            })
12023            .error(function(jqXHR, textStatus, errorThrown) {
12024                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
12025            });
12026    }
12027    
12028    _conRptTimesheet.openApproveSetting = function() {
12029    	var htm1 = '<h4>Change how timecards are approved</h4>' + '<p style="text-align: center;">When a timecard is approved it is included in the payroll report</p>';
12030    	var l1 = '<li> <label> <input type="radio" name="Timesheet_Type_cd" value="1"/>Timecards automatically approved when clocked out</label> </li>';
12031    	var l2 = '<li> <label> <input type="radio" name="Timesheet_Type_cd" value="10"/>Timecards automatically approved when clocked-out; can also un-approve timecards after clock-out or approve scheduled timecards (even if no actual hours, no clock-in/out)</label> </li>';
12032    	var l3 = '<li> <label> <input type="radio" name="Timesheet_Type_cd" value="2"/>Timecards must be approved by manage or admin</label> </li>';
12033    	
12034    	var ul = '<ul class="reset-list" style="margin: 0;">' + l1 + l2 + l3 + '</ul>'
12035    	var htm = '<div id="pop-timecard-approve-setting">' + htm1 + ul + '</div>';
12036    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Change Approval Setting', GLO.Report.Timesheet.saveApproveSetting);
12037    	
12038    	var tt = $('#report-timesheet-day').attr('timesheet_type_cd');
12039    	
12040    	jpop.find('ul input[value="' + tt + '"]').prop('checked', true).closest('label').css({ "font-weight": "bold" }).closest('li').css({ "background-color": "rgba(20,255,80, .4)" });
12041    }
12042    
12043    _conRptTimesheet.saveApproveSetting = function() {
12044        var jpop = $('#pop-timecard-approve-setting').closest('.glopop');
12045        var value = jpop.find('input[name="Timesheet_Type_cd"]:checked').val();
12046        
12047        var url = GLO.Link.WebsiteDomain + 'report/SaveTimesheetSetting';
12048        //GLO.UI.Form.beginProcessing( $('#timesheet-report .btnSave') );
12049        
12050        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "approve": value } })
12051            .success(function(data, textStatus, jqXHR) {
12052                GLO.Popup.close(jpop);
12053                $('#timesheet-header .timesheet-search-day .btnSearch > a').click();
12054                
12055                var msg = '<div>Re-loading Timesheet with new approval setting...</div>';
12056                var ojProcessing = GLO.Popup.Processing.open(msg, 'Timesheet Approve Setting Saved');
12057                
12058                setTimeout(function() {
12059                	ojProcessing.close();
12060                }, 3200);
12061            })
12062            .error(function(jqXHR, textStatus, errorThrown) {
12063                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
12064            });
12065    }
12066    
12067    return _conRptTimesheet;
12068})();
12069
12070
12071GLO.Report.Totalsales = (function() {
12072    function _conRptTotalsales() { }
12073    
12074    _conRptTotalsales.init = function() {
12075        //$('#report-header-search').click(GLO.Report.Totalsales.search);
12076    }
12077
12078    _conRptTotalsales.search = function() {
12079        var fieldset = $('fieldset.appt-list-search');
12080        var url = GLO.Link.WebsiteDomain + 'report/totalsales?';
12081        var start = fieldset.find('.Begin_dt').val();
12082        var end = fieldset.find('.End_dt').val();
12083        
12084        if (!UTIL.isDate(start)) {
12085            GLO.Popup.Warning(SA.Resource.PleaseEnterValidBeginDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .Begin_dt'); });
12086        } else if (!UTIL.isDate(end)) {
12087            GLO.Popup.Warning(SA.Resource.PleaseEnterValidEndDate, function() { GLO.Report.Template.focusDate('fieldset.appt-list-search .End_dt'); });
12088        } else if (new Date(start) > new Date(end)) {
12089            GLO.Popup.Warning(SA.Resource.BeginDateWarning2);
12090            return;
12091        }
12092        
12093        /*
12094        if (GLO.Report.staffFilter !== null) {
12095            var sfilter = GLO.Report.staffFilter;
12096            GLO.Report.staffFilter = null;
12097        } else {
12098            var sfilter = GLO.Uri.query('sfilter');
12099        }
12100        */
12101        
12102        var sfilter = GLO.Uri.query('sfilter');
12103        url += 'sfilter=' + sfilter;
12104        //url += '&view=' + fieldset.find('input[name=timesheet-view]:checked').val();
12105        url += '&start=' + start;
12106        url += '&end=' + end;
12107        
12108        var svcId = fieldset.find('#Service_Filter').val();
12109        if (!UTIL.isEmpty(svcId)) { url += '&service=' + svcId; }
12110        
12111        try {
12112            window.history.pushState("", "Report Portal", url);
12113        } catch (e) { }
12114        
12115        var jBtn = $(this).parent();
12116        GLO.UI.Form.beginProcessing(jBtn);
12117        url += '&ispartial=1';
12118        
12119        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
12120            .success(function(data, textStatus, jqXHR) {
12121                GLO.UI.Form.resetProcessing();
12122                if (!UTIL.isEmpty(data)) {
12123                    $('#report-main').html(data);
12124                    UI.initTableSorter( $('table.tablesorter:visible') );
12125                } else {
12126                    GLO.Popup.Info(SA.Resource.NoResultsFound);
12127                }
12128            })
12129            .error(function(jqXHR, textStatus, errorThrown) {
12130                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
12131                GLO.UI.Form.resetProcessing();
12132            });
12133    }
12134    
12135    return _conRptTotalsales;
12136})();
12137
12138
12139GLO.Report.Cash = (function() {
12140    function _conRptCash() { }
12141    
12142    _conRptCash.init = function() {
12143    	GLO.Info.init();
12144    	
12145    	var jtbl = $('table.tablesorter:visible');
12146    	UI.initTableSorter(jtbl);
12147    	
12148    	$('#report-cash-history').find('.ui-icon-circle-close').click(GLO.Report.Cash.deleteRow);
12149    	
12150    	GLO.Report.enableFullPageCheck();
12151    	GLO.Report.CellSummary.initReport(jtbl, true);
12152    	GLO.Report.initIcons(jtbl);
12153    	_initUrlCashReport();
12154    	$('#doc3').addClass('is-payment-report');
12155    }
12156    function _initUrlCashReport() {
12157    	var popup = UTIL.cleanString(GLO.Uri.url('popup')).toLowerCase();
12158    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
12159    	var jreport = $('#report-cash-history');
12160    	
12161    	if (popup === 'new') {
12162    		GLO.Report.Cash.newEvent()
12163    	} else if (popup === 'change' || popup === 'set-level') {
12164    		jreport.find('#cash-level').click();
12165    	} else if (popup === 'house-only-help') {
12166    		GLO.Report.Cash.helpHouseOnly();
12167    	} else if (popup === 'open') {
12168    		GLO.Report.Cash.openDrawerSetting();
12169    	} else if (popup === 'printer' || popup === 'printer-utility') {
12170    		GLO.Report.Cash.openHelpPrinterSelect();
12171    	}
12172    	
12173    	if (!UTIL.isEmpty(highlight)) {
12174	    	var jhighlight = jreport.find('#' + highlight + ', .' + highlight);
12175			
12176			if (jhighlight.length > 0) {
12177				UI.highlight(jhighlight, 800, 6400, true);
12178			}
12179		}
12180    }
12181
12182	_conRptCash.changeCashDrawerSetting = function (event) {
12183		var cashDrawerSettingCode = $(event.target).val();
12184		if (cashDrawerSettingCode == '5') {
12185			GLO.Report.Cash.displayLocalPrinters();
12186		}
12187		else {
12188			$('#local-printer-selection-container').addClass('hide');
12189			
12190		}
12191	}
12192    
12193    _conRptCash.search = function() {
12194    	var jrpt = $('#report-cash-history');
12195    	var rows = jrpt.find('#Rows_sr').val();
12196    	
12197    	var url = GLO.Link.WebsiteDomain + 'report/cash?search=1&rows=' + rows;
12198    	var jbtn = jrpt.find('.btnSearch');
12199    	var jd = {};
12200    	
12201    	if (!GLO.Report.hasReportPassword(jd)) {
12202	    	return;
12203	    }
12204	    
12205	    GLO.UI.Form.beginProcessing(jbtn);
12206        
12207        var jqxhr = $.ajax({ "type": "POST", "url": url, "cache": false, "data": jd })
12208            .success(function(data, textStatus, jqXHR) {
12209                GLO.UI.Form.resetProcessing();
12210                
12211                if (!UTIL.isEmpty(data)) {
12212                	var cash = UTIL.displayMoney($(data).attr('drawer_amount_mn'), false, false, true);
12213                	var jrpt = $('#report-cash-history');
12214                	
12215                	jrpt.find('#cash-level').text(cash);
12216                	jrpt.find('.report-container').html(data);
12217                    
12218                    GLO.Report.Cash.init();			//UI.initTableSorter( jrpt.find('table.tablesorter:visible') );
12219                } else {
12220                    GLO.Popup.Info(SA.Resource.NoResultsFound);
12221                }
12222            })
12223            .error(function(jqXHR, textStatus, errorThrown) {
12224                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
12225                GLO.UI.Form.resetProcessing();
12226            });
12227    }
12228    
12229    _conRptCash.openDrawerSetting = function() {
12230    	var cd = $('#advanced-setting-open-cash-drawer').attr('cash_drawer_setting_cd');
12231    	var htm = '<div id="pop-advanced-setting-cash-drawer">'
12232                + '<label for="Cash_Drawer_Setting_cd" class="hide">Open Cash Drawer</label>'
12233                + '<select id="Cash_Drawer_Setting_cd" name="Cash_Drawer_Setting_cd" style="width: 90%; max-width: 480px; margin: 12px auto; letter-spacing: 1px;" onChange="GLO.Report.Cash.changeCashDrawerSetting(event)">'
12234                    + '<option value="0">Never Open</option>'
12235                    + '<option value="1">When Print Receipt</option>'
12236                    + '<option value="2">Display Open Cash Drawer Button at Top of Calendar</option>'
12237                    + '<option value="3">Display Open Cash Drawer Button + Require PIN</option>'
12238                    + '<option value="4">Display Open Cash Drawer Button + Require PIN | Print Receipt on Cash Payment</option>'
12239					+ '<option value="5">Display Open Cash Drawer Button + Select Receipt Printer</option>'
12240                + '</select>'
12241				+ '<div id="local-printer-selection-container" class="hide">'
12242				+ '</div>'
12243                + '<div id="cash-drawer-setting-info">'
12244                	+ '<p style="text-align: center;">Requires connecting Cash Drawer to Printer</p>'
12245                	+ '<p><b>Windows/Mac</b> connect your cash drawer to your receipt printer <small>(most receipt printers + cash drawers are compatible)</small></p>'
12246                	+ '<p><b>iPad</b> Connect your Star printer to your Star cash drawer <small>(or a cash drawer that supports the Star emulation)</small></p>'
12247                + '</div>'
12248            + '</div>';
12249        
12250        if ($('#pop-advanced-setting-cash-drawer').closest('.glopop').length) { return; }
12251        
12252        var jpop = GLO.Popup.Custom.openSimple(htm, 'Open Cash Drawer Setting', GLO.Report.Cash.saveDrawerSetting);
12253        //GLO.Popup.Custom.singleButton(jpop, 'Close');
12254        jpop.find('.pop-buttons').css({ "max-width": "560px" });
12255        jpop.find('#Cash_Drawer_Setting_cd').val(cd);
12256		//load local printers if setting is open cash drawer + select printer setting
12257		if (cd == '5') {
12258			GLO.Report.Cash.displayLocalPrinters();
12259		}
12260		else {
12261			$('#local-printer-selection-container').addClass('hide');
12262			
12263		}
12264    }
12265    _conRptCash.saveDrawerSetting = function() {
12266    	var jpop = $('#pop-advanced-setting-cash-drawer').closest('.glopop');
12267    	var jcd = jpop.find('#Cash_Drawer_Setting_cd');
12268    	var htmSaveSuccess = 'Open Cash Drawer: ' + jcd.find(':selected').text();
12269    	
12270    	GLO.Provider.Advanced.saveField(jcd[0], event, htmSaveSuccess);
12271		if (jcd.val() == '5') {
12272			var selectedPrinterName = $('#printerSelect').val();
12273			UTIL.setCookie('_sa_receiptprinter', selectedPrinterName);
12274		}
12275		else {
12276			document.cookie = '_sa_receiptprinter=; Max-Age=0; path=/; domain=' + location.host;
12277		}
12278    	GLO.Popup.close(jpop);
12279    	$('#advanced-setting-open-cash-drawer').attr('cash_drawer_setting_cd', jcd.val());
12280    }
12281    
12282    function _getEventPopup(header, cashid, smid, cash, note, includeNote, saveFunction) {
12283    	var numberInputType = "text";
12284        if (GLO.Info.isAndroid) { numberInputType = "number"; }
12285    	
12286    	var htm = '<div>';
12287    	htm += '<div style="width: 200px; margin: 20px auto;"> <label for="Event_Amount_mn">' + SA.Resource.Amount + '</label>'
12288    			+ '$<input id="Event_Amount_mn" type="' + numberInputType + '" maxlength="9" onkeypress="UI.numberOnly(event, true, false)" value="' + UTIL.cleanString(cash) + '"/>'
12289    		+ '</div>';
12290    		
12291    	if (UTIL.isNumber(cash, true) || note || includeNote) {
12292    		var textareaNote = '<textarea id="Event_Note_vc" placeholder="' + SA.Resource.AddRemoveCashReason + '" maxlength="500">' + UTIL.cleanString(note) + '</textarea>';
12293    		htm += '<div id="cash-event-note">' + textareaNote + '</div>';		// <label for="Event_Note_vc">Note</label> 
12294    	}
12295    	
12296    	htm += '</div>';
12297    	htm = $('<div id="cash-event-popup" cash_id="' + UTIL.cleanString(cashid) + '" schedule_multi_id="' + UTIL.cleanString(smid) + '">' + header + htm + '</div>');
12298    	
12299    	smid = UTIL.coalesce(smid, 'null');
12300    	
12301    	var oj = new GLO.Popup.Custom(htm, saveFunction);
12302    	var jpop = oj.getPopup().addClass('no-persist').attr('id', 'pop-add-remove-cash');
12303    	
12304    	if (!UTIL.isEmpty(cashid)) {
12305    		jpop.find('textarea').css({ "width": "350px", "margin-left": "20px" });
12306    		
12307    		var jbtn = jpop.find('.pop-buttons');
12308    		jbtn.find('.btnSave').css({ "margin-left": "40px" });
12309    		jbtn.append('<span class="btnDelete" style="float: right; width: 100px; font-size: 85%;"> <a onclick="GLO.Report.Cash.deleteEvent(' + cashid + ', ' + smid + ')">' + SA.Resource.Delete + '</a> </span>');
12310    	} else if (!GLO.Info.isMobile()) {
12311    		var jbtn = jpop.find('.pop-buttons').addClass('pop-buttons2');			//.css({ "width": "300px" });
12312    		jbtn.append('<span class="btnRemoveCash btnAdd btn">
12312<a onclick="GLO.Report.Cash.removeCash()">Remove Cash</a></span>');
12313    		
12314    		jbtn.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "margin": "0" }).find('> a').css({ "letter-spacing": "1px" });		//"margin-left": "25px"
12315    		jbtn.find('.btnSave').addClass('btnAddCash').find('> a').text('Add Cash');								//"margin-left": "50px"
12316    	}
12317        
12318        jpop.find('h1').css({ "letter-spacing": "1px" });
12319        //UI.initAutoComplete(jpop.find('#Event_Amount_mn'), GLO.Report.Cash.saveEvent);
12320        return jpop;
12321    }
12322    
12323    _conRptCash.removeCash = function() {
12324    	var jpop = $('#cash-event-popup').closest('.glopop');
12325		var cash = UTIL.coalesceMoney(jpop.find('#Event_Amount_mn').val());
12326    	
12327    	if (cash > 0) {
12328    		jpop.find('#Event_Amount_mn').val('-' + cash);
12329    	}
12330    	
12331    	jpop.find('.btnSave > a').click();
12332    }
12333    
12334    _conRptCash.setLevel = function(element) {
12335    	var header = '<h1 class="change-cash-level">' + SA.Resource.ChangeCashLevel + '</h1>';
12336    	var cash = UTIL.displayMoney($(element).text().replace('$', ''), true);
12337    	var jpop = _getEventPopup(header, null, null, cash, null, false, GLO.Report.Cash.save);
12338    }
12339    
12340    _conRptCash.newEvent = function() {
12341    	var header = '<h1 class="new-event">' + SA.Resource.AddRemoveCash + '</h1>';
12342    	var jpop = _getEventPopup(header, null, '', null, '', true, GLO.Report.Cash.saveEvent);
12343    }
12344    
12345    _conRptCash.openEvent = function(element, cashid, smid) {
12346    	var tr = $(element).closest('tr');
12347    	var cash = tr.find('.payment').text().replace('$', '');
12348    	var note = tr.find('.payment-note').text();
12349    	
12350    	var header = '<h1 class="edit-cash-event">' + SA.Resource.EditCashTransaction + '</h1>';
12351    	var jpop = _getEventPopup(header, cashid, smid, cash, note, true, GLO.Report.Cash.saveEvent);
12352    }
12353    
12354    _conRptCash.deleteEvent = function(cashid, smid, label) {
12355    	var label = UTIL.coalesceString(label, SA.Resource.DeleteCashTransactionConfirm);
12356    	var css = 'width: 90%; height: 40px; margin-left: 11px; line-height: 150%;';
12357    	var pcss = 'letter-spacing: 1px; line-height: 1.8; font-size: larger; font-weight: bold; color: Red;';
12358    	
12359    	var htm = '<form cash_id="' + UTIL.cleanString(cashid) + '" schedule_multi_id="' + UTIL.cleanString(smid) + '"><p style="' + pcss + '">' + label + '</p>'
12360                    + '<textarea id="Delete_Reason_vc" name="Delete_Reason_vc" class="defaultText" maxlength="2000" rows="2" title="' + SA.Resource.IncludeNoteHelp + '" style="' + css + '"> </textarea>'
12361                + '</form>';
12362    	
12363    	GLO.Popup.Confirm('<div id="cash-event-popup">' + htm + '</div>', GLO.Report.Cash.deleteEventConfirmed);
12364    }
12365    
12366    _conRptCash.deleteRow = function() {
12367    	var icon = $(this);
12368    	var label = icon.attr('title');
12369    	var tr = icon.closest('tr');
12370    	var cashId = tr.attr('cash_id'), smid = tr.attr('schedule_multi_id');
12371    	var jPayDate = tr.find('.rpt-cash-pay-date'), jPayAmount = tr.find('.payment');
12372    	
12373    	if (jPayDate.length > 0 && jPayAmount.length > 0) {
12374    		if (jPayDate.find('a').length > 0) { jPayDate = jPayDate.find('a'); }
12375    		
12376    		label += '<div style="margin-top: 12px; text-align: center;"> <b style="padding-right: 4px;">' + jPayDate.text() + '</b> <b>' + jPayAmount.text() + '</b></div>';
12377    	}
12378    	
12379    	_conRptCash.deleteEvent(cashId, smid, label);
12380    }
12381    
12382    _conRptCash.deleteEventConfirmed = function(jform) {
12383    	var url = GLO.Link.WebsiteDomain + 'report/CashDeleteEvent';
12384    	var cashid = jform.attr('cash_id');
12385    	var smid = jform.attr('schedule_multi_id');
12386    	var reason = UTIL.htmlEncode(jform.find('#Delete_Reason_vc').val());
12387    	var jd = { "cash_id": cashid, "schedule_multi_id": smid, "delete_reason_vc": reason };
12388    	
12389    	if (!GLO.Report.hasReportPassword(jd)) {
12390	    	return false;
12391	    }
12392	    
12393	    var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
12394            .success(function(data, textStatus, jqXHR) {
12395                if (GLO.Report.hasReportPasswordWarning(data)) {
12396                	return false;
12397                }
12398                
12399                var cash = $('#cash-event-popup #Event_Amount_mn').val();
12400                UserPortal.Price.Receipt.openCashDrawer(cash, ' (delete)');
12401                
12402                GLO.Report.Cash.search();
12403                GLO.Popup.close();
12404                new GLO.Popup.Success(SA.Resource.CashTransactionSuccessfullyDeleted);
12405            })
12406            .error(function(jqXHR, textStatus, errorThrown) {
12407                new GLO.Popup.Error('Unable to delete.  Please try again');
12408            });
12409    }
12410    
12411    _conRptCash.saveEvent = function() {
12412    	var jpop = $('#cash-event-popup').closest('.glopop');
12413    	var url = GLO.Link.WebsiteDomain + 'report/CashEditEvent';
12414    	
12415    	var cashid = jpop.find('#cash-event-popup').attr('cash_id');
12416    	var smid = jpop.find('#cash-event-popup').attr('schedule_multi_id');
12417    	var note = UTIL.htmlEncode(UTIL.cleanString(jpop.find('#Event_Note_vc').val()));
12418    	var cash = String(jpop.find('#Event_Amount_mn').val()).replace(',', '');
12419    	
12420    	if (cash.indexOf('(') !== -1 && cash.indexOf(')') !== -1) {
12421    		cash = '-' + cash.replace('(', '').replace(')', '');
12422    	}
12423    	
12424    	var jd = { "payment_mn": cash, "payment_note_vc": note, "schedule_multi_id": smid, "cash_id": cashid };
12425    	
12426    	if (!UTIL.isNumber(cash, true)) {
12427    		if (cash.indexOf('(') > -1 && (cash.indexOf(')') + 1) === cash.length) {			//= user entered parentheses to indicate negative number.
12428    			cash = cash.replace('(', '').replace(')', '');
12429    			
12430    			if (UTIL.coalesceMoney(cash) > 0) { cash = -cash; }
12431    		}
12432    		
12433    		if (!UTIL.isNumber(cash, true)) {
12434	    		var style = 'style="margin-bottom: 0; padding-top: 6px; letter-spacing: 2px;"';
12435	    		var msg = '<div> <h1 ' + style + '>Invalid Amount</h1> <div ' + style + '>Cash Amount Must Be A Number</div></div>';
12436	    		new GLO.Popup.Warning(msg, function() { $('#cash-event-popup #Event_Amount_mn').focus(); });
12437	    		return;
12438	    	}
12439    	}
12440    	
12441    	if (!GLO.Report.hasReportPassword(jd)) {
12442	    	return;
12443	    }
12444    	
12445    	var jsave = jpop.find('.btnSave');
12446    	GLO.UI.Form.beginProcessing(jsave);
12447    	
12448    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
12449            .success(function(data, textStatus, jqXHR) {
12450                if (GLO.Report.hasReportPasswordWarning(data)) {
12451                	return;
12452                }
12453                
12454                UserPortal.Price.Receipt.openCashDrawer(cash);
12455                
12456                GLO.Report.Cash.search();
12457                GLO.Popup.close();
12458                new GLO.Popup.Success(SA.Resource.CashTransactionSuccessfullySaved);
12459            })
12460            .error(function(jqXHR, textStatus, errorThrown) {
12461                GLO.UI.Form.resetProcessing();
12462                new GLO.Popup.Error('Unable to save.  Please try again');
12463            });
12464    }
12465    
12466    _conRptCash.save = function() {
12467    	var jpop = $('#cash-event-popup').closest('.glopop');
12468    	var url = GLO.Link.WebsiteDomain + 'report/CashSave';
12469    	var note = UTIL.htmlEncode(UTIL.cleanString(jpop.find('#Event_Note_vc').val()));
12470    	
12471    	var newCashLevel = jpop.find('#Event_Amount_mn').val();
12472    	
12473    	if (newCashLevel.indexOf('(') !== -1 && newCashLevel.indexOf(')') !== -1) {
12474    		newCashLevel = '-' + newCashLevel.replace('(', '').replace(')', '');
12475    	}
12476    	
12477    	newCashLevel = UTIL.coalesceMoney(newCashLevel.replace(',', ''), 0);
12478    	
12479    	var currentCashLevel = UTIL.coalesceMoney($('#report-cash-header #cash-level').text().replace('$', ''), 0);
12480    	var cash = UTIL.coalesceMoney(newCashLevel - currentCashLevel);
12481    	
12482    	var jd = { "cash_mn": cash, "update_note_vc": note };
12483    	
12484    	if (!GLO.Report.hasReportPassword(jd)) {
12485	    	return;
12486	    }
12487	    
12488	    if (jpop.find('#drawer-config').length === 1) {
12489    		jd.all_product_fl = jpop.find('#all_product_fl').prop('checked');
12490    		jd.all_service_fl= jpop.find('#all_service_fl').prop('checked');
12491    		jd.all_tip_fl = jpop.find('#all_tip_fl').prop('checked');
12492    	}
12493    	
12494    	var jsave = jpop.find('.btnSave');
12495    	GLO.UI.Form.beginProcessing(jsave);
12496    	
12497    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
12498            .success(function(data, textStatus, jqXHR) {
12499                UserPortal.Price.Receipt.openCashDrawer(cash, ' (' + SA.Resource.Update.toLowerCase() + ')');
12500                
12501                GLO.Popup.close();
12502                GLO.Report.Cash.search();
12503                new GLO.Popup.Success(SA.Resource.CashLevelSuccessfullyChanged);
12504            })
12505            .error(function(jqXHR, textStatus, errorThrown) {
12506                GLO.UI.Form.resetProcessing();
12507                new GLO.Popup.Error('Unable to change the cash level at this time.  Please try again');
12508            });
12509    }
12510    
12511    function _getHouseOnlyInfo(useHeader) {
12512    	var msg1 = 'When Enabled: Only cash payments for products and staff using your house merchant account are included in the cash drawer';
12513    	var msg2 = 'This feature is useful if only some of your staff use the house account and some are independent contractors who collect payment independently';
12514    	var htm = '<p>' + msg1 + '</p> <p style="letter-spacing: 0; line-height: 1.4; font-size: smaller;">' + msg2 + '</p>';
12515    	
12516    	if (useHeader) {
12517    		htm = '<h3>House Only Cash Drawer</h3>' + htm;
12518    	}
12519    	
12520    	return htm;
12521    }
12522    _conRptCash.helpHouseOnly = function() {
12523    	var htm = _getHouseOnlyInfo(false);
12524    	GLO.Popup.Info.open(htm, 'House Only Cash Drawer');
12525    }
12526    _conRptCash.changeHouseOnly = function() {
12527    	var jHouseOnly = $('#advanced-payment-cash-house-only #Cash_House_Only_fl');
12528    	var isHouseOnly = jHouseOnly.prop('checked');
12529    	var url = GLO.Link.WebsiteDomain + 'provider/manage/CashHouseOnly?ishouse=' + isHouseOnly;
12530    	var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99);
12531    	
12532    	if (mt > 79) {
12533    		var msg1 = '<p style="line-height: 1.2; padding-bottom: 0; font-weight: bold; color: red;">Merchant Account Required for this feature</p>';
12534    		var msg2 = '<p style="padding-left: 2px; line-height: 1.4; font-size: smaller;">
12534This is how ' + GLO.Info.getScheduleAnyoneHtm() + ' knows which staff are using the house account</p>';
12535    		
12536    		var msg3 = '<p>' + _getHouseOnlyInfo(true) + '</p>';
12537    		var htm = msg1 + msg2 + msg3;
12538    		
12539    		GLO.Popup.Warning.open(htm, 'House Only Cash Drawer');
12540    		
12541    		jHouseOnly.prop('checked', false);
12542    		return;
12543    	} else if (mt < 10 && isHouseOnly) {
12544    		var msg1 = '<p style="margin-top: 12px; padding-bottom: 0; line-height: 1.2; font-weight: bold; color: red;">Enabling Multi-Merchant Required for this feature</p>';
12545    		var msg2 = '<p style="padding-left: 2px; letter-spacing: 0; line-height: 1.4;">This is how ' + GLO.Info.getScheduleAnyoneHtm() + ' knows which staff are using the house account</p>';
12546    		
12547    		var msg3 = '<p>' + _getHouseOnlyInfo(true) + '</p>';
12548    		var msg4 = '<p style="margin-top: 24px; padding-bottom: 0; line-height: 1; font-size: larger; font-weight: bold; color: green;">Would you like us to enable multi-merchant?</p>';
12549    		var msg5 = '<p style="letter-spacing: 0; line-height: 1.4; font-size: smaller; color: green;">This is free, after we enable you just must set which staff use the house account</p>';
12550    		var htm = msg1 + msg2 + msg3 + msg4 + msg5;
12551    		
12552    		var jpop = GLO.Popup.Confirm.open(htm, 'House Only Cash Drawer', GLO.Report.Cash.enableMultiMerchant).getPopup();
12553    		jpop.find('.btnYes').find('>a').text('Yes, Enable Multi-Merchant');
12554    		
12555    		jHouseOnly.prop('checked', false);
12556    		return;
12557    	}
12558    	
12559    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
12560            .success(function(data, textStatus, jqXHR) {
12561                GLO.Popup.Success.open('House Account Only changed to: ' + isHouseOnly, 'House Only Cash Drawer');
12562            })
12563            .error(function(jqXHR, textStatus, errorThrown) { });
12564    }
12565    _conRptCash.enableMultiMerchant = function() {
12566    	var url = GLO.Link.WebsiteDomain + 'provider/manage/CashHouseOnly?ishouse=1';
12567    	$('#advanced-payment-cash-house-only #Cash_House_Only_fl').prop('checked', true);
12568    	
12569    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
12570            .success(function(data, textStatus, jqXHR) {
12571                var msg1 = '<p>House Account Only changed to: true</p>';
12572                var msg2 = '<p style="color: green;">We will contact you to confirm as soon as Multi-Merchant is Enabled</p>';
12573                
12574                GLO.Popup.Success.open(msg1 + msg2, 'House Only Cash Drawer');
12575            })
12576            .error(function(jqXHR, textStatus, errorThrown) { });
12577    }
12578
12579	_conRptCash.openHelpPrinterSelect = function() {
12580		var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;';
12581		var title = '<p style="' + css1 + '">Setup Cash drawer to open only when <b class="narrow-text">Open Cash Drawer</b> button is clicked or <b class="narrow-text">Cash</b> payment method is selected on a ticket</p>';
12582		var sa = GLO.Info.getScheduleAnyoneHtm();
12583		
12584		var pctCustom = '<i class="narrow-text">(currently <b class="narrow-text">only MUNBYN</b> receipt printers are supported on Windows PC)</i>';
12585		
12586		var hPct = '<h3>Receipt Printer Settings - Windows</h3>';
12587		var msgPct = '<p> Configure receipt printer settings for cash drawer open' + pctCustom + '</p>';
12588		var videoPct = '<video controls controlsList="nodownload" muted width="800"><source src="' + GLO.Data.cdnDirectory + 'image/faq/printer/munbyn-cashbox-none.mp4" type="video/mp4">Your browser does not support the video tag</video>';
12589		
12590		var hDollar = '<h3>Download & Install ' + sa + ' Printer Utility - Windows</h3>';
12591		var msgDollar = '<p>Our Printer Utility is a lightweight app that runs on your Windows PC and allows ' + sa + ' to directly communicate with your receipt printer</p>';
12592		var downloadSAPrintUtility = '<a style="margin-bottom:20px;font-weight:bold;" href="' + GLO.Data.cdnDirectory + 'image/faq/printer/SetupSAClientServer.msi"">Download SA Print Utility</a>';
12593		var videoDollar = '<video controls controlsList="nodownload" muted width="800" style="margin-top:20px;"><source src="' + GLO.Data.cdnDirectory + 'image/faq/printer/install-sa-print-utility.mp4" type="video/mp4">Your browser does not support the video tag.</video>';
12594
12595		var hDollar2 = '<h3>Launch ' + sa + ' Printer Utility after reboot - Windows</h3>';
12596		var msgDollar2 = '<p>Use these instructions to setup SA Printer Utility to launch automatically after computer reboots</p>';
12597		var videoDollar2 = '<video controls controlsList="nodownload" muted width="800" style="margin-top:20px;"><source src="' + GLO.Data.cdnDirectory + 'image/faq/printer/launch-sa-utility-at-startup.mp4" type="video/mp4">Your browser does not support the video tag</video>';
12598
12599		var htm = '<div id="pop-help-tip-percent-or-dollar">' + title + hDollar + msgDollar + downloadSAPrintUtility + videoDollar + hPct + msgPct + videoPct  + hDollar2 + msgDollar2 + videoDollar2 + '</div>';
12600		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Configure Cash Drawer open settings', null, null, true);
12601		var jpop = ojpop.getPopup();
12602		
12603		jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" });
12604		GLO.Popup.Custom.singleButton(jpop);
12605		ojpop.realign();
12606		
12607		if (GLO.Info.isMobile(true)) {
12608			setTimeout(function() { ojpop.realign(); }, 900);
12609		} else {
12610			jpop.css({ "top": "40px" });
12611		}
12612	}
12613
12614	_conRptCash.displayLocalPrinters = function() {
12615		var $printSelectHelpIcon = '<b class="help-icon4" onclick="GLO.Report.Cash.openHelpPrinterSelect()" title="Open cash drawer only for cash payments">?</b>';
12616		//CHECK IF COOKIE EXISTS
12617		var selectedReceiptPrinterFromCookie = SA.ClientServer.getReceiptPrinterFromCookie();
12618
12619		SA.ClientServer.checkApiStatus()
12620		.then(isRunning => {
12621			if (isRunning) {
12622				console.log('Web application can use API');
12623				SA.ClientServer.getLocalPrinters()
12624				.then(printersArray => {
12625					if (printersArray.length > 0) {
12626						console.log('display local printers');
12627						$('#local-printer-selection-container').removeClass('hide');
12628						var $printerSelectLabel = $('<label for="printerSelect">Select Receipt Printer: </label>')
12629						var $printerSelect = $("<select id='printerSelect'></select>");
12630						printersArray.forEach(item=> {
12631							$printerSelect.append($('<option>', { 
12632								value: item.name,
12633								text : item.name 
12634							}));
12635						});
12636						$('#local-printer-selection-container').empty();
12637						$('#local-printer-selection-container').append($printerSelectLabel);
12638						$('#local-printer-selection-container').append($printerSelect);
12639						$('#local-printer-selection-container').append($printSelectHelpIcon);
12640						if (selectedReceiptPrinterFromCookie) {
12641							$printerSelect.val(selectedReceiptPrinterFromCookie);
12642						}
12643						
12644					}
12645					else {
12646						console.log('Cannot display local printers');
12647						$('#local-printer-selection-container').removeClass('hide');
12648						var $printerNotFound = $('<span style="color:red">No printers found</span>');
12649						$('#local-printer-selection-container').empty();
12650						$('#local-printer-selection-container').append($printerNotFound);
12651						$('#local-printer-selection-container').append($printSelectHelpIcon);
12652					}
12653				})
12654			}
12655			else {
12656				console.log('Cash drawer option disabled, API unavailable');
12657				var $printerNotFound = $('<span style="color:red">No printers found. Check if Printer Utility is installed.</span>');
12658				$('#local-printer-selection-container').removeClass('hide');
12659				$('#local-printer-selection-container').empty();
12660				$('#local-printer-selection-container').append($printerNotFound);
12661				$('#local-printer-selection-container').append($printSelectHelpIcon);
12662			}
12663		})
12664	}
12665
12666	_conRptCash.openDrawer = function() {
12667
12668		//CHECK IF COOKIE EXISTS
12669		var selectedReceiptPrinterFromCookie = SA.ClientServer.getReceiptPrinterFromCookie();
12670
12671		SA.ClientServer.checkApiStatus()
12672		.then(isRunning => {
12673			if (isRunning) {
12674				console.log('Web application can use API');
12675				SA.ClientServer.postOpenDrawer(selectedReceiptPrinterFromCookie)
12676				.then(response => {
12677					if (response == 'success') {
12678						console.log('open drawer success');
12679					}
12680					else {
12681						console.log('could not open drawer');
12682					}
12683				})
12684			}
12685			else {
12686				console.log('Cash drawer option disabled, API unavailable');
12687			}
12688		})
12689	}
12690    
12691    return _conRptCash;
12692})();
12693
12694
12695GLO.Report.TicketHistory = (function() {
12696    function _conRptTicket() { }
12697    
12698    _conRptTicket.init = function() {
12699    	var jtbl = $('table.tablesorter:visible');
12700    	var jhead = $('.report-search-header');
12701    	
12702    	UI.initTableSorter(jtbl);
12703    	
12704        for (var i=0; i < jhead.length; i++) {
12705            jhead.eq(i).find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 });
12706            jhead.eq(i).find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths() });
12707        }
12708        
12709        var ifilter = UTIL.coalesceString(GLO.Uri.query('inventoryfilter'), GLO.Uri.query('ifilter'));
12710        var by = _initGroupBy();
12711        
12712        jhead.find('.Inventory_Filter').val(ifilter).find('option[value="-1"]').remove();
12713        
12714        _displayHeaderInfo(by);
12715        _setHeading(jhead, ifilter);
12716        
12717        if (!GLO.Report.Sales.initStaffFilter()) {
12718        	GLO.Report.Template.initStaffFilter();
12719        }
12720        
12721        GLO.Staff.Filter.isReportPortal = true;
12722        GLO.Report.portalName = 'ticket';
12723        GLO.Report.CellSummary.initReport(jtbl, true, true);
12724        GLO.Report.initIcons(jtbl);
12725        GLO.Report.setupFastClick();
12726        
12727        _initSingleClient();
12728        _conRptTicket.loadColumns(jtbl);
12729        GLO.Report.initUrlAction();
12730    }
12731    
12732    _conRptTicket.loadColumns = function(jtbl) {
12733    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-staff');
12734    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-service');
12735    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-product');
12736    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-price');
12737    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-payment');
12738    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-note');
12739    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-checkin');
12740    	GLO.Report.hideEmptyColumn(jtbl, 'ticket-column-checkout');
12741    	
12742    	var colCount = jtbl.find('tbody > tr:first td:not(.hideX)').length;
12743    	var jrpt = jtbl.closest('.report-container').addClass('column-count-' + colCount);
12744    	
12745    	if (colCount > 11) {
12746    		jrpt.addClass('ticket-history-very-wide');
12747    	} else if (colCount > 9) {
12748    		jrpt.addClass('ticket-history-wide');
12749    	}
12750    }
12751    
12752    function _initSingleClient() {
12753    	var j = $('#report-ticket-history');
12754    	var jclient = j.find('#Client_Filter_id');
12755    	
12756    	if (jclient.length > 0) {
12757    		UI.initAutoComplete(jclient, GLO.Link.Object.Provider.ClientSearch);
12758    		
12759    		var cname = j.find('#ticket-history-report tbody > tr:first').find('.ticket-column-buyer > a').text();
12760    		
12761    		if (!UTIL.isEmpty(cname)) {
12762    			jclient.val(cname).attr('autoId', GLO.Uri.query('client'));
12763    		} else {
12764    			new GLO.Popup.Info.openSimple('No tickets found for client that match the search parameters', 'No Tickets Found');
12765    		}
12766    	}
12767    }
12768    
12769    function _initGroupBy() {
12770    	var j = $('#group-by');
12771    	
12772    	var pm = GLO.Uri.query('pay-method');
12773    	if (!UTIL.isEmpty(pm)) { j.val('pm' + pm); return 'pm'; }
12774    	
12775    	var as = GLO.Uri.query('appt-status');
12776    	if (!UTIL.isEmpty(as)) { j.val('as' + as); return 'as'; }
12777    	
12778    	var ct = GLO.Uri.query('client-type');
12779    	if (!UTIL.isEmpty(ct)) { j.val('ct' + ct); return 'ct'; }
12780    	
12781    	var tw = GLO.Uri.query('ticket-with');
12782    	if (!UTIL.isEmpty(tw)) { j.val('tw' + tw); return 'tw'; }
12783    	
12784    	var pr = GLO.Uri.query('referral');
12785    	if (!UTIL.isEmpty(pr)) { j.val('pr' + pr); return 'pr'; }
12786    	
12787    	var pd = GLO.Uri.query('discount');
12788    	if (!UTIL.isEmpty(pd)) { j.val('pd' + pd); return 'pd'; }
12789    	
12790    	var ad = GLO.Uri.query('addon');
12791    	if (!UTIL.isEmpty(ad)) { j.val('ad' + ad); return 'ad'; }
12792    	
12793    	var sg = GLO.Uri.query('service-group');
12794    	if (!UTIL.isEmpty(sg)) { j.val('sg' + sg); return 'sg'; }
12795    	
12796    	var iv = GLO.Uri.query('vendor');
12797    	if (!UTIL.isEmpty(iv)) { j.val('iv' + iv); return 'iv'; }
12798    	
12799    	var ic = GLO.Uri.query('product-category');
12800    	if (!UTIL.isEmpty(ic)) { j.val('ic' + ic); return 'ic'; }
12801    	
12802    	var it = GLO.Uri.query('product-type');
12803    	if (!UTIL.isEmpty(it)) { j.val('it' + it); return 'it'; }
12804    }
12805    
12806    function _displayHeaderInfo(by) {
12807    	$('#ticket-header-referral-info, #ticket-header-discount-info, #ticket-header-addon-info').addClass('hide');
12808    	
12809    	if (by === 'pr') {
12810    		$('#ticket-header-referral-info').removeClass('hide');
12811    	} else if (by === 'pd') {
12812    		$('#ticket-header-discount-info').removeClass('hide');
12813    	} else if (by === 'ad') {
12814    		$('#ticket-header-addon-info').removeClass('hide');
12815    	}
12816    }
12817    
12818    function _setHeading(jhead, ifilter) {
12819    	var lbl = $('#group-by :selected').text();
12820    	
12821    	if (UTIL.isEmpty(lbl) && !UTIL.isEmpty(ifilter)) {
12822        	lbl = $.trim(jhead.find('.Inventory_Filter').find('option:selected').text());
12823    	}
12824    	
12825    	$('#ticket-history-title-span').text(lbl + ' ' + SA.Resource.TicketHistory);
12826    	
12827    	_addOtherParameterToHelp();
12828    	GLO.Report.enableFullPageCheck();
12829    }
12830    
12831    function _getGroupBy(gby) {
12832    	var dos = gby.substring(0, 2);
12833    	gby = gby.substring(2);
12834    	
12835    	_displayHeaderInfo(gby);
12836    	
12837    	if (dos === 'pm') {
12838    		return '&pay-method=' + gby;
12839    	} else if (dos === 'as') {
12840    		return '&appt-status=' + gby;
12841    	} else if (dos === 'ct') {
12842    		return '&client-type=' + gby;
12843    	} else if (dos === 'tw') {
12844    		return '&ticket-with=' + gby;
12845    	} else if (dos === 'pr') {
12846    		return '&referral=' + gby;
12847    	} else if (dos === 'pd') {
12848    		return '&discount=' + gby;
12849    	} else if (dos === 'ad') {
12850    		return '&addon=' + gby;
12851    	} else if (dos === 'sg') {
12852    		return '&service-group=' + gby;
12853    	} else if (dos === 'iv') {
12854    		return '&vendor=' + gby;
12855    	} else if (dos === 'ic') {
12856    		return '&product-category=' + gby;
12857    	} else if (dos === 'it') {
12858    		return '&product-type=' + gby;
12859    	} else {
12860    		return '';
12861    	}
12862    }
12863    
12864    function _getOtherParameters() {
12865    	var minstaff = GLO.Uri.query('minstaff');
12866    	var minservice = GLO.Uri.query('minservice');
12867    	var minproduct = GLO.Uri.query('minproduct');
12868    	var mindiscount = GLO.Uri.query('mindiscount');
12869    	var minservicediscount = GLO.Uri.query('minservicediscount');
12870    	
12871    	return { "minstaff": minstaff, "minservice": minservice, "minproduct": minproduct, "mindiscount": mindiscount, "minservicediscount": minservicediscount };
12872    }
12873    
12874    function _keepOtherParameters() {
12875    	var json = _getOtherParameters();
12876    	var qs = '';
12877    	
12878    	if (!UTIL.isEmpty(json.minstaff)) { qs += '&minstaff=' + json.minstaff; }
12879    	if (!UTIL.isEmpty(json.minservice)) { qs += '&minservice=' + json.minservice; }
12880    	if (!UTIL.isEmpty(json.minproduct)) { qs += '&minproduct=' + json.minproduct; }
12881    	if (!UTIL.isEmpty(json.mindiscount)) { qs += '&mindiscount=' + json.mindiscount; }
12882    	if (!UTIL.isEmpty(json.minservicediscount)) { qs += '&minservicediscount=' + json.minservicediscount; }
12883    	
12884    	return qs;
12885    }
12886    
12887    function _addOtherParameterToHelp() {
12888    	var json = _getOtherParameters();
12889    	var msg = '';
12890    	
12891    	if (!UTIL.isEmpty(json.minstaff)) { msg += _addOtherParameterItemToHelp('staff', json.minstaff, false); }
12892    	if (!UTIL.isEmpty(json.minservice)) { msg += _addOtherParameterItemToHelp('Service', json.minservice, true); }
12893    	if (!UTIL.isEmpty(json.minproduct)) { msg += _addOtherParameterItemToHelp('Product', json.minproduct, true); }
12894    	if (!UTIL.isEmpty(json.mindiscount)) { msg += _addOtherParameterItemToHelp('Discount', json.mindiscount, true); }
12895    	if (!UTIL.isEmpty(json.minservicediscount)) { msg += _addOtherParameterItemToHelp('Service Discount', json.minservicediscount, true); }
12896    	
12897    	if (msg !== '') {
12898    		var msg = '<ul id="report-header-help-other-param">' + msg + '</ul>';
12899    		$('#report-header-help-text').append(msg);
12900    	}
12901    }
12902    
12903    function _addOtherParameterItemToHelp(minLabel, minValue, allowPlural) {
12904    	if (allowPlural) {
12905    		minLabel = UTIL.pluralLabel(minValue, minLabel);
12906    	}
12907    	
12908    	var queryKey = 'min' + minLabel.toLowerCase().replace(' ', '');
12909    	var iconRemove = '<span class="report-header-help-remove" onclick="GLO.Report.TicketHistory.removeOtherParam(this, \'' + queryKey + '\')">&#10006;</span>';
12910    	
12911    	return '<li>' + iconRemove + '<i>and ticket has at least ' + minValue + ' ' + minLabel + '</i></li>';
12912    }
12913    
12914    _conRptTicket.removeOtherParam = function(icon, queryKey) {
12915    	GLO.Uri.removeQueryKey(queryKey);
12916    	$(icon).closest('li').remove();
12917    	
12918    	GLO.Report.TicketHistory.search();
12919    }
12920    
12921    _conRptTicket.changeUrl = function(qs, title) {
12922    	if (window.history.pushState) {
12923    		//var htm = $('body').outerHTML();
12924    		var url = window.location.origin + window.location.pathname + '?' + qs;
12925		    
12926		    //window.history.pushState({"html": htm, "pageTitle": "Ticket History" } , "", url);
12927		    window.history.pushState({ "pageTitle": title } , "", url);
12928    	}
12929    }
12930    
12931    _conRptTicket.gotoReport = function(event, url, element) {
12932    	if (event && event.target && element === undefined) {
12933    		element = event.target;
12934    	}
12935    	
12936    	GLO.Uri.gotoReport(url, element, null, null, null, event);
12937    	return;
12938    	
12939    	var sfilter = GLO.Uri.query('sfilter');
12940    	
12941    	if (!UTIL.isEmpty(sfilter)) { url += '&sfilter=' + sfilter; }
12942    	
12943    	if (SA.Menu.isRequirePIN(url, null, event)) {
12944    		return false;
12945    	}
12946    	
12947    	if (event.ctrlKey) {
12948    		url = document.location.protocol + '//' + document.location.host + url;
12949    		var childWindow = UI.openChildWindow(url, '', true);
12950    	} else {
12951    		setTimeout(function() {
12952    			document.location = url;
12953    		}, 100);
12954    	}
12955    }
12956    
12957    _conRptTicket.search = function(isExportToExcel) {
12958    	var jrpt = $('#report-ticket-history');
12959    	var begin = jrpt.find('.Begin_dt').val();
12960    	var end = jrpt.find('.End_dt').val();
12961    	
12962    	var gby = jrpt.find('#group-by').val();
12963    	var ifilter = jrpt.find('.Inventory_Filter').val();
12964    	var other = _keepOtherParameters();
12965    	var jd = {}, qs = 'start=' + begin + '&end=' + end + other;
12966    	
12967    	if (!GLO.Report.hasReportPassword(jd)) {
12968	    	return;
12969	    }
12970    	
12971    	if (!UTIL.isEmpty(gby)) { 
12972    		qs += _getGroupBy(gby);
12973    	} else if (!UTIL.isEmpty(ifilter)) {
12974    		qs += '&ifilter=' + ifilter;
12975    	}
12976    	
12977    	var sfilter = GLO.Uri.query('sfilter');
12978    	if (!UTIL.isEmpty(sfilter)) { qs += '&sfilter=' + sfilter; }
12979    	
12980    	var jclient = jrpt.find('#Client_Filter_id');
12981    	if (!UTIL.isEmpty(jclient.val())) { qs += '&client=' + jclient.attr('autoId'); }
12982    	
12983    	qs += GLO.Message.Bulk.getTagQueryString(jrpt);
12984    	
12985    	var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?search=1&' + qs;
12986    	setTimeout(function() { GLO.Report.TicketHistory.changeUrl(qs, SA.Resource.TicketHistory); }, 50);
12987    	
12988    	if (isExportToExcel) {
12989        	var btnExport = jrpt.parent().find('.btnExportToExcel');
12990        	GLO.UI.Form.beginProcessing(btnExport);
12991        	
12992        	window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 4500);
12993        	
12994        	url += '&ExportToExcel=1';
12995        	var childWindow = UI.openChildWindow(url, '', true);
12996        	
12997        	return;
12998        } else {
12999        	var jbtn = jrpt.find('.btnSearch');
13000    		GLO.UI.Form.beginProcessing(jbtn);
13001        }
13002    	
13003        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jd })
13004            .success(function(data, textStatus, jqXHR) {
13005                GLO.UI.Form.resetProcessing();
13006                
13007                if (!UTIL.isEmpty(data)) {
13008                	jrpt.find('.report-container').html(data);
13009                    var jtbl = jrpt.find('table.tablesorter:visible');
13010                    
13011                    UI.initTableSorter(jtbl);
13012                    GLO.Report.CellSummary.initReport(jtbl, true, true);
13013                    GLO.Report.initIcons(jtbl);
13014                    _conRptTicket.loadColumns(jtbl);
13015                } else {
13016                    GLO.Popup.Info(SA.Resource.NoResultsFound);
13017                }
13018                
13019                var jhead = $('.report-search-header');
13020                _setHeading(jhead, ifilter);
13021            })
13022            .error(function(jqXHR, textStatus, errorThrown) {
13023                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
13024                GLO.UI.Form.resetProcessing();
13025            });
13026    }
13027    
13028    function _helpColorMessage(label) {
13029    	return '<p>The color indicates the ' + label + ' status</p>';
13030    }
13031    function _openHelpColorPopup(htm, h1) {
13032    	var jpop = GLO.Popup.Custom.openSimple(htm, h1);
13033    	GLO.Popup.Custom.singleButton(jpop, 'Close');
13034    	return jpop;
13035    }
13036    _conRptTicket.helpDateColor = function() {
13037    	var msg = _helpColorMessage('Appointment Status');
13038    	
13039    	var aOnclick = 'GLO.FAQ.gotoQuestion(\'calendar-appt-icons\', \'tips\', this, event)';
13040    	var aIcon = '<a onclick="' + aOnclick + '" style="font-weight: bold" title="What do the icons on appointments mean?">FAQ: Appointment Icons</a>';
13041    	var labelIcon = '<span class="narrow-text">Information about the different icons</span>';
13042    	var htmIconInfo = '<div style="margin-bottom: 24px; padding: 6px;">' + labelIcon + ' <b class="arrow-right">&#10140;</b> ' + aIcon + '</div>';
13043    	
13044    	var htm = '<div id="pop-info-ticket-history-color">' + msg + '<ul>'
13045	        		+ '<li class="ticket-column-date-checkin">Appointment Status = Checked-In</li>'
13046	        		+ '<li class="ticket-column-date-checkout">Appointment Status = Checked-Out</li>'
13047	        		+ '<li class="ticket-column-date-noshow">Appointment Status = No Show</li>'
13048	        		+ '<li class="ticket-column-date-latecancel">Appointment Status = Late Cancelation</li>'
13049        		+ '</ul>' + htmIconInfo + '</div>';
13050    	
13051    	_openHelpColorPopup(htm, 'Appointment Status Color');
13052    }
13053    _conRptTicket.helpPaymentColor = function() {
13054    	var msg = _helpColorMessage('Payment');
13055    	var htm = '<div id="pop-info-ticket-history-color">' + msg + '<ul>'
13056	        		+ '<li class="ticket-column-price-paid">Ticket Fully Paid</li>'
13057	        		+ '<li class="ticket-column-price-partial-paid">Ticket Partially Paid</li>'
13058	        		+ '<li class="ticket-column-unpaid">Ticket Un-Paid</li>'
13059	        	+ '</ul></div>';
13060	    _openHelpColorPopup(htm, 'Payment Color');
13061    }
13062    _conRptTicket.helpApptStatusColor = function(isCheckout) {
13063    	if (isCheckout) {
13064    		var word = 'Check-Out';
13065    	} else {
13066    		var word = 'Check-In';
13067    	}
13068    	
13069    	var msg = _helpColorMessage(word);
13070    	var htm = '<div id="pop-info-ticket-history-color">' + msg + '<ul>'
13071	        		+ '<li class="checkin-ontime">' + word + ' On Time <small></small></li>'
13072        			+ '<li class="checkin-barely-late">' + word + ' Barely Late <small>(less than 5 minutes late)</small></li>'
13073        			+ '<li class="checkin-slightly-late">' + word + ' Slightly Late <small>(more than 5 minutes late)</small></li>'
13074        			+ '<li class="checkin-late">' + word + ' Late <small>(more than 15 minutes late)</small></li>'
13075        			+ '<li class="checkin-very-late">' + word + ' Very Late <small>(more than 1 hour late)</small></li>'
13076        			+ '<li class="checkin-extremely-late">' + word + ' Extremely Late <small>(more than 2 hours late)</small></li>';
13077        		+ '</ul></div>';
13078        _openHelpColorPopup(htm, word + ' Color');
13079    }
13080    
13081	return _conRptTicket;
13082})();
13083
13084
13085GLO.Report.Other = (function() {
13086    function _conRptOther() { }
13087    
13088    _conRptOther.init = function() {
13089    	GLO.Staff.Filter.isReportPortal = true;
13090    	GLO.Info.init();
13091    	GLO.Report.Template.initStaffFilter();
13092    	
13093    	var jtbls = $('.tablesorter');
13094        
13095        for (var i=0; i < jtbls.length; i++) {
13096            UI.initTableSorter( jtbls.eq(i) );			//$('#report-main .tablesorter')
13097        }
13098        
13099        GLO.Report.setupFastClick();
13100        _conRptOther.initWithSearch();
13101        _initData(jtbls);
13102        _initHelloBar();
13103        _initInventoryFilter();
13104        GLO.Report.enableFullPageCheck();
13105        
13106        _initPaymentIncorrect();
13107        _conRptOther.initUrl();
13108    }
13109    _conRptOther.initIncorrect = function() {
13110    	_conRptOther.init();
13111    	
13112    	if (GLO.Info.isMobile() && GLO.Info.roleType > 209) {
13113    		var jstaff = $('#hd-mobile #staff-filter');
13114    		
13115    		if (jstaff.find('option[value="all"]').length === 0) {
13116    			jstaff.prepend('<option value="all" title="All staff members">ALL</option>');
13117    			
13118    			if (UTIL.isEmpty(GLO.Uri.url('highlight'))) {
13119    				jstaff.find('option[value="all"]').prop('selected', true);
13120    			}
13121    		}
13122    	}
13123    }
13124    _conRptOther.initUrl = function() {
13125    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
13126    	
13127		if (!UTIL.isEmpty(highlight)) {
13128			var jhighlight = $('#' + highlight + ', .' + highlight);
13129			
13130			if (jhighlight.length > 0) {
13131				UI.highlight(jhighlight, 800, 6400, true);
13132			}
13133		}
13134    }
13135    function _initInventoryFilter() {
13136    	var ifilter = GLO.Uri.query('inventoryfilter');
13137        
13138        if (!UTIL.isEmpty(ifilter)) {
13139        	$('.report-search-header .inventory-filter').val(ifilter);
13140        }
13141    }
13142    
13143    function _initHelloBar() {
13144    	var sfilter = GLO.Uri.query('sfilter');
13145        
13146        if (UTIL.coalesce(sfilter, 'all') != 'all') {
13147        	GLO.Report.setStaffHelloBar(sfilter);
13148        }
13149    }
13150    
13151    _conRptOther.initWithSearch = function() {
13152    	GLO.Staff.Filter.isReportPortal = true;
13153    	var jhead = $('.report-search-header');
13154    	
13155        for (var i=0; i < jhead.length; i++) {
13156            jhead.eq(i).find('input[type=text].Report_Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), showCurrentAtPos: 1 });
13157            jhead.eq(i).find('input[type=text].Report_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths() });
13158        }
13159        
13160        //$('#report-portal-header').removeClass('hide');
13161        //_conRptTemplate.initStaffFilter();
13162    }
13163    
13164    function _initData(jtbls) {
13165    	for (var i=0; i < jtbls.length; i++) {
13166    		GLO.Report.CellSummary.initReport(jtbls.eq(i), true, true);
13167    		GLO.Report.initIcons(jtbls.eq(i));
13168    	}
13169    }
13170    
13171    function _initPaymentIncorrect() {
13172    	if ($('#report-header-help-incorrect-payment').length === 0) { return; }
13173    	
13174    	GLO.Report.portalName = 'incorrect-payment';
13175    	
13176    	setTimeout(function() {
13177    		$('.shadow-content0 h1 .fa-refresh').click();
13178    	}, 900);
13179    }
13180    
13181    function _setUrl(uri, title) {
13182    	window.history.pushState('', '', uri);
13183    	
13184    	if (title) {
13185    		document.title = title;
13186    	}
13187    }
13188    
13189    _conRptOther.search = function(button, isExportToExcel) {
13190    	var jd = {}, jrpt = $('#report-main');
13191    	var uri = location.origin + location.pathname + '?';
13192    	button = $(button);
13193    	
13194    	if (button.hasClass('fa-spin')) {
13195    		return;
13196    	} else if (!GLO.Report.hasReportPassword(jd)) {
13197	    	return;
13198	    }
13199	    
13200    	if (button.hasClass('fa')) {
13201    		button.addClass('fa-spin');
13202    	} else {
13203    		GLO.UI.Form.beginProcessing(button.parent());
13204    	}
13205    	
13206    	var jRptHeader = $('.report-search-header:visible');
13207    	var qstring = '', sfilter = GLO.Uri.query('sfilter'), days = 
13207UTIL.cleanString(GLO.Uri.query('days')), ifilter = UTIL.cleanString($('.report-search-header .inventory-filter').val());
13208    	
13209    	if (GLO.Report.portalName === 'incorrect-payment') {
13210    		if (!UTIL.isEmpty(days)) { uri += '&days=' + days; }
13211    	} else {
13212    		jrpt.css({ "text-align": "center" }).html( $('#imgThrobber').outerHTML() );
13213    		jrpt.find('#imgThrobber').css({ "margin": "30px" });
13214    	}
13215    	
13216    	if (jRptHeader.length > 0) {
13217    		var start = jRptHeader.find('.Report_Begin_dt').val();
13218    		if (UTIL.isDate(start)) { qstring += '&start=' + new Date(start).toGloDate(true); }
13219    		
13220    		var end = jRptHeader.find('.Report_End_dt').val();
13221    		if (UTIL.isDate(end)) { qstring += '&end=' + new Date(end).toGloDate(true); }
13222    	}
13223    	
13224    	if (!UTIL.isEmpty(sfilter)) {
13225    		qstring += '&sfilter=' + sfilter;
13226    	}
13227    	
13228    	if (!UTIL.isEmpty(ifilter)) {
13229    		qstring += '&inventoryfilter=' + ifilter;
13230    	}
13231    	
13232    	if (isExportToExcel) {
13233    		qstring += '&ExportToExcel=1';
13234    	}
13235    	
13236    	var jqxhr = $.ajax({ type: "POST", url: uri + qstring + '&ispartial=1', "cache": false, "data": jd })
13237            .success(function(data, textStatus, jqXHR) {
13238                button.removeClass('fa-spin');
13239                GLO.UI.Form.resetProcessing();
13240                
13241                var jdata = $(data);
13242                jrpt.html( jdata.html() );
13243                
13244                var tbl = jrpt.find('.tablesorter');
13245                if (tbl.length > 0) { UI.initTableSorter(tbl); }
13246                
13247                _initData(tbl);
13248                _setUrl(uri + qstring);
13249                GLO.Report.enableFullPageCheck();
13250            })
13251            .error(function(jqXHR, textStatus, errorThrown) {
13252            	button.removeClass('fa-spin');
13253            	GLO.UI.Form.resetProcessing();
13254            	
13255            	if (jrpt.find('.incorrect-payment-report').length) {
13256            		button.remove();
13257            	} else {
13258	            	var htm = '<div style="padding: 20px 0; text-align: center; line-height: 200%; letter-spacing: 1px;">Unable to load report</br>Please try again</div>';
13259	            	jrpt.html(htm);
13260            	}
13261            });
13262    }
13263    
13264    return _conRptOther;
13265})();
13266
13267
13268GLO.Report.StaffSummary = (function() {
13269	function _conStaffSum() {}
13270    
13271    _conStaffSum.init = function(startDay, endDay) {
13272		GLO.Report.Template2.init('staff-summary', startDay, endDay);
13273		$('#report-main').find('.btnSearch > a').click();
13274    }
13275    
13276    _conStaffSum.searchComplete = function(jrpt, data) {
13277    	GLO.Report.Template2.searchCompleteFade(jrpt, data);
13278    	GLO.Report.CellSummary.initReport(jrpt, true, true);
13279    	
13280    	setTimeout(function() {
13281    		$('#report-staff-summary.report-container .tablesorter thead tr:last-child .column-staff').click();			//sort by staff name
13282    	}, 150);
13283    	
13284    	_hideClientRequestColumn();
13285    }
13286    
13287    function _hideClientRequestColumn() {
13288    	if (!GLO.Data.displayClientRequest) {
13289			var jrpt = $('#report-staff-summary');
13290			var jtrHead = jrpt.find('thead > tr');
13291			jrpt.find('.column-client-request').addClass('hide');
13292			
13293			_changeColumnSpan(jtrHead.eq(0).find('.column-client-top'), -1);
13294			_changeColumnSpan(jtrHead.eq(1).find('.column-client-top'), -1);
13295		}
13296    }
13297    
13298    function _changeColumnSpan(jtd, diff) {
13299    	var colspan = parseInt(jtd.attr('colspan'));
13300    	jtd.attr('colspan', colspan + diff);
13301    }
13302    
13303    _conStaffSum.openClientRequestHelp = function() {
13304    	var h1 = 'When is Appointment marked as a Client Request?';
13305    	
13306    	var roleList = 'The staff roles <i>Limited-Receptionist</i>, <i>Receptionist</i>, <i>Manager</i>, and <i>Admin</i>';
13307    	var htmArrow = ' &#10140; ';
13308    	var seeHowLink = '<a onclick="GLO.Provider.Advanced.Help.Calendar.openDisplayClientRequest()">see how</a>';
13309    	var li1 = roleList + ' can assign whether the client requested the staff when creating or editing the appointment' + htmArrow + seeHowLink;
13310    	
13311    	var li2 = 'If other staff roles create an appointment for themselves on a day in the future that appointment is set as a client request';
13312    	var li3 = 'When a client books online, if the client specifically searches for a specific staff member, then that staff is set as a client request';
13313    	
13314    	var ul = '<ul> <li>' + li1 + '</li> <li>' + li2 + '</li> <li>' + li3 + '</li> </ul>';
13315    	var htm = '<div id="pop-client-request-info">' + ul + '</div>';
13316    	
13317    	GLO.Popup.Info.open(htm, h1).getPopup().css({ "background-color": "rgba(230, 248, 255)" });
13318    }
13319    
13320    return _conStaffSum;
13321})();
13322
13323
13324GLO.Report.StaffSummaryDetail = (function() {				//= Staff Goal Report
13325	function _conStaffSumDetail() {}
13326	var _isInitComplete = false, _isInitialPageLoad = true;
13327	var _searchRequest = null;
13328    
13329    _conStaffSumDetail.init = function() {
13330		GLO.Staff.Filter.isReportPortal = true;
13331		GLO.Report.portalName = 'staff-summary-detail';
13332		
13333		if (!GLO.Report.Sales.initStaffFilter()) {
13334			GLO.Report.Template.initStaffFilter(true);
13335		}
13336		
13337		var jrpt = $('#report-staff-summary-detail');
13338        var jhead = $('.report-search-header');
13339        
13340        jhead.find('#Start_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
13341                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths()
13342                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect });
13343        jhead.find('#End_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
13344                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths()
13345                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect });
13346        
13347        jhead.find('#Start_Week_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
13348                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths()
13349                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect });
13350        jhead.find('#End_Week_d').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, firstDay: (GLO.Data.firstWeekDay - 1)
13351                , calculateWeek: UTIL.datePickerCalculateWeek, beforeShow: GLO.Report.datePickerBeforeShow, numberOfMonths: UI.getDatepickerMonths()
13352                , onChangeMonthYear: GLO.Report.datePickerOnChange, onSelect: GLO.Report.datePickerOnSelect });
13353        
13354		jhead.find('#Start_Month_d').Monthpicker();
13355		jhead.find('#End_Month_d').Monthpicker();
13356		
13357		var period = GLO.Uri.query('period');
13358		_conStaffSumDetail.setPeriod(period);
13359		
13360		_initDisplayEndDate();
13361		_initOtherFilter();
13362		
13363		GLO.Report.setupFastClick();
13364		GLO.Report.StaffSummaryDetail.search();
13365		
13366		$('#bd #report-main .open-help-arrow:visible').click();
13367    }
13368    function _initOtherFilter() {
13369    	if (UTIL.parseBool($.cookies.get('Only_Paid_fl'))) {
13370    		$('#staff-goal-filter-other').find('#Only_Paid_fl').prop('checked', true);
13371    	}
13372    	
13373    	if (UTIL.parseBool($.cookies.get('Only_Clocked_In_Hours_fl'))) {
13374    		$('#staff-goal-filter-other').find('#Only_Clocked_In_Hours_fl').prop('checked', true);
13375    	}
13376    }
13377    function _initDisplayEndDate() {
13378    	var dtEnd = GLO.Uri.query('end');
13379    	
13380    	if (UTIL.isDate(dtEnd)) {
13381    		$('#staff-summary-detail-header').find('.date-cell.end-cell').removeClass('hide');
13382    	}
13383    }
13384    function _initGoals(jrpt) {
13385    	var tfoot = jrpt.find('tfoot');
13386    	var goalId = tfoot.attr('staff_goal_id');
13387    	
13388    	if (GLO.Info.roleType > 219) {				//= is manager
13389			var btnSave = '<span class="btnEditGoals btnSave"> <a onclick="GLO.Report.StaffSummaryDetail.editGoal(this)">Change</a></span>';
13390			tfoot.find('tr.report-goal-row').find('td.column-period, td.column-goal').append(btnSave);
13391			tfoot.find('input').on('change', function() {
13392				$(this).closest('tr').find('.btnEditGoals').addClass('btn-has-change');
13393			});
13394			
13395			if (tfoot.find('.report-goal-row').length > 1) {
13396				tfoot.find('tr.report-goal-row').find('.column-staff').on('mousedown', GLO.Report.StaffSummaryDetail.enableSort);
13397				$('#report-staff-summary-detail').addClass('allow-sort');
13398			}
13399		} else {
13400			tfoot.find(':text').prop('disabled', true);
13401		}
13402    }
13403    
13404    function _initSortGoals(tfoot) {
13405    	var jrpt = $('#report-staff-summary-detail').addClass('enable-sort-goal');
13406    	jrpt.find('tfoot tr.report-goal-row').find('.column-staff').off('mousedown', GLO.Report.StaffSummaryDetail.enableSort); 
13407    	
13408    	jrpt.find('tfoot').sortable({
13409			handle: 'td.column-staff'
13410			, items: 'tr.report-goal-row'
13411			, change: function(event, ui) {
13412				var test = 123;
13413			}
13414			, update: function(event, ui) {
13415				var goalId = ui.item.attr('staff_goal_id');
13416				var trs = $('#report-staff-summary-detail-data tfoot').find('tr.report-goal-row');
13417				var xml = '';
13418				
13419				for (var i=0; i < trs.length; i++) {
13420					var goalId = trs.eq(i).attr('staff_goal_id');
13421					xml += '<tr goal_id="' + goalId + '"></tr>';
13422					
13423					if (UTIL.isEmpty(goalId)) {
13424						var msg = '<div id="pop-warn-unsaved-goal-level">Please Save New Goal Level before sorting</div>';
13425						var fn = function() { UI.highlight(trs.eq(i)); }
13426						
13427						GLO.Popup.Warning.open(msg, 'Un-Saved New Goal Level', fn);
13428						return
13429					}
13430				}
13431				
13432				_updateGoalOrder('<table>' + xml + '</table>');
13433			}
13434			/*
13435			, start: function (event, ui) {
13436				//$('#report-staff-summary-detail-data').css({ "margin-left": 0 });
13437				//$('#report-staff-summary-detail-data tr.report-goal-row-multi .ui-sortable-handle').css({ "position": "static" });
13438				//$('#report-staff-summary-detail-data tr.report-goal-row-multi .btnEditGoals > a').css({ "visibility": "hidden", "display": "none" });
13439			}
13440			, stop: function (event, ui) {
13441				//if (!_isValidOrderChange(ui)) { $(this).sortable('cancel'); }
13442				
13443				//$('#report-staff-summary-detail-data').css({ "margin-left": "" });
13444				//$('#report-staff-summary-detail-data tr.report-goal-row-multi .ui-sortable-handle').css({ "position": "" });
13445				//$('#report-staff-summary-detail-data tr.report-goal-row-multi .btnEditGoals > a').css({ "visibility": "", "display": "" });
13446			}
13447			*/
13448		});
13449    }
13450    _conStaffSumDetail.helpOnlyClockedInHours = function() {
13451    	var aHrs = '<a class="narrow-text" onclick="GLO.Report.StaffSummaryDetail.highlightHoursPerDay()" style="font-weight: bold; color: #139ad2;">Hours Per Day section</a>';
13452    	
13453    	var h1 = '<h4>Only Clocked-In Hours</h4>';
13454    	var msg1 = '<p>' + aHrs + ' only counts hours when staff is clocked-in</p>';
13455    	
13456    	var h2 = '<h4 style="margin-top: 36px;">Hour Available on Calendar</h4>';
13457    	var msg2 = '<p>' + aHrs + ' counts hours staff is available on the calendar</p>';
13458    	
13459    	var htm = '<div id="pop-help-clocked-in-only">' + h1 + msg1 + h2 + msg2 + '</div>';
13460    	GLO.Popup.Info.openSimple(htm, 'Hours Per Day', GLO.Report.StaffSummaryDetail.highlightHoursPerDay);
13461    }
13462    _conStaffSumDetail.highlightHoursPerDay = function() {
13463    	var jhrs = $('#report-staff-summary-detail').find('.column-time');
13464    	UI.highlight(jhrs, 100, 9500);
13465    }
13466    _conStaffSumDetail.enableSort = function() {
13467    	var jpop = GLO.Popup.Success.open('Drag the Goal Name up or down to change the sort order', 'Sort Goal Level Enabled').getPopup();
13468    	jpop.css({ "max-width": "400px", "min-width": "280px", "line-height": "1.4" });
13469    	jpop.find('.msg').css({ "padding-right": "8px" });
13470    	jpop.find('.friendly-responsive').css({ "line-height": "1.4" });
13471    	//GLO.Popup.Custom.singleButton(jpop, 'Close');
13472    	
13473    	_initSortGoals();
13474    }
13475    function _isValidOrderChange(ui) {
13476    	if (!ui.item.hasClass('report-goal-row')) {
13477    		return false;
13478    	} else {
13479    		return true;
13480    	}
13481    }
13482    
13483    function _updateGoalOrder(xml) {
13484    	var goalXml = UTIL.htmlEncode(xml);
13485    	var url = GLO.Link.WebsiteDomain + 'report/StaffGoalOrder';
13486		
13487        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "goal_xml": goalXml } })
13488            .success(function(data, textStatus, jqXHR) {
13489                var test = data;
13490            })
13491            .error(function(jqXHR, textStatus, errorThrown) {
13492                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
13493            });
13494    }
13495    
13496    function _loadGoalCss(isReset) {
13497    	var tbl = $('#report-staff-summary-detail-data');
13498    	tbl.find('.goal-met').removeClass('goal-met');
13499    	tbl.find('.goal-close').removeClass('goal-close');
13500    	tbl.find('.goal-far').removeClass('goal-far');
13501    	
13502    	_setColumnGoalStatus('column-count-client', tbl);
13503		_setColumnGoalStatus('column-count-service', tbl);
13504		_setColumnGoalStatus('column-count-product', tbl);
13505		
13506		_setColumnGoalStatus('column-sales-total-service', tbl);
13507		_setColumnGoalStatus('column-sales-total-tip', tbl);
13508		_setColumnGoalStatus('column-sales-total-product', tbl);
13509		_setColumnGoalStatus('column-product-to-service', tbl);
13510		
13511		_setColumnGoalStatus('column-service-request', tbl);
13512		_setColumnGoalStatus('column-existing', tbl);
13513		_setColumnGoalStatus('column-pre-book', tbl);
13514		
13515		_setColumnGoalStatus('column-days-worked', tbl);
13516		_setColumnGoalStatus('column-hours-available', tbl);
13517		_setColumnGoalStatus('column-hours-worked', tbl);
13518		_setColumnGoalStatus('column-hours-worked-percent', tbl);
13519		
13520		_setColumnGoalStatus('column-ticket-avg-total', tbl);
13521		_setColumnGoalStatus('column-ticket-avg-service', tbl);
13522		_setColumnGoalStatus('column-ticket-avg-product', tbl);
13523		
13524		_setColumnGoalStatus('column-daily-avg-ticket-count', tbl);
13525		_setColumnGoalStatus('column-daily-avg-service-sales', tbl);
13526		_setColumnGoalStatus('column-daily-avg-product-sales', tbl);	
13527    }
13528    
13529    function _setColumnGoalStatus(columnClass, tbl) {
13530    	var tds = tbl.find('tbody td.' + columnClass);
13531    	var tfoot = tbl.find('tfoot');
13532    	var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl'));
13533    	var goal = $.trim(tfoot.find('td.' + columnClass + ' input[type="text"]').val()).replace(',', '');
13534    	
13535    	for (var i=0; i < tds.length; i++) {
13536    		var val = tds.eq(i).text().replace('$', '').replace(',', '').replace('%', '');
13537    		
13538    		if (!isSingleStaff) {
13539	    		var goalid = tds.eq(i).closest('tr').attr('staff_goal_id');
13540	    		goal = $.trim(tfoot.find('tr[staff_goal_id="' + goalid + '"]').find('td.' + columnClass + ' input[type="text"]').val()).replace(',', '');
13541	    	}
13542    		
13543    		if (UTIL.isNumber(val) && UTIL.isNumber(goal)) {
13544    			val = parseFloat(val);
13545    			goal = parseFloat(goal);
13546    			
13547    			if (val >= goal) {
13548    				tds.eq(i).addClass('goal-met');
13549    			} else if (val >= goal * .9) {
13550    				tds.eq(i).addClass('goal-close');
13551    			} else if (val < goal/2) {
13552    				tds.eq(i).addClass('goal-far');
13553    			}
13554    		}
13555    	}
13556    }
13557    
13558    function _loadPeriod() {
13559    	var isDailyReport = $('.report-search-header #view-period-daily').prop('checked');
13560    	var isWeeklyReport = $('.report-search-header #view-period-weekly').prop('checked');
13561    	var isMonthlyReport = $('.report-search-header #view-period-monthly').prop('checked');
13562    	var trs = $('#report-staff-summary-detail tfoot tr.report-goal-row');
13563    	
13564    	for (var i=0; i < trs.length; i++) {
13565    		var tr = trs.eq(i);
13566    		
13567    		var isDailyGoal = UTIL.parseBool(tr.attr('period_vc') == 'day');
13568			var isWeeklyGoal = UTIL.parseBool(tr.attr('period_vc') == 'week');
13569			var isMonthlyGoal = UTIL.parseBool(tr.attr('period_vc') == 'month');
13570			
13571	    	if (isMonthlyReport && isWeeklyGoal) {				//= change goals to monthly
13572	    		var adjust = 4.25;
13573	    	} else if (isMonthlyReport && isDailyGoal) {		//= change goals to monthly
13574	    		var adjust = 4.25 * 7;
13575	    	} else if (isWeeklyReport && isMonthlyGoal) {		//= change goals to weekly
13576	    		var adjust = 1/4.25;
13577	    	} else if (isWeeklyReport && isDailyGoal) {			//= change goals to weekly
13578	    		var adjust = 7;
13579	    	} else if (isDailyReport && isWeeklyGoal) {			//= change goals to daily
13580	    		var adjust = 1/7;
13581	    	} else if (isDailyReport && isMonthlyGoal) {		//= change goals to daily
13582	    		var adjust = 1/(4.25 * 7);
13583	    	} else {
13584	    		var adjust = null;
13585	    	}
13586    		
13587    		if (adjust > 0) {
13588    			_loadPeriod2(tr, adjust);
13589    		}
13590    	}
13591    }
13592    
13593    function _loadPeriod2(tr, ratio) {
13594    	var jgoals = tr.find('input[type="text"]');
13595    	
13596    	for (var i=0; i < jgoals.length; i++) {
13597    		var val = jgoals.eq(i).val().replace(',', '');
13598    		
13599    		if ((val >= 425 && ratio < 1) || (val >= 100 && ratio >
13599 1)) {
13600    			val = Math.round(val * ratio);
13601    		} else {
13602    			val = Math.round(val * ratio, 1);
13603    		}
13604    		
13605    		if (val >= 1000) {
13606    			val = UTIL.displayMoney(val, true, false, true);
13607    		}
13608    		
13609    		jgoals.eq(i).val(val);
13610    	}
13611    }
13612    
13613    _conStaffSumDetail.changeActiveStaffOnly = function(element) {
13614    	UI.highlightStaffFilter();
13615    	$('#staff-summary-detail-header').find('.btnSearch > a').click();
13616    }
13617    _conStaffSumDetail.setFilterOption = function(element) {			//previously: changePaidOnly()
13618    	if (element.type == 'checkbox') {
13619    		if (element.checked) {
13620    			UTIL.setCookie(element.id, '1');
13621    		} else {
13622    			UTIL.setCookieWithExpire(element.id, null);
13623    		}
13624    	}
13625    	
13626    	//$('#staff-summary-detail-header').find('.btnSearch > a').click();
13627    }
13628    _conStaffSumDetail.setPer = function(element) {
13629    	var j = $('#report-main');
13630    	var jhead = j.find('#staff-summary-detail-header');
13631    	var period = jhead.find('input[name="view-period"]:checked').val()
13632    	
13633    	_conStaffSumDetail.setPeriod(period);
13634    	UI.highlightStaffFilter();
13635    }
13636    _conStaffSumDetail.setPeriod = function(period, isReload) {
13637    	var j = $('#report-main');
13638    	var jhead = j.find('#staff-summary-detail-header');
13639    	var jPerLabel = j.find('#report-search-header-per-period').find('label');
13640    	
13641    	var isDisplayEndDate = (jhead.find('input[name="filter-per"]:checked').val() === 'period' || UTIL.parseBool(j.find('tfoot').attr('is_single_staff_fl')));
13642    	var jend = $('#staff-summary-detail-header').find('.date-cell.end-cell');
13643    	
13644    	if (period === 'day' || period === 'daily') {
13645			j.removeClass('month-view').removeClass('week-view').addClass('day-view');
13646			jPerLabel.text('Day');
13647			
13648			jhead.find('#view-period-daily').prop('checked', true);
13649			//jhead.find('.monthpicker').addClass('hide');					//css
13650			//jhead.find('#Start_d, #End_d').removeClass('hide');			//css
13651			//jhead.find('#week-start-help').addClass('hide');				//css
13652		} else if (period === 'week' || period === 'weekly') {
13653			j.removeClass('month-view').removeClass('day-view').addClass('week-view');
13654			jPerLabel.text('Week');
13655			
13656			jhead.find('#view-period-weekly').prop('checked', true);
13657			//jhead.find('.monthpicker').addClass('hide');					//#Start_Month_d, #End_Month_d
13658			//jhead.find('#Start_Week_d, #End_Week_d').removeClass('hide');
13659			//jhead.find('#week-start-help').removeClass('hide');
13660		} else {
13661			j.removeClass('day-view').removeClass('week-view').addClass('month-view');
13662			jPerLabel.text('Month');
13663			
13664			jhead.find('#view-period-monthly').prop('checked', true);
13665			//jhead.find('#Start_Week_d, #End_Week_d').addClass('hide');
13666			//jhead.find('.monthpicker').removeClass('hide');
13667			//jhead.find('#week-start-help').addClass('hide');
13668		}
13669		
13670		if (isDisplayEndDate) {
13671			jend.removeClass('hide');
13672		} else {
13673			jend.addClass('hide');
13674		}
13675		
13676		if (isReload) {
13677			jhead.find('.btnSearch > a').click();
13678		}
13679    }
13680    
13681    _conStaffSumDetail.addGoalLevel = function() {
13682    	var msg = _getEditGoalName('', 'Save Goal Level');
13683    	var htm = '<div id="pop-confirm-save-goals">' + msg + '</div>';
13684    	var fnSave = function() { GLO.Report.StaffSummaryDetail.editGoalConfirmed(); };
13685    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Add New Goal Level', fnSave);
13686    }
13687    _conStaffSumDetail.addGoalLevelRow = function(goalId, goalName) {
13688    	var period = $('#report-main').find('input[name="view-period"]:checked').val();
13689    	var trCurr = $('#report-staff-summary-detail-data tfoot .report-goal-row:last');
13690    	var trNew = trCurr.clone().attr('staff_goal_id', goalId).attr('period_vc', peri
13690od);
13691    	var inputs = trNew.find('input');
13692    	
13693    	for (var i=0; i < inputs.length; i++) {
13694    		inputs.eq(i).val('');
13695    	}
13696    	
13697    	_setGoalName(trNew, null, goalName);
13698    	trCurr.after(trNew);
13699    	
13700    	trCurr.next().find('input').on('change', function() {
13701			$(this).closest('tr').find('.btnEditGoals').addClass('btn-has-change');
13702		});
13703    }
13704    _conStaffSumDetail.editGoal = function(btn) {
13705    	GLO.Popup.close($('#pop-confirm-save-goals').closest('.glopop'));
13706    	
13707    	var jrpt = $('#report-staff-summary-detail-data');
13708    	var tfoot = jrpt.find('tfoot');
13709    	var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl'));
13710    	
13711    	if (btn && $(btn).length) {
13712    		var tr = $(btn).closest('tr');
13713    	}
13714    	
13715    	if (tr.length === 0) {
13716    		tr = tfoot.find('tr');
13717    	}
13718    	
13719    	var goalId = tr.attr('staff_goal_id');
13720    	var goalName = _getGoalName(tr, isSingleStaff);
13721    	var hasChange = tr.find('.btnEditGoals').hasClass('btn-has-change');
13722    	//var h1 = _editGoalHeader(goalId, goalName, isSingleStaff, isChangePreset, hasChange);
13723    	
13724    	if (isSingleStaff) {
13725    		var h1 = 'Update Goals';
13726    		var msg = _editGoalsForStaffHtm(tr, goalId, goalName, hasChange);
13727    	} else {
13728    		var h1 = 'Update Goal Level: ' + goalName;
13729    		var msg = _editGoalLevelHtm(tr, goalId, goalName, hasChange);
13730    	}
13731    	
13732    	var htm = '<div id="pop-confirm-save-goals" staff_goal_id="' + UTIL.cleanString(goalId) + '">' + msg + '</div>';
13733    	var fnSave = function() { GLO.Report.StaffSummaryDetail.editGoalConfirmed(goalId); };
13734    	var jpop = GLO.Popup.Custom.openSimple(htm, h1, fnSave);
13735    	
13736    	jpop.find('.btnCancel').addClass('btnCenter').find('a').css({ "letter-spacing": "1px" });
13737    	
13738    	if (!isSingleStaff && !UTIL.isEmpty(goalId)) {
13739    		jpop.find('.pop-buttons').prepend('<span class="btnDelete btnLeft"><a onclick="GLO.Report.StaffSummaryDetail.deleteGoal(' + goalId + ')">Delete</a></span>');
13740    	}
13741    }
13742    
13743    _conStaffSumDetail.changeNewGoalName = function(element) {
13744    	if (!UTIL.isEmpty(element.value)) {
13745    		$('#pop-confirm-save-goals').find('#Create_Goal_fl').prop('checked', true);
13746    	}
13747    }
13748    
13749    function _getGoalName(tr, isSingleStaff) {
13750    	if (UTIL.isEmpty(isSingleStaff)) {
13751    		return tr.find('.column-staff, .column-period').find('b').text();
13752    	} else if (isSingleStaff) {
13753    		return tr.find('.column-period').find('b').text();
13754    	} else {
13755    		return tr.find('.column-staff').find('b').text();
13756    	}
13757    }
13758    function _setGoalName(tr, isSingleStaff, goalName) {
13759    	if (UTIL.isEmpty(isSingleStaff)) {
13760    		tr.find('.column-staff, .column-period').find('b').text(goalName);
13761    	} else if (isSingleStaff) {
13762    		tr.find('.column-period').find('b').text(goalName);
13763    	} else {
13764    		tr.find('.column-staff').find('b').text(goalName);
13765    	}
13766    }
13767    
13768    function _editGoalLevelHtm(tr, goalId, goalName, hasChange) {
13769    	return _getEditGoalName(goalName, 'Save Goal Level');
13770    }
13771    function _editGoalsForStaffHtm(tr, goalId, goalName, hasChange) {
13772    	var sname = $('#report-header-text').find('i').text();
13773    	var ddPreset = _getPresetGoalDropDown(goalId);
13774    	var htm = '', hasPreset = (!UTIL.isEmpty(ddPreset));
13775    	
13776    	if (hasPreset) {
13777    		if (!UTIL.isEmpty(goalId)) {
13778    			var input1 = '<input type="radio" name="goal-option" id="Update_Goal_fl" value="update"/>';
13779    			var msg1 = 'Update Goal Level', msg1b = 'This will update the goals for all staff that use the goal level <b>' + goalName + '</b>';
13780    			htm += _getEditGoalName(goalName, msg1, input1, msg1b, 'Goal_Name_vc', 'Update_Goal_fl', null, true);
13781    		}
13782    		
13783    		var input2 = '<input type="radio" name="goal-option" id="Goal_Switch_fl" value="switch"/>';
13784	    	htm += '<div class="goal-update-container"><label for="Goal_Switch_fl">' + input2 + 'Switch Goal Level to ' + ddPreset + '</label></div>';
13785    		
13786    		var input3 = '<input type="radio" name="goal-option" id="Create_Goal_fl" value="new"/>';
13787    		var msg3 = 'Create New Goal Level';
13788    		htm += _getEditGoalName('', msg3, input3, '', 'New_Goal_Name_vc', 'Create_Goal_fl', 'GLO.Report.StaffSummaryDetail.changeNewGoalName(this)');
13789    	} else {
13790    		if (!UTIL.isEmpty(goalId)) {
13791	    		var inputRemove = '<input type="radio" name="goal-option" id="Goal_Remove_fl" value="remove"/>';
13792		    	htm += '<div class="goal-update-container"><label for="Goal_Remove_fl">' + inputRemove + 'Remove ' + sname + ' from ' + goalName + '</label></div>';
13793	    	}
13794    		
13795    		htm += _getEditGoalName(goalName, 'Save Goal Level');
13796    	}
13797    	
13798    	return '<div id="pop-confirm-save-goal-choice">' + htm + '</div>';
13799    }
13800    function _getEditGoalName(goalName, msg, radioButton, msgSmall, textid, rdoid, textOnChange, isNoHelp) {
13801    	textid = UTIL.coalesce(textid, 'Goal_Name_vc');
13802    	rdoid = UTIL.coalesce(rdoid, 'Goal_Name_vc');
13803    	
13804    	if (!UTIL.isEmpty(textOnChange)) {
13805    		textOnChange = ' onchange="' + textOnChange + '"';
13806    	}
13807    	
13808    	var label = '<label for="' + rdoid + '" style="white-space: inherit;">' + msg + '</label>';
13809    	var css = ' style="width: 280px; letter-spacing: 1px;"';
13810    	var input = '<input id="' + textid + '" type="text" value="' + UTIL.coalesceString(goalName) + '" maxlength="100" placeholder="Name of Goal Level"' + UTIL.cleanString(textOnChange) + css + '/>';
13811    	//var helpIcon = '<b id="help-goal-period" class="help-icon4" onclick="GLO.Report.StaffSummaryDetail.goalPeriodHelp(true)" title="Weekly or Monthly Goals?">?</b>';
13812    	
13813    	if (!UTIL.isEmpty(msgSmall)) {
13814    		msgSmall = '<small>' + msgSmall + '</small>';
13815    	}
13816    	
13817    	if (isNoHelp) {
13818    		var htmPeriod = '';
13819    	} else {
13820    		var htmPeriod = _conStaffSumDetail.goalPeriodHelp(false);
13821    	}
13822    	
13823    	return '<div><div class="goal-update-container">' + UTIL.coalesceString(radioButton) + label + input + UTIL.cleanString(msgSmall) + '</div>' + htmPeriod + '</div>';
13824    }
13825    _conStaffSumDetail.goalPeriodHelp = function(isPopup) {
13826    	var currentPeriod = 'Monthly';
13827    	
13828    	if ($('#view-period-weekly').prop('checked')) { currentPeriod = 'Weekly'; }
13829    	
13830    	var htmPeriodCurrent = '<div id="pop-help-goal-period-current"><label>Current Period</label> <b>' + currentPeriod + '</b> <small>(so saving goals as ' + currentPeriod + ')</small></div>';
13831    	var h4 = '<h5>Can setup Weekly or Monthly Goals</h5>';
13832    	var msg1 = 'When change report period between weekly and monthly, the goals are automatically adjusted by a <b>1/4.25 ratio between week/month</b>';
13833    	var msg2 = 'When change report period between weekly and daily, the goals are automatically adjusted by a <b>1/7 ratio between day/week</b>';
13834    	var htm = '<div id="pop-help-goal-period">' + h4 + htmPeriodCurrent + '<p>' + msg1 + '</p><p>' + msg2 + '</p></div>';
13835    	
13836    	if (isPopup) {
13837    		GLO.Popup.Info.open(htm, 'Setup Goals');
13838    	} else {
13839    		return htm;
13840    	}
13841    }
13842    function _getPresetGoalDropDown(goalId) {
13843    	var dd = '<select id="Preset_Goal_id" onchange="GLO.Report.StaffSummaryDetail.selectPresetGoal(event, this)"> <option value="">(none)</option>';
13844    	var liPreset = $('#preset-goal-list').find('li');
13845    	
13846    	if (liPreset.length === 0) { return ''; }
13847    	
13848    	for (var i=0; i < liPreset.length; i++) {
13849    		var selected = '', id = liPreset.eq(i).attr('id');
13850    		
13851    		if (id == goalId) { selected = ' selected="selected"'; }
13852    		
13853    		dd += '<option value="' + id + '"' + selected + '>
13853' + liPreset.eq(i).text() + '</option>';
13854    	}
13855    	
13856    	return dd + '</select>';
13857    }
13858    
13859    _conStaffSumDetail.gotoGoalReport = function(element, event, staffid) {
13860    	var uri = 'report/StaffGoal?sfilter=' + staffid;
13861    	
13862    	if ($('#view-period-weekly').prop('checked')) {
13863	    	uri += '&period=week';
13864	    }
13865    	
13866    	GLO.Uri.gotoUriWithSpinner(uri, element, event);
13867    }
13868    
13869    _conStaffSumDetail.selectPresetGoal = function(event, element) {
13870    	var jgoal = $(element).find('option:selected');
13871		var goalId = jgoal.val(), goalName = jgoal.text();
13872		
13873		if (!UTIL.isEmpty(goalId)) {
13874    		var msg = '<p>Use Goal Level ' + goalName + '?</p>';
13875    		var h1 = goalName;
13876		} else {
13877			var msg = 'Remove Goals for this Staff?';
13878			var h1 = 'No Goals for Staff';
13879		}
13880		
13881		var fnYes = function() {			//= use this wrapper because by default GLO.Popup.Confirm passes popup html to function.
13882			var jpop = $('#pop-confirm-save-goals').closest('.glopop');
13883			jpop.find('#Goal_Switch_fl').prop('checked', true);
13884			_conStaffSumDetail.editGoalConfirmed();
13885		};
13886		
13887    	GLO.Popup.Confirm.open(msg, h1, fnYes);
13888    }
13889    
13890    _conStaffSumDetail.deleteGoal = function(goalId) {
13891    	var htm = '<div id="pop-confirm-delete-goal">Are you sure you want to delete this goal level?</div>';
13892    	var fnSave = function() {
13893    		GLO.Report.StaffSummaryDetail.deleteGoalConfirmed(goalId);
13894    	}
13895    	
13896    	GLO.Popup.Confirm.open(htm, 'Confirm Delete Preset Goal Level', fnSave);
13897    }
13898    _conStaffSumDetail.deleteGoalConfirmed = function(goalId) {
13899    	GLO.Popup.close($('#pop-confirm-delete-goal').closest('.glopop'));
13900    	
13901    	var tfoot = $('#report-staff-summary-detail-data tfoot');
13902    	var tr = tfoot.find('tr[staff_goal_id="' + goalId + '"]');
13903    	var url = GLO.Link.WebsiteDomain + 'report/StaffGoalDelete?goalid=' + goalId;
13904        var jpop = $('#pop-confirm-save-goals').closest('.glopop');
13905        var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl'));
13906        var goalName = _getGoalName(tr, isSingleStaff);
13907    	
13908        GLO.UI.Form.beginProcessing(tr.find('.btnEditGoals'));
13909        GLO.UI.Form.beginProcessing(jpop.find('.btnDelete'));
13910    	
13911    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
13912            .success(function(data, textStatus, jqXHR) {
13913                GLO.UI.Form.resetProcessing();
13914                GLO.Popup.close(jpop);
13915                GLO.Popup.Success.open('Preset Goal Level ' + goalName + ' Deleted', 'Goal Level Delete');
13916                
13917                if (isSingleStaff) {
13918	                _setGoalName(tr, isSingleStaff, 'Goals');
13919                	tr.attr('staff_goal_id', '');
13920                } else {
13921                	tr.remove();
13922                }
13923            })
13924            .error(function(jqXHR, textStatus, errorThrown) {
13925            	GLO.UI.Form.resetProcessing();
13926            	GLO.Popup.Error.open('<div><p>Unable to delete staff goals</p><p>Please try again</p></div>', 'Delete Goals');
13927            });
13928    }
13929    
13930    function _getGoalRow(goalId) {
13931    	var tr = $('#report-staff-summary-detail-data tfoot').find('tr.report-goal-row');
13932        
13933        if (tr.length === 1) {
13934        	return tr;
13935        } else {
13936        	if (!UTIL.isEmpty(goalId)) {
13937	        	return $('#report-staff-summary-detail-data tfoot').find('tr.report-goal-row[staff_goal_id = "' + goalId + '"]');
13938        	}
13939        	
13940        	for (var i=0; i < tr.length; i++) {
13941        		if (tr.eq(i).find('.btnEditGoals.btnProcessing4').length) {
13942        			return tr.eq(i);
13943        		}
13944        	}
13945        }
13946    }
13947    
13948    function _removeAndResetStaffGoals(goalId) {
13949		var trRemove = _getGoalRow(goalId).removeAttr('staff_goal_id').attr('period_vc', 'week');
13950		var jinput = trRemove.find('input');
13951		
13952		trRemove.find('.column-period b').text('Goals');
13953		
13954		for (var i=0; i < jinput.length; i++) {
13955			jinput.eq(i).val('');
13956		}
13957    }
13958    
13959    function _isValidGoalEdit(jpop, rdoList, rdoVal, goalName) {
13960    	if (rdoList.length > 0) {
13961    		if (UTIL.isEmpty(rdoVal)) {
13962	    		var htm = '<p>Please select the whether you want to update:</p><ul>'
13963	    				+ '<li>The Goal Level: ' + goalName + '</li>'
13964	    				+ '<li>Creat a New Goal Level</li>'
13965	    				+ '<li>Switch Staff to Different Goal Level</li>'
13966	    				+ '<li>Remove Goal Level from Staff</li>'
13967	    			+ '</ul>';
13968	    				
13969	    		GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">' + htm + '</div>', 'How Update Staff Goals?');
13970	    		return false;
13971	    	} else if (rdoVal == 'update' && UTIL.isEmpty(goalName)) {
13972	    		var fn = function() { jpop.find('#Goal_Name_vc').focus(); };
13973	    		GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">Please Enter Goal Name</div>', 'Goal Name Missing', fn);
13974	    		return false;
13975	    	} else if (rdoVal == 'new' && UTIL.isEmpty(jpop.find('#New_Goal_Name_vc').val())) {
13976	    		var fn = function() { jpop.find('#New_Goal_Name_vc').focus(); };
13977	    		GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">Please Enter Goal Name</div>', 'Goal Name Missing', fn);
13978	    		return false;
13979	    	}
13980	    } else if (UTIL.isEmpty(goalName)) {
13981		    var fn = function() { jpop.find('#Goal_Name_vc').focus(); };
13982			GLO.Popup.Warning.open('<div id="pop-warn-confirm-save-goals">Please Enter Goal Name</div>', 'Goal Name Missing', fn);
13983			return false;
13984	    }
13985	    
13986	    return true;
13987    }
13988    
13989    _conStaffSumDetail.editGoalConfirmed = function(goalId) {
13990    	var jrpt = $('#report-main');
13991        var jRptData = jrpt.find('.report-container');
13992        
13993    	var jpop = $('#pop-confirm-save-goals').closest('.glopop');
13994    	var rdoList = jpop.find('input[name="goal-option"]'), rdoVal = jpop.find('input[name="goal-option"]:checked').val();
13995    	var goalName = jpop.find('#Goal_Name_vc').val();
13996    	
13997    	if (!_isValidGoalEdit(jpop, rdoList, rdoVal, goalName)) { return; }
13998    	
13999    	if (rdoList.length === 0 && UTIL.isEmpty(goalId)) {										//= simple create
14000    		var tr = null, jd = { "goal_name_vc": goalName, "updatetype": "create-simple" };
14001    	} else if ((rdoList.length === 0 && !UTIL.isEmpty(goalId)) || rdoVal === 'update') {	//= update
14002    		var tr = _getGoalRow(goalId);
14003    		var jd = _getGoals(tr, goalId, goalName, "update");
14004    	} else if (rdoVal === 'new') {															//= copy existing + create
14005    		goalName = jpop.find('#New_Goal_Name_vc').val();
14006    		var tr = _getGoalRow(goalId);
14007    		goalId = '';
14008    		var jd = _getGoals(tr, goalId, goalName, 'create-copy');
14009    	} else if (rdoVal === 'switch') {														//= switch staff to different (existing) goal level/
14010    		goalId = jpop.find('#Preset_Goal_id').val();
14011    		goalName = jpop.find('#Preset_Goal_id option:selected').text();
14012    		
14013    		var tr = _getGoalRow(goalId);
14014    		var jd = { "goal_id": goalId, "updatetype": "switch" };
14015    	} else if (rdoVal === 'remove') {														//= remove
14016    		goalName = goalId = '';
14017    		_removeAndResetStaffGoals(goalId);
14018    		var tr = null, jd = { "goal_name_vc": goalName, "updatetype": "remove" };
14019    	} else {																				//= error
14020    		GLO.Log.insertSimple('Update Goal Level Error', 'goal id = ' + goalId + '; ' + goalName, 'error');
14021    		GLO.Popup.Warning('Error Updating Staff Level', 'Update Staff Level');
14022    		return;
14023    	}
14024    	
14025    	var period = jrpt.find('input[name="view-period"]:checked').val();
14026    	
14027    	if (!GLO.Report.hasReportPassword(jd)) {
14028    		return;
14029    	} else if (tr && tr.length) {
14030    		GLO.UI.Form.beginProcessing(tr.find('.btnEditGoals'));
14031    		tr.attr('period_vc', period);
14032    	}
14033    	
14034    	var jdts = _getDateRange(jrpt);
14035		var start = UTIL.fromSADate(jdts.start, true, true), end = UTIL.fromSADate(jdts.end, true, true);
14036    	var url = _getGoalSearchUrl(jrpt, period, start, end, true) + '&ispartial=1';
14037    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
14038    	
14039    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
14040            .success(function(data, textStatus, jqXHR) {
14041                GLO.UI.Form.resetProcessing();
14042                GLO.Popup.closeIfExist($('#pop-warn-save-goal, #report-password-container').closest('.glopop'));
14043                
14044                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
14045                	var jpopPIN = GLO.Popup.Custom.openSimple('<div id="pop-warn-save-goal">' + data + '</div>', 'Enter PIN / Password');
14046                	jpopPIN.find('.pop-buttons-parent').remove();
14047                	return;
14048                }
14049                
14050                GLO.Popup.close(jpop);
14051                GLO.Popup.Success.open('Goals Saved', 'Staff Goals');
14052                
14053                if (UTIL.parseBool(jd.updatetype === 'switch')) {
14054                	_loadData(jRptData, data);
14055                } else {
14056                	var gid = UTIL.coalesceInt($(data).attr('goal_id'), jd.goal_id);
14057                	var gname = UTIL.coalesceString(goalName, 'Goals');
14058                	
14059                	if (tr && tr.length) {
14060                		_setGoalName(tr, null, gname);
14061                		tr.attr('staff_goal_id', gid);
14062                		tr.find('.btnEditGoals').removeClass('btn-has-change');
14063                	} else if (jd.updatetype === "create-simple") {
14064                		_conStaffSumDetail.addGoalLevelRow(gid, gname);
14065                	}
14066                	
14067                	_loadGoalCss(true);
14068                }
14069            })
14070            .error(function(jqXHR, textStatus, errorThrown) {
14071            	GLO.UI.Form.resetProcessing();
14072            	GLO.Popup.Error.open('<div><p>Unable to save staff goals</p><p>Please try again</p></div>', 'Save Goals');
14073            });
14074    }
14075    
14076    function _getGoals(tr, goalId, goalName, updateType) {
14077		var jd = { "goal_id": goalId, "goal_name_vc": goalName, "updatetype": updateType
14078				, "client_nr": tr.find('.column-count-client input').val(), "service_nr": tr.find('.column-count-service input').val(), "product_nr": tr.find('.column-count-product input').val()
14079				, "service_mn": tr.find('.column-sales-total-service input').val(), "tip_mn": tr.find('.column-sales-total-tip input').val()
14080				, "product_mn": tr.find('.column-sales-total-product input').val(), "ps_ratio_pct": tr.find('.column-product-to-service input').val()
14081				
14082				, "request_pct": tr.find('.column-service-request input').val(), "existing_pct": tr.find('.column-existing input').val()
14083				, "pre_book_pct": tr.find('.column-pre-book input').val()
14084				
14085				, "day_worked_nr": tr.find('.column-days-worked input').val(), "available_per_day_nr": tr.find('.column-hours-available input').val()
14086				, "booked_per_day_nr": tr.find('.column-hours-worked input').val(), "booked_pct": tr.find('.column-hours-worked-percent input').val()
14087				
14088				, "ticket_avg_mn": tr.find('.column-ticket-avg-total input').val()
14089				, "ticket_service_avg_mn": tr.find('.column-ticket-avg-service input').val(), "ticket_product_avg_mn": tr.find('.column-ticket-avg-product input').val()
14090				
14091				, "ticket_per_day": tr.find('.column-daily-avg-ticket-count input').val()
14092				, "service_per_day": tr.find('.column-daily-avg-service-sales input').val(), "product_per_day": tr.find('.column-daily-avg-product-sales input').val()
14093			};
14094		
14095		return jd;
14096    }
14097    
14098    _conStaffSumDetail.monthToDate = function(moyr, isStart) {
14099    	var monthAndYear = moyr.split('/');
14100    	var mo = monthAndYear[0], yr = monthAndYear[1];
14101    	var dtStart = new Date(mo + '/1/' + yr);
14102    	
14103    	if (isStart) {
14104    		return dtStart;
14105    	} else {
14106    		return new Date(dtStart.setMonth(dtStart.getMonth() + 1)).addDays(-1);
14107    	}
14108    }
14109    
14110    function _getDateRange(jrpt) {
14111    	var end = '', jend = jrpt.find('#report-search-header-dates .end-cell');
14112    	
14113    	if (jrpt.find('#view-period-daily').prop('checked')) {
14114    		var period = 'day';
14115    		var start = jrpt.find('#Start_d').val();
14116    		
14117    		if (jend.is(':visible')) {
14118    			end = jrpt.find('#End_d').val();
14119    		} else {
14120    			end = start;
14121    		}
14122    	} else if (jrpt.find('#view-period-weekly').prop('checked')) {
14123    		var period = 'week';
14124    		var start = jrpt.find('#Start_Week_d').val();
14125    		
14126    		if (jend.is(':visible')) {
14127    			end = jrpt.find('#End_Week_d').val();
14128    		} else {
14129    			end = new Date(start).addDays(7);
14130    		}
14131    	} else {
14132    		var period = 'month';
14133    		var start = _conStaffSumDetail.monthToDate(jrpt.find('#Start_Month_d').val(), true);
14134			
14135			if (jend.is(':visible')) {
14136				end = _conStaffSumDetail.monthToDate(jrpt.find('#End_Month_d').val(), false);
14137			}
14138	 	}
14139	 	
14140	 	return { "start": start, "end": end, "period": period }
14141    }
14142    function _getCurrentChartArray(jRptData) {
14143    	var arr = [], checkedList = jRptData.find('tr.display-chart-row').find(':checked');
14144    	
14145    	for (var i=0; i < checkedList.length; i++) {
14146    		arr.push(checkedList.eq(i).closest('td').index());
14147    	}
14148    	
14149    	return arr;
14150    }
14151    function _loadData(jRptData, data) {
14152    	var arrChartList = _getCurrentChartArray(jRptData);
14153    	
14154    	if (data) {
14155    		jRptData.html(data);
14156        }
14157        
14158        UI.initTableSorter2(jRptData.find('table.tablesorter'), [0,0]);
14159        _initHideEmptyColumns();
14160        
14161        jRptData.find('tbody tr:odd').addClass('EveryOtherRowQuiet');
14162        GLO.Report.CellSummary.initReport(jRptData, true, true);
14163		
14164		_initGoals(jRptData);
14165		_loadPeriod();
14166		_displayEndDate(jRptData);
14167		
14168		var cssThrobber = 'position: relative; height: 160px; z-index: 9;'
14169    	var blueThrobber = '<div id="throbber-loading-report-charts" style="margin-top: 140px; height: 60px;">' + GLO.Report.Template2.getBlueThrobber(cssThrobber) + '</div>';
14170    	
14171    	$('.report-chart-container').html(blueThrobber);
14172    	setTimeout(GLO.Report.StaffSummaryDetail.initComplete, 4900);		//= in case there is an error later -> ensure blue throbber is removed
14173    	
14174    	setTimeout(function() {
14175    		_initChart0(arrChartList);
14176    	}, 900);
14177    }
14178    function _initHideEmptyColumns() {
14179    	var j = $('#report-staff-summary-detail-data');
14180    	var jtimeHeader = j.find('thead #staff-goal-header-hours-per-day');
14181    	
14182    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-hours-sick')) {
14183    		var colspan = parseInt(jtimeHeader.attr('colspan')) - 1;
14184    		jtimeHeader.attr('colspan', colspan);
14185    		
14186    		if (colspan < 3) {
14187    			jtimeHeader.addClass('narrow-cell');
14188    		}
14189    	}
14190    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-hours-vacation')) {
14191    		var colspan = parseInt(jtimeHeader.attr('colspan')) - 1;
14192    		jtimeHeader.attr('colspan', colspan);
14193    		
14194    		if (colspan < 3) {
14195    			jtimeHeader.addClass('narrow-cell');
14196    		}
14197    	}
14198    	
14199    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-count-product')) {
14200    		var jh = j.find('thead #staff-goal-header-count');
14201    		jh.attr('colspan', parseInt(jh.attr('colspan')) - 1);
14202    	}
14203    	
14204    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-product-to-service')) {
14205    		var jh = j.find('thead #staff-goal-header-sales');
14206    		jh.attr('colspan', parseInt(jh.attr('colspan')) - 1);
14207    	}
14208    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-sales-total-product')) {
14209    		var jh = j.find('thead #staff-goal-header-sales');
14210    		jh.attr('colspan', parseInt(jh.attr('colspan')) - 1);
14211    	}
14212    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-sales-total-commission')) {
14213    		var jh = j.find('thead #staff-goal-header-sales');
14214    		jh.attr('colspan', parseInt(jh.attr('colspan')) - 1);
14215    	}
14216    	
14217    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-ticket-avg-product')) {
14218    		var jh = j.find('thead #staff-goal-header-average-ticket');
14219    		jh.attr('colspan', parseInt(jh.attr('colspan')) - 1);
14220    	}
14221    	
14222    	if (GLO.Report.Template.hideEmptyColumn(j, 'column-daily-avg-product-sales')) {
14223    		var jh = j.find('thead #staff-goal-header-average-daily');
14224    		jh.attr('colspan', parseInt(jh.attr('colspan')) - 1);
14225    	}
14226    }
14227    
14228    function _displayEndDate(jRptData) {
14229    	var tfoot = jRptData.find('tfoot');
14230		var isBizLevel = UTIL.parseBool(tfoot.attr('is_business_level'));
14231		var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl'));
14232		var jend = $('#staff-summary-detail-header').find('.date-cell.end-cell');
14233		
14234		if (!isBizLevel) {
14235    		_loadGoalCss();
14236    	}
14237    	
14238    	if (isSingleStaff || isBizLevel) {
14239    		jend.removeClass('hide');
14240    	} else {
14241    		jend.addClass('hide');
14242    		//$('#report-staff-summary-detail-data').find('thead th.column-staff').click();
14243    	}
14244    }
14245    function _initChart0(arrChartList) {
14246    	google.charts.load('current', {'packages':['bar']});
14247      	google.charts.setOnLoadCallback(function() { GLO.Report.StaffSummaryDetail.initChart(arrChartList); });
14248    }
14249    function _getLegendColors() {
14250    	var arrColors = [], jcolors = $('.gchart:first svg g:first').find('rect');
14251    	
14252    	for (var i=1; i < jcolors.length - 1; i++) {
14253    		arrColors.push(jcolors.eq(i).attr('fill'));
14254    	}
14255    	
14256    	return arrColors;
14257    }
14258    function _getLegend(jrpt) {
14259    	var lastRowLabel = null, tfoot = jrpt.find('tfoot');
14260    	var isBizLevel = UTIL.parseBool(tfoot.attr('is_business_level'));
14261    	var isSingleStaff = UTIL.parseBool(tfoot.attr('is_single_staff_fl'));
14262    	
14263    	if (isSingleStaff || isBizLevel) {
14264    		if (isSingleStaff) {
14265    			lastRowLabel = 'Goal';
14266    		}
14267    		
14268    		var arrLegend = _legendArray(jrpt, 'column-period', lastRowLabel);
14269    	} else {
14270    		var arrLegend = _legendArray(jrpt, 'column-staff');
14271    	}
14272    	
14273    	return arrLegend;
14274    }
14275    function _createChartsOnLoadAfterPageLoad(jrpt) {
14276    	if (jrpt.find('#view-period-daily').prop('checked')) { return; }
14277    	
14278    	var arrLegend = _getLegend(jrpt);
14279    	var chartWidth = _conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-sales-total-service', 'Total Service Sales', 'Services Sales: Actual vs Goal', '', null, 'currency');
14280    	var chartCount = (innerWidth - 200) / (chartWidth + 120);
14281    	
14282    	if (chartCount > 2) {
14283    		setTimeout(function() {						//= give first chart time to load so can re-used legend colors
14284    			var arrColors = _getLegendColors();
14285    			_preLoadCharts(chartCount, arrLegend, jrpt, arrColors);
14286    		}, 600);
14287    	}
14288    	
14289    	return chartCount;
14290    }
14291    function _preLoadCharts(chartCount, arrLegend, jrpt, arrColors) {
14292    	// if (GLO.Data.provider.industry_cd == 8) {
14293    	_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-ticket-avg-total', 'Average Ticket', 'Average product and service', '', arrColors, 'currency');
14294    	
14295    	if (chartCount >= 3) {
14296    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-count-ticket', 'Ticket Count', 'Number of Tickets', '', arrColors, 'long');
14297    	}
14298    	if (chartCount >= 4) {
14299    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-days-worked', 'Days Worked', 'Days Worked: Actual vs Goal', '', arrColors, 'long');
14300    	}
14301    	if (chartCount >= 5) {
14302    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-hours-worked', '% Booked', 'Hours Booked / Hours Available', '', arrColors, 'percent');
14303    	}
14304    	if (chartCount >= 6) {
14305    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-daily-avg-service-sales', 'Daily Services', 'Daily Average Service Sales', '', arrColors, 'currency');
14306    	}
14307    	if (chartCount >= 7) {
14308    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-sales-total-tip', 'Service Tips', 'Total Service Tips', '', arrColors, 'currency');
14309    	}
14310    	if (chartCount >= 8) {
14311    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-product-to-service', 'Product:Service Sales', 'Ratio of Product to Service Sales', '', arrColors, 'currency');
14312    	}
14313    	if (chartCount >= 9) {
14314    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-service-request', 'Client Request', 'Requested by Client', '', arrColors, 'currency');
14315    	}
14316    	if (chartCount >= 10) {
14317    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-pre-book', 'Client Pre-Booked', 'appointment booked before/during last appointment', '', arrColors, 'currency');
14318    	}
14319    	if (chartCount >= 11) {
14320    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-existing', 'Client Existing', '% of tickets with existing client', '', arrColors, 'currency');
14321    	}
14322    	if (chartCount >= 12) {
14323    		_conStaffSumDetail.drawChart(arrLegend, jrpt, 'column-sales-total-product', 'Total Product Sales', 'Product Sales: Actual vs Goal', '', arrColors, 'currency');	
14324    	}
14325    }
14326    function _createChartsOnLoadDataAfterSearch(arrChartList) {
14327    	var tds = $('#report-staff-summary-detail-data').find('tr.display-chart-row').find('td');
14328    	
14329    	for (var i=0; i < arrChartList.length; i++) {
14330    		var td = tds.eq(arrChartList[i]);
14331    		var columnClass = _getColumnClass(td);
14332    		
14333    		td.find(':checkbox').prop('checked', true);
14334    		_drawChart0(td, columnClass);
14335    	}
14336    	
14337    	return arrChartList.length;
14338    }
14339    function _createChartsOnLoadFromUrl(displayCharts) {
14340    	var chartCount = 0, arrChart = displayCharts.split(',');
14341    	var tr = $('#report-staff-summary-detail-data').find('tr.display-chart-row');
14342    	
14343    	for (var i=0; i < arrChart.length; i++) {
14344    		//tr.find('.column-' + arrChart[i]).find(':checkbox').prop('checked', true).change();			//change event not yet wired
14345    		
14346    		var columnClass = 'column-' + arrChart[i];
14347    		var td = tr.find('.' + columnClass);
14348    		
14349    		if (td.length) {
14350	    		td.find(':checkbox').prop('checked', true);
14351	    		_drawChart0(td, columnClass);
14352	    		++chartCount;
14353    		}
14354    	}
14355    	
14356    	return chartCount;
14357    }
14358    _conStaffSumDetail.initChart = function(arrChartList) {
14359    	//var arrColors = _loadChartColors(jrpt);			google charts does a better job of generating colors
14360    	//var label = _getChartLabel(jrpt);		chart looks better without label
14361    	var jrpt = $('#report-main');
14362    	jrpt.find('thead input[type="checkbox"]').prop('checked', false);
14363    	
14364    	if (jrpt.find('table#report-staff-summary-detail-data tbody > tr').length === 0) { return; }
14365    	
14366    	if (_isInitComplete) {
14367    		if (jrpt.find('#view-period-daily').prop('checked')) {
14368    			var chartCount = 0;
14369    		} else {
14370    			var chartCount = _createChartsOnLoadDataAfterSearch(arrChartList);
14371    		}
14372    	} else {
14373    		var displayCharts = UTIL.cleanString(GLO.Uri.url('chart')).toLowerCase();
14374    		
14375    		if (!UTIL.isEmpty(displayCharts)) {
14376    			var chartCount = _createChartsOnLoadFromUrl(displayCharts);
14377    		} else {
14378    			var chartCount = _createChartsOnLoadAfterPageLoad(jrpt);
14379    		}
14380    		
14381    		_isInitComplete = true;
14382    	}
14383    	
14384    	if (chartCount > 0) {
14385	    	setTimeout(GLO.Report.StaffSummaryDetail.initComplete, 900);
14386        } else {
14387        	_conStaffSumDetail.initComplete();
14388        }
14389    }
14390    _conStaffSumDetail.initComplete = function() {
14391    	var jrpt = $('#report-main');
14392    	jrpt.find('#throbber-loading-report-charts').remove();
14393        jrpt.find('thead tr.display-chart-row').find('input[type="checkbox"]').change(GLO.Report.StaffSummaryDetail.displayColumnChart);
14394    }
14395    function _getColumnClass(td) {
14396    	var columnClass = td.attr('class').replace('sorter-false', '').replace('left-column', '').replace('right-column', '');
14397    	columnClass = columnClass.replace('column-count', '').replace('column-sales-total', '').replace('column-client', '');
14398    	columnClass = columnClass.replace('column-hours', '').replace('column-time', '').replace('column-ticket-avg', '').replace('column-daily-avg', '');
14399    	return $.trim(columnClass);
14400    }
14401    _conStaffSumDetail.displayColumnChart = function(event) {
14402    	var isDisplayChart = $(this).prop('checked');
14403    	var td = $(this).closest('td');
14404    	var columnClass = _getColumnClass(td);
14405    	
14406    	$('.report-chart-container').find('.gchart.' + columnClass).remove();
14407    	
14408    	if (isDisplayChart) {
14409    		_drawChart0(td, columnClass);
14410    	}
14411    }
14412    
14413    function _getChartSubTitle(subtitle) {
14414    	if ($('#staff-summary-detail-header #filter-per-period').prop('checked')) {
14415    		if (subtitle.toLowerCase().indexOf('goal') !== -1) {
14416    			return '';
14417    		}
14418    	}
14419    	
14420    	return subtitle;
14421    }
14422    function _drawChart0(td, columnClass) {
14423    	var fmt = td.find(':checkbox').attr('chart_format');
14424		var title = td.attr('title');
14425		var subtitle = UTIL.coalesceString(td.attr('subtitle'), '');
14426		
14427		var jrpt = $('#report-main');
14428    	var arrLegend = _getLegend(jrpt);
14429    	var arrColors = _getLegendColors();
14430		
14431		_conStaffSumDetail.drawChart(arrLegend, jrpt, columnClass, title, subtitle, '', arrColors, fmt);
14432    }
14433    _conStaffSumDetail.drawChart = function(legendArray, jrpt, columnClass, title, subtitle, label, colors, format) {
14434    	jrpt.find('thead td.' + columnClass + ' input[type="checkbox"]').prop('checked', true);
14435    	format = UTIL.coalesce(format, "decimal");
14436    	subtitle = _getChartSubTitle(subtitle);
14437    	
14438    	var td = jrpt.find('tbody td.' + columnClass + ', tfoot tr.report-goal-row-single td.' + columnClass);
14439    	var arr = [], height = 300, width = 100 + parseInt(td.length * 20), maxWidth = parseInt(innerWidth * .9);
14440		
14441		if (maxWidth > 700) { height = 400; }
14442		
14443		if (format === 'percent') {				//Feb 2020 -> google charts appears to have a bug sometimes when display percents as bar chart values
14444			format = 'long'
14445		}
14446		
14447		var options = {
14448          	chart: { title: title, subtitle: subtitle },
14449          	bars: "vertical",
14450          	vAxis: { format: format },
14451          	width: width, height: height
14452          	//, colors: arrColors			//, colors: ['#d95f02', '#6bee97', '#7570b3', '#1b9e77']
14453        };
14454        
14455        if (legendArray.length > 10) {
14456        	options.legend = { "position": "none" };
14457        } else if (colors && colors.length > 0) {
14458        	options.colors = colors;
14459        	options.legend = { "position": "none" };
14460        	//options.legend = { "position": "top", "textStyle": { "fontSize": 11 }};
14461        } else {
14462    		options.width += 120;
14463    		options.legend = { "position": "left" };
14464        }
14465        
14466        if (options.width > maxWidth) { options.width = maxWidth; }
14467        
14468        arr.push(legendArray);
14469        _addChart(title, td, arr, format);
14470        var data = google.visualization.arrayToDataTable(arr);
14471        
14472        var jcontainer = $('.report-chart-container');
14473        var chartid = 'chart' + (jcontainer.find('.gchart').length + 1);
14474        jcontainer.append('<div id="' + chartid + '" class="gchart ' + columnClass + '"></div>');
14475        
14476        var chart = new google.charts.Bar(document.getElementById(chartid));
14477        chart.draw(data, google.charts.Bar.convertOptions(options));
14478        return width;
14479    }
14480    function _legendArray(jrpt, columnClass, extraLegendItem, label) {
14481    	var arr = [];
14482    	var td = jrpt.find('tbody td.' + columnClass + ', tfoot tr.report-goal-row-single td.' + columnClass);
14483    	
14484    	arr.push(UTIL.coalesceString(label, ''));
14485    	
14486    	for (var i=0; i < td.length - 1; i++) {
14487    		if (td.eq(i).is(':visible')) {				// && td.eq(i).closest('tr').attr('id') !== 'report-goal-total'
14488    			arr.push(_getLegendLabel(td.eq(i)));
14489    		}
14490    	}
14491    	
14492    	if (extraLegendItem) {
14493    		arr.push(extraLegendItem);
14494    	} else if (td.eq(i).is(':visible')) {
14495    		arr.push(_getLegendLabel(td.eq(i)));
14496    	}
14497    	
14498    	return arr;
14499    }
14500    function _getLegendLabel(td) {
14501    	var nm = UTIL.directTagOnly(td);
14502		
14503		if (UTIL.isEmpty(nm)) {
14504			nm = UTIL.directTagOnly(td.find('small'));
14505			
14506			if (UTIL.isEmpty(nm)) {
14507				nm = UTIL.directTagOnly(td.next());
14508			}
14509		}
14510		
14511		return nm;
14512    }
14513    function _loadChartColors(jrpt) {
14514    	var tdPeriod = jrpt.find('td.column-period');
14515    	var arrColor = [];
14516    	
14517    	for (var i=1; i < tdPeriod.length; i++) {
14518    		arrColor.push(UI.getHexColor());
14519    	}
14520    	
14521    	return arrColor;
14522    }
14523    function _addChart(label, td, arr, fmt) {
14524    	var arr1 = [];
14525    	arr1.push(' ');					//arr1.push(label);
14526    	
14527    	for (var i=0; i < td.length-1; i++) {
14528	    	if (td.eq(i).is(':visible')) {
14529	    		var amt = UTIL.coalesceMoney(td.eq(i).text().replace('$', '').replace(',', '').replace('%', ''));
14530	    		
14531	    		if (UTIL.isNumber(amt) && amt > 1 && fmt == 'percent') {
14532	    			amt = UTIL.coalesceMoney(amt/100);
14533	    		}
14534	    		
14535	    		arr1.push(amt);
14536	    	}
14537    	}
14538    	
14539    	if (td.eq(i).is(':visible')) {
14540	    	var jinput = td.eq(i).find('input');
14541	    	
14542	    	if (jinput.length) {
14543	    		var amt = UTIL.coalesceMoney(jinput.val().replace('$', '').replace(',', '').replace('%', ''));
14544	    		
14545	    		if (UTIL.isNumber(amt) && amt > 1 && fmt == 'percent') {
14546	    			amt = UTIL.coalesceMoney(amt/100);
14547	    		}
14548	    		
14549	    		arr1.push(amt);
14550	    	} else {
14551	    		arr1.push(UTIL.coalesceMoney(td.eq(i).text().replace('$', '').replace(',', '').replace('%', '')));
14552	    	}
14553    	}
14554    	
14555    	arr.push(arr1);
14556    }
14557    function _getChartLabel(jrpt) {
14558    	if ($('#view-period-weekly').prop('checked')) {
14559    		var period = 'Week';
14560    	} else {
14561    		var period = 'Month';
14562    	}
14563    	
14564    	if (jrpt.find('.column-staff').length > 0) {			//= is single staff
14565    		var label = 'Staff';
14566    	} else {
14567    		var label = period;
14568    	}
14569    	
14570    	return label;
14571    }
14572    _conStaffSumDetail.changeToSetupGoal = function() {
14573    	var btn = $('#staff-goal-change-to-setup .btnEditGoals');
14574    	GLO.UI.Form.beginProcessing(btn);
14575    	$('#staff-summary-detail-header #filter-per-staff').prop('checked', true);
14576    	_conStaffSumDetail.search();
14577    }
14578    function _getGoalSearchUrl(jrpt, period, start, end, isSave) {
14579    	var qstring = 'sfilter=' + GLO.Uri.url('sfilter') + '&period=' + period;
14580    	
14581    	if (UTIL.isDate(start)) {
14582    		qstring += '&start=' + new Date(start).toGloDate(true);
14583    	}
14584    	
14585    	if (UTIL.isDate(end)) {
14586    		qstring += '&end=' + new Date(end).toGloDate(true);
14587    	}
14588    	
14589    	var urlPage = 'StaffGoal';
14590    	
14591    	if (isSave) {
14592    		urlPage = 'StaffGoalSave';
14593    	}
14594    	
14595    	var url = GLO.Link.WebsiteDomain + 'report/' + urlPage + '?' + qstring;
14596	 	
14597	 	var isPerStaff = (jrpt.find('input[name="filter-per"]:checked').val() === 'staff');
14598	 	var isActiveStaffOnly = jrpt.find('#Only_Active_Staff_fl').prop('checked');
14599	 	var isOnlyPaid = jrpt.find('#Only_Paid_fl').prop('checked');
14600	 	var isOnlyClockedIn = jrpt.find('#Only_Clocked_In_Hours_fl').prop('checked');
14601	 	
14602	 	if (isPerStaff) { url += '&isPerStaff=1'; }
14603	 	if (isActiveStaffOnly) { url += '&isActiveStaffOnly=1'; }
14604	 	if (isOnlyPaid) { url += '&isOnlyPaid=1'; }
14605	 	if (isOnlyClockedIn) { url += '&isOnlyClockedIn=1'; }
14606	 	
14607	 	if (jrpt.find('#filer-include-mon').prop('checked')) { url += '&mon=1'; } else { url += '&mon=0'; }
14608	 	if (jrpt.find('#filer-include-tue').prop('checked')) { url += '&tue=1'; } else { url += '&tue=0'; }
14609	 	if (jrpt.find('#filer-include-wed').prop('checked')) { url += '&wed=1'; } else { url += '&wed=0'; }
14610	 	if (jrpt.find('#filer-include-thu').prop('checked')) { url += '&thu=1'; } else { url += '&thu=0'; }
14611	 	if (jrpt.find('#filer-include-fri').prop('checked')) { url += '&fri=1'; } else { url += '&fri=0'; }
14612	 	if (jrpt.find('#filer-include-sat').prop('checked')) { url += '&sat=1'; } else { url += '&sat=0'; }
14613	 	if (jrpt.find('#filer-include-sun').prop('checked')) { url += '&sun=1'; } else { url += '&sun=0'; }
14614	 	
14615	 	return url;
14616    }
14617    _conStaffSumDetail.cancelSearch = function() {
14618    	UTIL.abortAjaxRequest(_searchRequest, true, true);
14619    }
14620    _conStaffSumDetail.search = function() {
14621    	var jrpt = $('#report-main');
14622    	var btnSearch = jrpt.find('.btnSearch');
14623    	var jRptData = jrpt.find('.report-container');
14624    	var jd = _getDateRange(jrpt);
14625    	
14626	 	var start = UTIL.fromSADate(jd.start, true, true);
14627	 	var end = UTIL.fromSADate(jd.end, true, true);
14628	 	
14629	 	if (GLO.Info.roleType > 219) {				//= is manager, search could come from staff-filter change
14630	 		var sname = $('#staff-filter').find('option:selected').text();
14631	 		$('#staff-summary-detail-report-header').find('i').text(sname);
14632	 	} else {
14633	 		var sname = UTIL.directTagOnly($('#staff-summary-detail-report-header').find('i'));
14634	 	}
14635	 	
14636	 	var pageTitle = 'Goals ' + sname + ': ' + start + ' - ' + end;
14637	 	var url = _getGoalSearchUrl(jrpt, jd.period, start, end);
14638	 	
14639	 	if (!GLO.Report.hasReportPassword(jd)) {
14640    		return;
14641	 	} else if (btnSearch.hasClass('btnProcessing4')) {
14642	 		if (_searchRequest && _searchRequest.abort) {
14643	 			_searchRequest.abort();
14644	 		}
14645	 	} else {
14646	 		GLO.UI.Form.beginProcessing(btnSearch);
14647        }
14648        
14649    	_searchRequest = $.ajax({ "type": "POST", "url": (url + '&ispartial=1'), "cache": false })				//, "data": jd
14650            .success(function(data, textStatus, jqXHR) {
14651                GLO.UI.Form.resetProcessing();
14652                _loadData(jRptData, data);
14653                
14654                document.title = pageTitle;
14655                window.history.pushState('', '', url);
14656                
14657                _completePageLoad();
14658            })
14659            .error(function(jqXHR, textStatus, errorThrown) {
14660                GLO.UI.Form.resetProcessing();
14661                GLO.Popup.Error('Unable to lookup data at this time.  Please try again.');
14662                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
14663            });
14664    }
14665    
14666    function _completePageLoad() {
14667        if (!_isInitialPageLoad) { return; }
14668        
14669        var hideIcon = $('#bd #report-main #report-header-help .close-icon:visible');
14670		
14671		if (hideIcon.length) {				//=  only auto-hide if help is visible, then still visible 1.5 seconds later (avoid auto-closing while opening which causes display icon to show back up)
14672			setTimeout(function() {
14673				$('#bd #report-main #report-header-help .close-icon:visible').click();
14674			}, 1500);
14675		}
14676        
14677        $('#report-staff-summary-detail #throbber-still-loading').remove();
14678        _isInitialPageLoad = false;
14679    }
14680    
14681    _conStaffSumDetail.exportReport = function() {
14682    	//var tbody = document.getElementById('report-payroll-summary-container');
14683    	var j = $('#report-main');
14684    	var jrpt = j.find('#report-staff-summary-detail-data');
14685    	var trs = jrpt.find('tr');
14686    	var jsonDates = _getDateRange(j);
14687    	
14688    	var fileName = 'Staff Goal Report ' + new Date(jsonDates.start).toGloDate(true) + ' - ' +  new Date(jsonDates.end).toGloDate(true);
14689    	GLO.Report.exportAsSpreadsheet(trs, fileName);				//_exportExcel(trs, fileName);
14690    }
14691    
14692    return _conStaffSumDetail;
14693})();
14694
14695
14696GLO.ReminderPortal = (function() {
14697    function _constructor(name) { }
14698    _constructor.isReminderView = false;
14699    var isInitialized = false;
14700
14701    _constructor.init = function() {
14702        _constructor.isReminderView = true;
14703        
14704        //Step I: Set Day
14705            $(window).hashchange(function() { GLO.ReminderPortal.hashNavigate(); });
14706            
14707            var dt = _constructor.getHashDate(true);
14708            _constructor.setHashDate(dt);
14709
14710        
14711        //Step II: Datepicker Day Navigator
14712            $('.fc-header-title').click(function() { 
14713                if ( $('#ui-datepicker-div:visible').length === 0 ) {
14714                    $('#headerDatePicker').datepicker('show');
14715                } else {
14716                    $('#headerDatePicker').datepicker('hide');
14717                }
14718            });
14719        
14720            var headerDatePicker = $('#headerDatePicker').datepicker({
14721                buttonText: '', buttonImageOnly: true, showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showOn: 'both', showAnim: 'blind'
14722                , showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
14723                , numberOfMonths: UI.getDatepickerMonths()
14724                
14725                , onSelect: function(dateText, inst) { 
14726                    //$('.fc-header-title .ui-datepicker-trigger').css('display', 'none');
14727                    GLO.ReminderPortal.gotoDay(dateText);
14728                }
14729
14730                , beforeShow: function(input, inst) {
14731                    //$("#ui-datepicker-div").addClass('hide');
14732                    //$('.fc-header-title .ui-datepicker-trigger').css('display', 'inline');
14733
14734                    $(input).datepicker('setDate', GLO.Uri.getDate('dt'));
14735                }
14736            });
14737
14738            $("#ui-datepicker-div").on('click', 'button.ui-datepicker-current', function() {        //= click on datepicker's today button.
14739                headerDatePicker.datepicker("hide");
14740                GLO.ReminderPortal.gotoDay(new Date().toGloDate());
14741            });
14742        
14743
14744        //Step III: Add hover over button effects to header buttons
14745            _setupHeader();
14746
14747        //Step IV: Shortcut Keys
14748            $(document).keydown(function(event) {
14749                if (event.ctrlKey) {
14750                    switch (event.which) {
14751                        case 37:                    //left arrow key.
14752                            if (UI.hasNoPopup()) { GLO.ReminderPortal.gotoPrevDay(); }
14753                            break;
14754                        case 38:                    //up arrow key.
14755                        	if (UI.hasNoPopup()) { GLO.ReminderPortal.moveByDay(-
147557); }
14756                            break;
14757                        case 39:                    //right arrow key.
14758                            if (UI.hasNoPopup()) { GLO.ReminderPortal.gotoNextDay(); }
14759                            break;
14760                        case 40:                    //down arrow key.
14761                            if (UI.hasNoPopup()) { GLO.ReminderPortal.moveByDay(7); }
14762                            break;
14763                    }
14764                }
14765
14766                if (event.altKey) {
14767                    if (event.which === 33) {                                		//33: page up --> go back 1 week.
14768                        var dt = GLO.ReminderPortal.getHashDate();
14769                        dt.setDate(dt.getDate() - 7);
14770                        GLO.ReminderPortal.gotoDay(dt);
14771                    } else if (event.which === 34) {                                //34: page down --> go forward 1 week.
14772                        var dt = GLO.ReminderPortal.getHashDate();
14773                        dt.setDate(dt.getDate() + 7);
14774                        GLO.ReminderPortal.gotoDay(dt);
14775                    } else if (event.which === 77) {                                //M: switch to month view 
14776                        if ( $('.fc-button-month:visible').length === 1) {
14777                            document.location = GLO.Link.Page.Provider.Home + 'calendarOne?sfilter=' + GLO.Uri.query('sfilter') + '#vw=month&dt=' + GLO.Uri.hash('dt');
14778                            UTIL.cancelEvent(event);
14779                        }
14780                    } else if (event.which === 68) {                                //D: switch to day view 
14781                        if ( $('.fc-button-agendaDay:visible').length === 1) {
14782                            document.location = GLO.Link.Page.Provider.Home + 'calendarOne?sfilter=' + GLO.Uri.query('sfilter') + '#vw=agendaDay&dt=' + GLO.Uri.hash('dt');
14783                            UTIL.cancelEvent(event);
14784                        }
14785                    } else if (event.which === 80) {                                //P: Print
14786                    	window.print();
14787                    } else if (event.which === 82) {                                //R: refresh appts
14788                        GLO.ReminderPortal.hashNavigate();
14789                        UTIL.cancelEvent(event);
14790                    } else if (event.which === 84) {                                //T: switch to today (or moves focus to "Go To" drop down)
14791                        GLO.ReminderPortal.gotoToday();
14792                        UTIL.cancelEvent(event);
14793                    } else if (event.which === 87) {                                //W: switch to week view 
14794                        if ( $('.fc-button-agendaWeek:visible').length === 1) {
14795                            document.location = GLO.Link.Page.Provider.Home + 'calendarOne?sfilter=' + GLO.Uri.query('sfilter') + '#vw=agendaWeek&dt=' + GLO.Uri.hash('dt');
14796                            UTIL.cancelEvent(event);
14797                        }
14798                    }
14799                }
14800            });
14801            $(window).bind('keypress', function(e) {
14802                //if (e.ctrlKey) { if (e.which > 36 && e.which < 41) { e.preventDefault(); } }
14803
14804                if (e.altKey) {
14805                    if (e.which === 33 || e.which === 34) {         		//33 = page up, 34 = page down.
14806                        e.preventDefault(); 
14807                    } else if (e.which > 48 && e.which < 56) {        		//1-7: 
14808                        e.preventDefault();
14809                    } else if (e.which === 68) {        					//D: switch to day view 
14810                        e.preventDefault();
14811                    } else if (e.which === 77) {        					//M: switch to month view 
14812                        e.preventDefault();
14813                    } else if (e.which === 80) {               				//P: print
14814                        e.preventDefault();
14815                    } else if (e.which === 82) {               				//R: refresh appts
14816                        e.preventDefault();
14817                    } else if (e.which === 84) {        					//T: Switch to today (or go to drop down)
14818                        e.preventDefault();
14819                    } else if (e.which === 87) {        					//W: switch to week view 
14820                        e.preventDefault();
14821                    }
14822                }
14823            });
14824
14825        //Step V: If Mobile
14826        if (GLO.Info.isMobile(true)) {
14827            setTimeout( function() {      //so overrides style set on _providerLayout.cshtml.
14828                $("#staff-portal-header").css({ "font-size": "108%" });
14829                $("#apptPortal-cal-btns").css({ "font-size": "108%" });
14830                $("#staff-filter").css({ "width": "165px" });
14831                //$("#calList-button").not('.reminderview').css({ "margin-right": "25px" });
14832                $('.fc-header-title').css({ 'margin-top': '1px' });
14833            }, 50);
14834            
14835            GLO.Info.setupFastClick($('#staff-portal-header')[0]);
14836        } else {
14837            //$('.fc-button-tomorrow').css({ "margin-left": "72px" });
14838            //$('#calList-button').css({ "margin-right": "21px" });
14839        }
14840        
14841        //Step VI: Other
14842        GLO.WaitList.setupRefresh(null, true);
14843        GLO.Report.enableFullPageCheck();
14844        
14845        _initVerifySFilter();
14846        _initUrlReminderView();
14847    }
14848    
14849    /* Solves 2 Use Cases
14850    	* when change location it clears staff-filter in url, unless staff-filter is a number (i.e. a single staff), this verifies single-staff filter exists in provider
14851    	* on phone and go to Schedule -> Reminders, defaults to current staff; but current staff does NOT perform client services
14852    */
14853    function _initVerifySFilter() {
14854    	var sfilter = GLO.Uri.query('sfilter');
14855    	
14856    	if (UTIL.isEmpty(sfilter) || sfilter.indexOf(',') !== -1 || !UTIL.isNumber(sfilter)) { return; }
14857    	
14858    	var jstaff = $('#staff-filter');
14859    	
14860    	if (jstaff.length === 0) { return; }
14861    	
14862    	var stdd = jstaff.find('option[value=' + sfilter + ']');
14863    	
14864    	if (stdd.length === 0) {
14865    		GLO.Staff.Filter.gotoSchedule();
14866    	}
14867    }
14868    
14869    function _initUrlReminderView() {
14870		//var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
14871		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
14872		
14873		if (!UTIL.isEmpty(highlight)) {
14874			GLO.ReminderPortal.attemptHighlight(highlight, 1);
14875		}
14876	}
14877	function _highlightColumn() {
14878		var highlight = UTIL.cleanString(GLO.Uri.url('highlight-column'));
14879		
14880		if (!UTIL.isEmpty(highlight)) {
14881			GLO.ReminderPortal.attemptHighlight(highlight, 1);
14882		}
14883	}
14884	_constructor.attemptHighlight = function(highlight, attemptCount) {
14885		var jhighlight = $('#' + highlight + ', .' + highlight);
14886		
14887		if (jhighlight.length > 0) {
14888			UI.highlight(jhighlight, 800, 6400, true);
14889		} else if (attemptCount < 5) {
14890			++attemptCount;
14891			
14892			setTimeout(function() {
14893				GLO.ReminderPortal.attemptHighlight(highlight, attemptCount);
14894			}, 1900);
14895		}
14896	}
14897    
14898    function _setupHeader() {
14899        //$('#easySearch_text').attr('title', 'Client search by name or phone');
14900
14901        var jBtnHeader = $('#staff-portal-header');
14902        UI.addButtonEffects( jBtnHeader.find('.fc-button-today').click(GLO.ReminderPortal.gotoToday) );
14903        UI.addButtonEffects( jBtnHeader.find('.fc-button-tomorrow').click(GLO.ReminderPortal.gotoTomorrow) );
14904
14905        UI.addButtonEffects( jBtnHeader.find('#calAll-button') );
14906        UI.addButtonEffects( jBtnHeader.find('#calList-button') );
14907            
14908        UI.addButtonEffects( jBtnHeader.find('.fc-button-month') );
14909        UI.addButtonEffects( jBtnHeader.find('.fc-button-agendaWeek') );
14910        UI.addButtonEffects( jBtnHeader.find('.fc-button-agendaDay') );
14911
14912        //jBtnHeader.find('.fc-button-prev').click(GLO.ReminderPortal.gotoPrevDay);
14913        //jBtnHeader.find('.fc-button-next').click(GLO.ReminderPortal.gotoNextDay);
14914        
14915        jBtnHeader.find('#reminder-left-arrow > img').click(GLO.ReminderPortal.gotoPrevDay);
14916        jBtnHeader.find('#reminder-right-arrow > img').click(GLO.ReminderPortal.gotoNextDay);
14917
14918        if ($('#inactiveStaffBar:visible, .hello-bar-container').length > 0 && $('#staffFilter:visible').length > 0) {
14919            $('#inactiveStaffBar:visible, .hello-bar-container').css({ "top": "25px" });
14920            $('#doc3').css({ "margin-top": "50px" });
14921        }
14922    }
14923
14924    _constructor.setHashDate = function(dt) {
14925        var currHashDt = _constructor.getHashDate();
14926        var newHashDtString;
14927
14928        if ( !_constructor.IsSameDay(dt, currHashDt)) {
14929            if ( _constructor.IsSameDay(dt, _constructor.getTomorrow()) ) {
14930                newHashDtString = 'tomorrow';
14931            } else if ( _constructor.IsSameDay(dt, new Date(GLO.Data.provider.now_dt)) ) {
14932                newHashDtString = 'today';
14933            } else {
14934                newHashDtString = (dt.getMonth() + 1) + '-' + dt.getDate() + '-' + dt.getFullYear()
14935            }
14936            
14937            //GLO.Uri.hash('dt', newHashDtString);
14938            document.location.hash = "dt=" + newHashDtString;
14939        } else if (!isInitialized) {
14940            GLO.ReminderPortal.hashNavigate();
14941        }
14942    }
14943
14944    _constructor.getHashDate = function(useTitle) {
14945        var dtHash = GLO.Uri.hash('dt');
14946        var dt = dtHash.replace(/-/g, '/');         //= dtHash.replaceAll('-', '/')
14947    
14948        if (useTitle && UTIL.isEmpty(dtHash)) {
14949        	var dtTest = $('.fc-header-title h2').text();
14950        	
14951        	if (UTIL.isDate(dtTest)) {
14952        		dt = dtHash = new Date(dtTest);
14953        		
14954        		if (dt.getFullYear() == '2001') {
14955        			dt.setFullYear(new Date().getFullYear());
14956        		}
14957        	}
14958        }
14959        
14960        if (UTIL.isEmpty(dtHash) || dtHash === 'today') {
14961            dt = new Date(GLO.Data.provider.now_dt);
14962        } else if (dtHash === 'tomorrow') {
14963            dt = new Date(GLO.Data.provider.now_dt).addDays(1);			//dt = _constructor.getTomorrow();
14964        } else {
14965            dt = new Date(dt);
14966            if (!UTIL.isDate(dt)) { dt = new Date(GLO.Data.provider.now_dt); }
14967            if (!UTIL.isDate(dt)) { dt = new Date(); }
14968        }
14969
14970        return dt;
14971    }
14972
14973    _constructor.IsSameDay = function(dt1, dt2) {
14974        if (dt1.getDate() === dt2.getDate() && dt1.getMonth() === dt2.getMonth() && dt1.getFullYear() === dt2.getFullYear()) {
14975            return true;   
14976        } else {
14977            return false;
14978        }
14979    }
14980
14981    _constructor.getTomorrow = function() {             //toDo (low priority): move to util.js
14982        var today = new Date(GLO.Data.provider.now_dt);
14983        //var dt = new Date();
14984        today.setDate(today.getDate() + 1);
14985        return today;
14986    }
14987
14988    _constructor.setTitle = function() {
14989        var dtHash = GLO.Uri.hash('dt');
14990        var newTitle;
14991        var newDate = _constructor.getHashDate();
14992
14993        if (dtHash === 'today') {
14994            newTitle = 'Today';
14995        } else if (dtHash === 'tomorrow') {
14996            newTitle = 'Tomorrow';
14997        } else {
14998            newTitle = newDate.toGloDateString(true, true, true);
14999        }
15000        
15001        document.title = 'Reminders - ' + newTitle;
15002        $('.fc-header-title h2').text(newDate.toGloDateString(true, false));
15003    }
15004
15005    _constructor.hashNavigate = function() {
15006        var dtHash = GLO.Uri.hash('dt');
15007        
15008        if (UTIL.isEmpty(dtHash) && isInitialized) {
15009            history.back();     //history.go(-1);
15010        } else {
15011            //GLO.Log.insert('dtHash = ' + dtHash + '; isInitialized = ' + isInitialized, 'hashNavigate #1');
15012            
15013            if (!UTIL.isDate(dtHash)) {
15014            	dtHash = _constructor.getHashDate(true);
15015            	dtHash = dtHash.toGloDate(true);
15016            } else if (!isInitialized) {
15017            	isInitialized = true;
15018            }
15019            
15020            //GLO.Log.insert('dtHash = ' + dtHash + '; isInitialized = ' + isInitialized, 'hashNavigate #2');
15021            
15022            var processing = $('.loadingDiv').clone();
15023            $('#reminder-day-view tbody').html('<tr><td colspan="11">' + processing.outerHTML() + '</td></tr>');
15024            
15025            _constructor.setTitle();
15026            //$("#reminder-day-view table").tablesorter({ textExtraction: UI.tableSorterOrderBy });
15027            var sfilter = GLO.Uri.query('sfilter');
15028            
15029            var url = location.protocol + '//' + location.host + '/provider/ReminderDay_ajax?dt=' + dtHash + '&sfilter=' + sfilter;
15030            var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
15031                .success(function(data, textStatus, jqXHR) {
15032                    var tbl = $('#reminder-day-view table.tablesorter');
15033                    var p = tbl.parent();
15034                    tbl.remove();
15035
15036                    tbl.find('tbody').html( $(data).html() );
15037                    p.append(tbl);
15038                    tbl = p.find('.tablesorter');
15039                    
15040                    if (tbl.find('.noResults').length === 0) {
15041                    	UI.initTableSorter(tbl);
15042                    	_loadTags(data);
15043                    	_highlightColumn();
15044                    }
15045                })
15046                .error(function(jqXHR, textStatus, errorThrown) { });
15047        }
15048    }
15049    
15050    function _loadTags(data) {
15051    	var jtags = $('<div>' + data + '</div>').find('#reminder-client-tag-list').find('.client-tag');
15052    	
15053    	if (jtags.length === 0) { return; }
15054    	
15055    	var tbl = $('#reminder-day-view table.tablesorter');
15056    	
15057    	for (var i=0; i < jtags.length; i++) {
15058    		var jtag = jtags.eq(i);
15059    		var tdClient = tbl.find('tr[client_id=' + jtag.attr('client_id') + ']').addClass('row-has-tag').find('.reminder-client-name');
15060    		
15061    		_constructor.setTagNameAndTitle(jtag);
15062    		tdClient.append(jtag);
15063    	}
15064    	
15065    	tbl.on('click.open-tag', '.client-tag', GLO.ReminderPortal.openTag);
15066    }
15067    
15068    _constructor.setTagNameAndTitle = function(jtag) {
15069    	var tag = jtag.text(), cid = jtag.attr('client_id'), rcid = jtag.attr('related_client_id'), note = UTIL.cleanString(jtag.attr('note_vc'));
15070    	var maxLen = 20;
15071    	
15072    	if (!UTIL.isEmpty(note) && (!UTIL.isEmpty(rcid) || tag.length > maxLen)) {
15073			note = 'note: ' + note;
15074		}
15075		
15076		if (!UTIL.isEmpty(rcid)) {
15077			if (!UTIL.isEmpty(note)) { note = ' | ' + note; }
15078			
15079			var relationshipName = UTIL.cleanString(jtag.attr('relationship_name_vc')), relateClientName = UTIL.cleanString(jtag.attr('related_client_vc'));
15080			
15081			note = relationshipName + ' ' + relateClientName + note;
15082		}
15083		
15084		if (tag.length > maxLen) {
15085			if (!UTIL.isEmpty(note)) { note = ' | ' + note; }
15086			
15087			note = tag + note;
15088			jtag.text(UTIL.maxString(tag, maxLen - 3));
15089		}
15090		
15091		if (!UTIL.isEmpty(note)) {
15092			jtag.attr('title', note);
15093		}
15094    }
15095    
15096    _constructor.openTag = function(event) {
15097    	var jtag = $(this);
15098    	var tr = jtag.closest('tr');
15099    	var thisClientId = tr.attr('client_id'), thisClientName = tr.find('.reminder-client-name').find('a').text();
15100    	
15101    	GLO.ClientProfile.Tag.openTagFromReport(jtag, thisClientId, thisClientName);
15102    }
15103    
15104    _constructor.gotoToday = function() {
15105        _constructor.setHashDate(new Date());
15106    }
15107
15108    _constructor.gotoTomorrow = function() {
15109        _constructor.setHashDate(_constructor.getTomorrow());
15110    }
15111    
15112    _constructor.gotoPrevDay = function() {
15113        _constructor.moveByDay(-1);
15114    }
15115    
15116    _constructor.gotoNextDay = function() {
15117        _constructor.moveByDay(1);
15118    }
15119    
15120    _constructor.moveByDay = function(days) {
15121    	var currDt = _constructor.getHashDate();
15122        var newDt = new Date(currDt);
15123        
15124        newDt.setDate(currDt.getDate() + days);
15125        _constructor.setHashDate(newDt);
15126    }
15127    
15128    _constructor.gotoDay = function(day) {
15129        var newDt = new Date(day);
15130        _constructor.setHashDate(newDt);
15131    }
15132
15133    function _savePhoneReminderToRow(row, status, note) {
15134    	row.attr('phone_ms_cd', status);
15135    	row.attr('phone_note_vc', note);
15136    }
15137    
15138    function _setPhoneReminderSpan(jRow, status, title, callDate) {
15139    	var jPhoneColumn = jRow.find('.reminder-phone-column').attr('title', title);
15140        var jPhoneSpan = jPhoneColumn.find('span');
15141    	
15142    	jPhoneSpan.text(callDate);
15143        jPhoneSpan.attr('dt', callDate);
15144    	jPhoneSpan.removeClass('reminder-phone-confirmed').removeClass('reminder-phone-left-message').removeClass('reminder-phone-no-response').removeClass('reminder-phone-wrong-number');
15145    	
15146    	if (status == 900) {
15147            jPhoneSpan.addClass('reminder-phone-confirmed');
15148        } else if (status == 901) {
15149            jPhoneSpan.addClass('reminder-phone-left-message');
15150        } else if (status == 902) {
15151            jPhoneSpan.addClass('reminder-phone-no-response');
15152        } else if (status == 903) {
15153            jPhoneSpan.addClass('reminder-phone-wrong-number');
15154        }
15155    }
15156    
15157    _constructor.savePhoneReminder = function() {		//= called when click span (in reminder view) which opens Phone Reminder Popup.
15158        var jModal = $('#simplemodal-container');
15159        UTIL.DefaultText.deInit(jModal);
15160
15161        var phoneReminderId = jModal.find('#Phone_Reminder_id').val();
15162        var scheduleId = jModal.find('#Phone_Schedule_id').val();
15163        var sMultiId = jModal.find('#Phone_Schedule_Multi_id').val();
15164        var scid = jModal.find('#Phone_Schedule_Client_id').val();
15165        var mStatus = jModal.find('#Phone_Message_Status_cd').val();
15166        
15167        var callDate = jModal.find('#Phone_Call_dt').val() + ' ' + UI.getTimeMaskValue(jModal.find('#Phone_Call_tm'));
15168        var note = jModal.find('#Phone_Note_vc').val().replace(/"/g, '');
15169
15170        _constructor.editPhoneReminder(phoneReminderId, scheduleId, sMultiId, scid, mStatus, c
15170allDate, note, null);
15171        
15172        if (!UTIL.isEmpty(scid)) {
15173        	var jRow = $('#reminder-day-view tr[schedule_client_id="' + scid + '"]');
15174        } else {
15175        	var jRow = $('#reminder-day-view tr#' + scheduleId);
15176        }
15177        
15178        _savePhoneReminderToRow(jRow, mStatus, note);
15179        
15180        var title = jModal.find('#Phone_Message_Status_cd option:selected').text();
15181        if (!UTIL.isEmpty(note)) { title += ": " + note; }
15182
15183        _setPhoneReminderSpan(jRow, status, title, callDate);
15184        _constructor.closePhoneReminder();
15185    }
15186
15187    _constructor.setPhoneReminder = function(checkbox) {		//= called when click checkbox (in reminder view).
15188        var jPhoneReminderField = $(checkbox).parent();
15189        var jRow = jPhoneReminderField.parent();
15190
15191        var dt = new Date();
15192        var strDt = dt.toGloTime();			// dt.toGloDateString(true, false, true) + ' @ ' + 
15193
15194        jPhoneReminderField.html('<span onclick="GLO.ReminderPortal.openPhoneReminder(this)" dt="' + dt + '">' + strDt + '</span>');
15195        jRow.removeClass("reminder-row-missing");
15196        
15197        var scheduleId = jRow.attr('id');
15198        var sMultiId = jRow.attr('schedule_multi_id');
15199        var scid = jRow.attr('schedule_client_id');
15200        
15201        _constructor.editPhoneReminder('', scheduleId, sMultiId, scid, '', '', '', jPhoneReminderField);
15202        _savePhoneReminderToRow(jRow, 900, '');
15203    }
15204    
15205    _constructor.editPhoneReminder = function(phoneReminderId, scheduleId, scheduleMultiId, scid, mStatus, callDt, note, jPhoneReminderField) {
15206        var url = location.protocol + '//' + location.host + '/provider/ReminderPhoneEdit_ajax?scheduleid=' + scheduleId + '&smid=' + scheduleMultiId + '&scid=' + scid
15207        			+ '&phonereminderid=' + phoneReminderId + '&mstatus=' + mStatus + '&calldt=' + callDt;
15208        
15209        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { note: note } })
15210            .success(function(data, textStatus, jqXHR) {
15211                if (UTIL.isNumber(data) && jPhoneReminderField && jPhoneReminderField.length) {
15212                	jPhoneReminderField.attr('id', data);
15213                }
15214            })
15215            .error(function(jqXHR, textStatus, errorThrown) { 
15216                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
15217            });
15218    }
15219
15220    _constructor.removePhoneReminder = function(phoneReminderId, scheduleId) {
15221        //Step I: Get Values
15222            var jModal = $('#simplemodal-container');
15223            var phoneReminderId = jModal.find('#Phone_Reminder_id').val();
15224            var scheduleId = jModal.find('#Phone_Schedule_id').val();
15225            var scid = jModal.find('#Phone_Schedule_Client_id').val();
15226            var sMultiId = jModal.find('#Phone_Schedule_Multi_id').val();
15227        
15228        //Step II: Remove value from cell & close
15229            var jRow = $('#reminder-day-view tr#' + scheduleId);
15230            jRow.attr('phone_note_vc', '');
15231            jRow.attr('phone_ms_cd', '');
15232
15233            var jPhoneColumn = jRow.find('.reminder-phone-column').attr('title', '');
15234            //jPhoneColumn.find('span').remove();
15235            jPhoneColumn.html('<input type="checkbox" value="1" name="phone-reminder' + scheduleId + '" id="phone-reminder' + scheduleId + '" onchange="GLO.ReminderPortal.setPhoneReminder(this)" title="' + SA.Resource.ReminderCallHelp + '"/>')
15236            
15237            _constructor.closePhoneReminder();
15238
15239        //Step III: Send Ajax Request
15240            var url = location.protocol + '//' + location.host + '/provider/ReminderPhoneRemove_ajax?scheduleid=' + scheduleId + '&phonereminderid=' + phoneReminderId;
15241
15242            var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
15243                .success(function(data, textStatus, jqXHR) {
15244                    if (UTIL.isNumber(data) && jPhoneReminderField !== null) { jPhoneReminderField.attr('id', data); }
15245                })
15246                .error(function(jqXHR, textStatus, errorThrown) { 
15247                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
15248                });
15249    }
15250	
15251	_constructor.setAndOpenPhoneReminder = function(el) {
15252		var thisTD = $(el).parent();
15253		var phoneTD = $(el).closest('tr').find('.reminder-phone-column');
15254        var jcheckbox = phoneTD.find(':checkbox');
15255        
15256        if (jcheckbox.length === 1) {
15257        	jcheckbox.click();
15258        	GLO.UI.Form.beginProcessing(thisTD);
15259        	
15260        	setTimeout(function() {
15261        		GLO.UI.Form.resetProcessing(thisTD);
15262        		phoneTD.find('>span').click();
15263        	}, 800);
15264        } else {
15265        	phoneTD.find('>span').click();
15266        }
15267	}
15268	
15269    _constructor.openPhoneReminder = function(el) {
15270        var jRow = $(el).closest('tr');
15271        var jTd = jRow.find('.reminder-phone-column');
15272        var el = jTd.find('>span');
15273        
15274        $('#pop-reminder-phone').modal();
15275        var jModal = $('#simplemodal-container').draggable({ "handle": "h2" });
15276        
15277        jModal.find('#Phone_Reminder_id').val(jTd.attr('id'));
15278        jModal.find('#Phone_Schedule_id').val(jRow.attr('id'));
15279        jModal.find('#Phone_Schedule_Client_id').val(jRow.attr('schedule_client_id'));
15280        jModal.find('#Phone_Schedule_Multi_id').val(jRow.attr('schedule_multi_id'));
15281        
15282        if (GLO.Info.isMobile()) {
15283        	var h2text = jRow.attr('client_vc') + ' at ' + jRow.attr('time_vc');
15284        } else {
15285        	var h2text = SA.Resource.PhoneReminderFor + ' ' + jRow.attr('client_vc') + ' ' + SA.Resource.at_text + ' ' + jRow.attr('time_vc');
15286        }
15287        
15288        jModal.find('h2').text(UTIL.htmlDecode(h2text));
15289        $.modal.setHeader();
15290        
15291        var dt = new Date(el.attr('dt'));
15292        jModal.find("#Phone_Call_dt").datepicker().val(dt.toGloDate());
15293        UI.timeMask('#simplemodal-container #Phone_Call_tm');
15294        UI.setTimeMaskValue(jModal.find("#Phone_Call_tm"), dt.toGloTime());
15295        
15296        jModal.find('#Phone_Message_Status_cd').val(jRow.attr('phone_ms_cd'));
15297        
15298        var note = jRow.attr('phone_note_vc');
15299        if (!UTIL.isEmpty(note)) { jModal.find('#Phone_Note_vc').val(note).removeClass('defaultTextActive'); }
15300
15301        if (jModal.width() < 10 || jModal.height() < 10) {
15302            $.modal.update(275, 500);
15303        }
15304
15305        jModal.find('input, select, textarea').change( function() { 
15306            jModal.find('.btnSave a').css({ "border": "3px solid Red" });
15307        });
15308    }
15309
15310    _constructor.closePhoneReminder = function() {
15311        $("#Phone_Call_dt").datepicker("hide");
15312        $("#Phone_Call_dt").datepicker("destroy");
15313        $.modal.close();
15314    }
15315
15316    return _constructor;
15317})();
15318
15319
15320GLO.Provider = (function() {
15321    function _cProvider() { }
15322    
15323    _cProvider.isValidGoldPackage = function() {
15324		if (GLO.Data.provider.packageType == 2 || GLO.Data.provider.packageType == 20 || GLO.Data.provider.packageType == 10) {
15325			if (_cProvider.isValidNextBillDate()) {
15326				return true;
15327			}
15328		}
15329		
15330		return false;
15331	}
15332	
15333	_cProvider.isValidNextBillDate = function() {
15334		if (UTIL.isDate(GLO.Data.provider.next_bill_dt)) {
15335			var dtNext = new Date(GLO.Data.provider.next_bill_dt);
15336			var dtCutoff = new Date().addDays(-14);
15337			
15338			if (dtNext > dtCutoff) {
15339				return true;
15340			}
15341		}
15342		
15343		if (GLO.Data.provider.var_cd == 3) {
15344			return true;
15345		}
15346		
15347		return false;
15348	}
15349	
15350	_cProvider.isPaidAccount = function(includeTrial) {
15351		var sd = GLO.Data.provider.signupDetail;
15352		
15353		if (GLO.Data === undefined || GLO.Data.provider === undefined) {
15354			return true;
15355		} else if (UTIL.coalesceInt(sd, 0) < 20 || sd == 40 || sd == 50 || sd == 51) {
15356			return true;
15357		} else if (includeTrial && sd == 52) {				//(sd == 52 || sd == 200)
15358			return true;
15359		} else {
15360			return false;
15361		}
15362	}
15363	
15364	_cProvider.isInCanada = function() {
15365		if (['NL','PE','NS','NB','QC','ON','MB','SK','AB','BC','YT','NT','NU'].has(GLO.Data.provider.state)) {
15366			return true;
15367		}
15368		
15369		return false;
15370	}
15371	
15372	_cProvider.isManagerCheck = function(action, jpop, checkIfExists) {
15373		if (GLO.Info.roleType > 219) {
15374			return true;
15375		} else {
15376			if (jpop) {
15377				if (checkIfExists) {
15378	        		jpop.find('.btnSave').remove();
15379	        		jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "font-weight": "bold" });
15380	        		jpop.find('input,select,textarea').prop('disabled', true);
15381	        	} else {
15382	        		GLO.Popup.close(jpop);
15383	        	}
15384        	}
15385        	
15386        	GLO.Popup.Warning.open('Must be a manager or admin edit ' + action, 'Insufficient Privilege');
15387			return false;
15388		}
15389	}
15390	
15391    return _cProvider;
15392})();
15393
15394
15395GLO.Provider.Referral = (function() {
15396    function _conRefer() { }
15397    
15398    _conRefer.init = function() {
15399        GLO.Info.init();
15400        
15401        var jrpt = $('.report-container');
15402        var jcontainer = jrpt.find('#ReferralList');
15403        SA.Upgrade.initReadOnly('referrals', jcontainer);
15404        
15405        _initData(jrpt);
15406        GLO.Report.enableFullPageCheck();
15407        GLO.Report.setupFastClick();
15408    }
15409    
15410    function _initData(jrpt) {
15411    	UI.initTableSorter(jrpt.find('.tablesorter'));
15412		GLO.Report.CellSummary.initReport(jrpt, false, true);
15413    }
15414    
15415    _conRefer.changeMinPurchase = function(thisTextBox) {
15416    	if (thisTextBox.value) {
15417    		$('#require-min-purchase').prop('checked', true);
15418    	}
15419    }
15420    
15421    _conRefer.openEdit = function(thisLink) {
15422        if (SA.Upgrade.initReadOnly('referrals')) { return; }
15423        
15424        var jPop = $('#manage-referral-popup');
15425        var ojpop = new GLO.Popup.Custom(jPop, GLO.Provider.Referral.save);
15426        
15427        jPop = ojpop.getPopup();            //.addClass('no-persist');
15428        jPop.find('.msg').append('<style> .ui-datepicker { z-index: 9999 !important; } </style>');
15429        jPop.find("#Expire_dt").datepicker({ minDate: 0 });
15430        
15431        var jbtns = jPop.find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "480px" });
15432        jbtns.find('.btnSave').css({ "margin": "0", "text-align": "center" });
15433        
15434        if (thisLink) {
15435            var tr = $(thisLink).closest('tr');
15436            _openEditPopulate(jPop, tr);
15437        }
15438        
15439        if (GLO.Provider.isManagerCheck('Referral', jPop, thisLink)) {
15440        	jPop.find('input, select, textarea').change( function() { 
15441	            $(this).closest('.glopop').find('.btnSave a').css({ "border": "3px solid Red" });
15442	        });
15443        }
15444    }
15445    
15446    function _openEditPopulate(jPop, tr) {
15447    	var jname = tr.find('.referral-column-name');
15448    	var minPurchase = tr.find('.min-purchase').text().replace('$', '');
15449        var jdiscount = tr.find('.referral-column-discount');
15450        
15451    	jPop.find('#Provider_Referral_id').val(tr.attr('provider_referral_id'));
15452        jPop.find('#Referral_Name_vc').val(UTIL.coalesce(jname.attr('title'), jname.find('a').text()));
15453
15454        jPop.find('#Coupon_Code_vc').val(tr.find('.coupon-code').text());
15455        jPop.find('#Max_Allowed_Per_Client_sr').val(tr.find('.max-allowed').text());
15456        jPop.find('#Expire_dt').val(tr.find('.expire-date').attr('dt'));
15457        
15458        if (!UTIL.isEmpty(minPurchase)) {
15459        	jPop.find('#require-min-purchase').prop('checked', true);
15460        	jPop.find('#Minimum_Purchase_mn').val(minPurchase);
15461        }
15462        
15463        var dpct = UTIL.coalesceMoney(jdiscount.attr('discount_pct'));
15464        var dmn = UTIL.coalesceMoney(jdiscount.attr('discount_mn'));
15465        
15466        jPop.find('#Discount_pct').val(dpct);
15467        jPop.find('#Discount_mn').val(dmn);
15468    }
15469    
15470    _conRefer.refresh = function() {
15471    	jbutton = $('#manage-referral-header .fa-refresh');
15472    	var jd = {};
15473    	
15474    	if (jbutton.hasClass('fa-spin')) {
15475    		return;
15476    	} else if (!GLO.Report.hasReportPassword(jd)) {
15477	    	return;
15478	    }
15479    	
15480    	jbutton.addClass('fa-spin');			//GLO.UI.Form.beginProcessing(jbutton);
15481    	
15482    	var jrpt = $('.report-container');
15483    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/referral?ispartial=1&display-expired=' + $('#manage-referral-container #Include_Inactive_fl').prop('checked');
15484    	
15485    	var jqxhr = $.ajax({ "type": "POST", "url": uri, "cache": false, "data": jd })
15486            .success(function(data, textStatus, jqXHR) {
15487                jbutton.removeClass('fa-spin');				//GLO.UI.Form.resetProcessing();
15488                
15489                jrpt.html($(data).html());
15490                _initData(jrpt);
15491            })
15492            .error(function(jqXHR, textStatus, errorThrown) {
15493            	jbutton.removeClass('fa-spin');
15494            	//jrpt.html('<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>');
15495            });
15496    }
15497    
15498    _conRefer.remove = function(thisTD) {
15499        var tr = $(thisTD).closest('tr');
15500        var referral = tr.find('.referral-column-name span').text();
15501        
15502        if (GLO.Provider.isManagerCheck('Referral')) {
15503        	GLO.Popup.Confirm(SA.Resource.RemoveConfirmQuestion + ' ' + referral + '?', function() { GLO.Provider.Referral.removeConfirmed(tr); });
15504        }
15505    }
15506
15507    _conRefer.removeConfirmed = function(tr) {
15508        if (!GLO.Provider.isManagerCheck('Referral')) { return; }
15509        
15510        var url = GLO.Link.Page.Provider.Home + 'manage/RemoveReferral';
15511        var prId = tr.attr('provider_referral_id');
15512        
15513        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_referral_id": prId } })
15514            .success(function(data, textStatus, jqXHR) {
15515                var tbl = $('#ReferralList tbody');
15516                tbl.find('tr[provider_referral_id="' + prId + '"]').remove();
15517            })
15518            .error(function(jqXHR, textStatus, errorThrown) {
15519                new GLO.Popup.Error('Unable to remove this referral at this time.  Please try again later.');
15520            });
15521    }
15522
15523    _conRefer.save = function() {
15524        if (!GLO.Provider.isManagerCheck('Referral')) { return; }
15525        if (!GLO.Info.isRequireGold()) { return false; }
15526        
15527        var jpop = $('#manage-referral-edit');
15528        var referral = jpop.find('#Referral_Name_vc').val();
15529
15530        if (UTIL.isEmpty(referral)) {
15531            GLO.Popup.Warning(SA.Resource.PleaseEnterReferralName, function() { $('#manage-referral-edit').find('#Referral_Name_vc').focus(); });
15532            return;
15533        }
15534
15535        var prId = jpop.find('#Provider_Referral_id').val();
15536        var expire = jpop.find('#Expire_dt').val();
15537        var coupon = jpop.find('#Coupon_Code_vc').val();
15538        var maxAllowed = jpop.find('#Max_Allowed_Per_Client_sr').val();
15539        
15540        //if (jpop.find('#Discount_Type_cd1').prop('checked')) { var pctDiscount = jpop.find('#Discount_pct').val(); } else { var pctDiscount = ''; }
15541        //if (jpop.find('#Discount_Type_cd2').prop('checked')) { var mnDiscount  = jpop.find('#Discount_mn').val();  } else { var mnDiscount  = ''; }
15542        
15543        var pctDiscount = jpop.find('#Discount_pct').val();
15544        var mnDiscount = jpop.find('#Discount_mn').val();
15545        
15546        var jsonRefer = {
15547                        "referral_name_vc": referral, "provider_referral_id": prId, "expire_dt": expire
15548                        , "coupon_code_vc": coupon, "max_allowed_per_client_sr": maxAllowed
15549                        , "discount_pct": pctDiscount, "discount_mn": mnDiscount
15550                    };
15551        
15552        if (jpop.find('#require-min-purchase').prop('checked')) {
15553        	jsonRefer.minimum_purchase_mn = jpop.find('#Minimum_Purchase_mn').val();
15554        }
15555        
15556        var url = GLO.Link.Page.Provider.Home + 'manage/referralSave';
15557        GLO.UI.Form.beginProcessing( jpop.closest('.glopop').find('.btnSave') );
15558
15559        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jsonRefer })
15560            .success(function(data, textStatus, jqXHR) {
15561                GLO.UI.Form.resetProcessing();
15562                GLO.Popup.close( $('#manage-referral-popup').closest('.pop-custom') );
15563
15564                var tr = $(data);
15565                var tbl = $('#ReferralList tbody');
15566
15567                tbl.find('tr[provider_referral_id="' + tr.attr('provider_referral_id') + '"]').remove();
15568                tbl.prepend(tr);
15569
15570                tbl.find('#no-referrals-row').remove();
15571            })
15572            .error(function(jqXHR, textStatus, errorThrown) {
15573                GLO.UI.Form.resetProcessing();
15574                new GLO.Popup.Error('Unable to edit this referral at this time.  Please try again later.');
15575            });
15576    }
15577    
15578    _conRefer.openHelpReferBy = function() {
15579    	var p1 = '<p>';
15580    	var msg1 = p1 + 'Can setup and track <a onclick="GLO.Uri.gotoUri2(\'report/refer\')">Referral Types</a></p>';
15581    	var msg2 = p1 + '</p>';
15582    	var msg3 = p1 + '</p>';
15583    	var msg4 = p1 + '</p>';
15584    	
15585    	var htm = '<div id="pop-help-refer">' + msg1 + msg2 + msg3 + msg4 + '</div>';
15586    	GLO.Popup.Info.open(htm, 'Refer Information');
15587    }
15588	
15589    return _conRefer;
15590})();
15591
15592
15593GLO.Provider.Advanced = (function() {
15594    function _conAdvanced() { }
15595    var _isLoading = true, _timeoutChangeEmailReminder = null, _timeoutChangeTextReminder = null, _timeoutInstantConfirmationTextReminder = null, _timeoutChangeTextReminderSecond = null;
15596    
15597    _conAdvanced.init = function() {
15598        _initAddTabs();
15599        
15600        var j = $('#advanced-options');
15601        
15602        if (false && SA.App.isWKWebView()) {				//toDo: Mar 2017!!!
15603			j.find('#sa-rate-app').removeClass('hide');
15604			j.find('#sa-share-app').removeClass('hide');
15605		}
15606		
15607		_conAdvanced.initReadOnlyCheck();
15608		_conAdvanced.Payment.init();
15609		_initUrlAction(true);
15610		_initTextFields(j);
15611		_initCalendarOptions(true);
15612		_initOnlineBookingOptions();
15613		
15614		var jclient = $('#advanced-options #page-client');
15615		_conAdvanced.initClientOptions(jclient);
15616		_isLoading = false;
15617		
15618		jscolor.init();
15619		GLO.Inventory.initHeaderHelpIcon();
15620    }
15621    
15622    _conAdvanced.initClientOptions = function(jclient) {
15623    	jclient.find('#Text_Reminder_fl').click(function() { UI.changeFocus(this, 'Text_Reminder_Hr_sr'); });
15624    	jclient.find('#Text2_Reminder_fl').click(function() { UI.changeFocus(this, 'Text2_Reminder_Hr_sr'); });
15625        jclient.find('#Email_Reminder_fl').click(function() { UI.changeFocus(this, 'Email_Reminder_Day_sr'); });
15626        
15627        jclient.find('#Text_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text_Reminder_fl'); }).change();
15628        jclient.find('#Text2_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text2_Reminder_fl'); }).change();
15629        jclient.find('#Email_Reminder_Day_sr').change(function() { UI.markCheckbox(this, 'Email_Reminder_fl'); }).change();
15630        
15631        jclient.find('#Email_Reminder_Day_sr').change();
15632        jclient.find("input:checkbox").change(UI.CrossOutCheckbox).change();
15633    }
15634    
15635    function _initOnlineBookingOptions(isInit) {
15636    	var j = $('#advanced-options');
15637    	var jBookEvery = j.find('#cc-book-every-row');
15638    	var be = jBookEvery.attr('avg_book_every');
15639    	
15640    	if (!UTIL.isEmpty(be)) {
15641    		jBookEvery.removeAttr('avg_book_every');
15642    		jBookEvery.find('option[value="' + be + '"]').prop('selected', true);
15643    	}
15644    	
15645    	var jonline = j.find('#advanced-online-booking');
15646    	var waitListClientPortalStart = UTIL.coalesceInt(jonline.attr('wait_list_start_cd')), waitListClientPortalEnd = UTIL.coalesceInt(jonline.attr('wait_list_end_cd'));
15647    	
15648    	jonline.find('#Wait_List_Start_cd').val(waitListClientPortalStart);
15649    	jonline.find('#Wait_List_End_cd').val(waitListClientPortalEnd);
15650    	
15651    	var enableToday = jonline.find('#Enable_Wait_List_Today_fl').prop('checked'), enableClientAccess = jonline.find('#Enable_Wait_List_fl').prop('checked');
15652    	
15653    	if (!enableClientAccess) { _conAdvanced.Online.greyClientAccess(enableClientAccess); }
15654	    if (!enableToday) { _conAdvanced.Online.greyToday(enableToday); }
15655    }
15656
15657	function _toggleEasyLoginSetting(loginFormType) {
15658		return false;
15659		
15660		/* if (loginFormType == '10') {
15661			$('#easy-login-form').removeClass('hide');
15662		} else {
15663			$('#Easy_Login_fl').prop('checked', false); // Unchecks it
15664			$('#easy-login-form').addClass('hide');
15665		} */
15666	}
15667    
15668    function _initCalendarOptions(isPageLoad) {
15669    	var j = $('#advanced-calendar');
15670    	
15671    	if (j.find('#Display_Running_Total_fl').prop('checked')) {
15672    		j.find('#row-running-total-order').removeClass('hide');
15673    	} else {
15674    		j.find('#row-running-total-order').addClass('hide');
15675    	}
15676    	
15677    	if (isPageLoad) {
15678    		j.find('#First_Available_Width_sr').val(j.find('#First_Available_Width_sr').attr('original_value'));
15679    		
15680    		var isKeypadDevice = $.cookies.get('is-keypad-device');
15681    		var divTouchScreen = $('#advanced-feature-this-device-enable-keypad').removeClass('hideX');
15682    		
15683    		divTouchScreen.find('#Touch_Screen_fl').prop('checked', UTIL.parseBool(isKeypadDevice));
15684    		//if (!UTIL.isEmpty(isKeypadDevice)) { divTouchScreen.find('#Touch_Screen_fl').prop('checked', UTIL.parseBool(isKeypadDevice)); }
15685    		
15686    		var jThisDeviceCalSize = $('#advanced-this-device-cal-header-size').removeClass('hideX').find('#This_Device_Calendar_Header_Size_cd');
15687    		var size = $.cookies.get('cal-header-size');
15688    		
15689    		if (jThisDeviceCalSize.length && !UTIL.isEmpty(size)) {
15690    			jThisDeviceCalSize.val(size);
15691    		}
15692    		
15693    		if (GLO.staffResources.length > 9 && !GLO.Info.isIPad) {				///later also enable for resource calendar based on -> SA.Data.resourceJson.resources.length
15694    			var jThisDeviceCalSticky = $('#advanced-this-device-cal-header-sticky').removeClass('hideX');
15695    			var isSticky = UTIL.parseBool($.cookies.get('is-cal-header-sticky'));
15696    			jThisDeviceCalSticky.find('#This_Device_Calendar_Sticky_Header_fl').prop('checked', isSticky);
15697    		}
15698    		
15699    		_conAdvanced.Calendar.setAppointmentNotRequestColor(true);
15700    	}
15701    }
15702    
15703    function _initTextFields(jcontainer) {
15704    	var jfield = jcontainer.find('#Create_Appt_Hr_nr');
15705		_initTextField(jfield);
15706		
15707		var jfield = jcontainer.find('#Update_Appt_Hr_nr');
15708		_initTextField(jfield);
15709		
15710		var jfield = jcontainer.find('#Search_Result_Limit_sr');
15711		_initTextField(jfield);
15712		
15713		var jfield = jcontainer.find('#Email_Notify_Day_sr');
15714		_initTextField(jfield);
15715		
15716		var jfield = jcontainer.find('#Text_Notify_Hr_sr');
15717		_initTextField(jfield);
15718		
15719		var jfield = jcontainer.find('#Today_Wait_List_Max_nr');
15720		_initTextField(jfield);
15721    }
15722    
15723    function _initTextField(jfield) {
15724    	var uriSave = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedFields';
15725		var fnAfterSave = function() { GLO.Provider.Advanced.afterSaveFieldText(jfield); };
15726		new UI.AutoSave(jfield, uriSave, fnAfterSave, 2800);
15727    }
15728    
15729    _conAdvanced.initReadOnlyCheck = function() {
15730    	GLO.Info.init();
15731    	
15732    	if (!GLO.Provider.isPaidAccount(true)) {
15733    		var arrow = '<b class="arrow-right">&#10140;</b>';
15734    		var btnUpdateCard = '<span class="btnAdd btnAdd2"> <a onclick="GLO.Uri.gotoUri(\'provider/profile/6\', this, event, true)">Profile ' + arrow + ' My Account</a> </span>';
15735    		
15736    		var apaid = '<a onclick="GLO.Uri.gotoUri(\'/hello/pricing\', this, event, true)" style="border-bottom: none;">';
15737    		var msg2 = '<p>A ' + apaid + 'paid package</a> is required to change the Advanced Settings</p>' + '<p>Update your card by going to ' + btnUpdateCard + '</p>';
15738    		var btnCSS = 'position: absolute; left: 8px; font-family: Georgia;';
15739    		
15740    		if (GLO.Info.providerPackage === 2) {
15741    			var btn = '<span class="btnAdd btnAdd2" style="' + btnCSS + '"> <a onclick="GLO.Uri.gotoUri(\'provider/profile/6\', this, event, true)">Update Card</a> </span>';
15742    		} else {
15743    			msg2 += '<p style="min-width: 300px; font-weight: bold;">' + apaid + 'Press here to checkout our different packages</a></p>';
15744    			
15745    			var btn = '<span class="btnAdd btnAdd2" style="' + btnCSS + '"> <a onclick="GLO.Uri.gotoUri(\'/hello/pricing\', this, event, true)">Paid Packages</a> </span>';
15746    		}
15747    	} else if (GLO.Info.roleType < 220) {
15748    		var msg2 = '<p>Only a manager or admin user can change an Advanced Setting</p>';
15749    		var btn = null;
15750    	} else {
15751    		return;
15752    	}
15753    	
15754    	var msg1 = '<p>You are welcome to checkout the ' + GLO.Info.getScheduleAnyoneHtm() + ' advanced settings</p>';
15755    	var jinput = $('#advanced-options').find('input, select');
15756    	
15757    	for (var i=0; i < jinput.length; i++) {
15758    		jinput.prop('disabled', true);
15759    	}
15760    	
15761    	var h1 = '<b style="font-size: larger;">Read Only Mode</b>';
15762    	var jpop = _conAdvanced.Help.open(h1, msg1 + msg2);
15763    	
15764    	if (innerWidth > 600) {
15765    		jpop.find('.msg').find('p').css({ "text-align": "center" });
15766    	}
15767    	
15768    	if (btn) {
15769    		var jbtns = jpop.find('.pop-buttons').css({ "position": "relative" });
15770    		jbtns.prepend(btn);
15771    		jbtns.find('.btnCancel').addClass('btnClick').css({ "position": "absolute", "right": "8px", "width": "64px", "font-size": "100%" });
15772    	}
15773    }
15774    
15775    function _initUrlAction(isInit) {
15776    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
15777    	var popup = UTIL.cleanString(GLO.Uri.url('popup')).toLowerCase();
15778    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
15779    	var step = GLO.Uri.url('step');
15780    	
15781    	if (isInit && UTIL.isEmpty(open)) { open = 'tab-online-booking'; }
15782    	
15783    	if (!UTIL.isEmpty(open)) {
15784    		var jtab = $('.advanced-tabs').find('#' + open);
15785    		
15786    		if (jtab.length > 0) {
15787    			jtab.click();
15788    		} else {
15789    			$('.advanced-tabs').find('td:first').click();
15790    		}
15791    	}
15792    	
15793    	if (popup == 'anon-search') {
15794    		GLO.Provider.Advanced.Online.confirmAllowAnon();
15795    	//} else if (popup == 'how-online-booking-works') {
15796    	//	GLO.Provider.Advanced.Help.Online.openAppointmentSearch();
15797    	} else if (popup == 'client-address-help') {
15798    		GLO.Provider.Advanced.Help.Client.openAddressConfig();
15799    	} else if (popup == 'how-to-guide-reports' || popup == 'how-to-guide-report' || popup == 'help-report-overview') {
15800    		SA.Menu.openReportHelp(step);
15801    	} else if (popup == 'how-to-guide-payroll' || popup == 'help-commission') {
15802    		GLO.Provider.Commission.openReportHelp(step);
15803    	} else if (popup == 'membership-setup-how-to' || popup == 'how-to-guide-membership') {
15804    		GLO.Provider.Membership.Help.openHowToSetup(step);
15805    	} else if (popup == 'how-to-guide-client-list' || popup == 'client-list-help') {
15806    		GLO.Message.Bulk.openHelp(step);
15807    	} else if (popup == 'how-to-guide-message' || popup == 'message-help-pop-container') {
15808    		GLO.Message.Marketing.openHelp(step);
15809    	} else if (popup == 'how-to-guide-online-booking') {
15810    		GLO.Provider.Advanced.Help.Online.openOnlineBookingGuide(step);
15811    	} else if (!UTIL.isEmpty(popup)) {
15812    		var jPopTrigger =$('#advanced-options #' + popup);
15813    		
15814    		if (!UTIL.isEmpty(jPopTrigger.attr('onclick'))) {
15815    			jPopTrigger.click();
15816    		} else {
15817    			jPopTrigger.find('a').click();
15818    		}
15819    	}
15820    	
15821    	if (!UTIL.isEmpty(highlight)) {
15822    		setTimeout(function() {
15823	    		var jhighlight = $('#advanced-options').find('#' + highlight);
15824	    		
15825	    		if (jhighlight.length > 0) {
15826	    			UI.highlight(jhighlight, 800, 6400, true);
15827	    		}
15828	    	}, 1200);
15829    	}
15830    }
15831    
15832    function _initAddTabs() {
15833    	if (innerWidth < 480) {
15834    		var labelAppt = 'Appt', labelPay = 'Pay', labelOnlineBooking = 'Booking';
15835    	} else {
15836    		var labelAppt = 'Appointments', labelPay = 'Payment', labelOnlineBooking = 'Online Booking';
15837    	}
15838    	
15839    	var j = $('.shadow0');
15840    	var tabHtm = '<td id="tab-appointment"><span>' + labelAppt + '</span></td>'
15841					+ '<td id="tab-payment"><span>' + labelPay + '</span></td>'
15842					+ '<td id="tab-online-booking"><span>' + labelOnlineBooking + '</span></td>'
15843					+ '<td id="tab-client"><span>Clients</span></td>'
15844					+ '<td id="tab-location"><span>Locations</span></td>'
15845					+ '<td id="tab-help"><span>Help</span></td>';
15846		
15847    	j.before('<div class="advanced-tabs"><table><tbody><tr>' + tabHtm + '</tr></tbody></table></div>');
15848    	$('.advanced-tabs').find('td').click(GLO.Provider.Advanced.goToPageFromTab);
15849    }
15850    
15851    _conAdvanced.goToItem = function(tab, highlight, element) {
15852    	var jadvanced = $('#doc3 #advanced-options');
15853    	var isAdvancedScreen = jadvanced.length;
15854    	
15855    	GLO.Popup.close();
15856    	
15857    	if (isAdvancedScreen) {
15858    		$('#advanced-tabs').find('#tab-' + tab).click();
15859    		
15860    		if (!UTIL.isEmpty(highlight)) {
15861    			var jhigh = jadvanced.find('#' + highlight);
15862    			UI.highlight(jhigh, 800, 6400, true);
15863    		}
15864    	} else {
15865    		var url = document.location.origin + '/provider/manage/advanced?open=tab-' + UTIL.coalesceString(tab, '') + '&highlight=' + UTIL.coalesceString(highlight, '');
15866    		
15867    		setTimeout(function() {
15868    			GLO.Uri.gotoUriWithSpinner(url, element, event, true);
15869    		}, 100);
15870    	}
15871    }
15872    _conAdvanced.goToPageFromTab = function() {
15873    	$('.advanced-tabs').find('.wiz-tab').removeClass('wiz-tab');
15874    	
15875    	var id = $(this).addClass('wiz-tab').attr('id').replace('tab-', 'page-');
15876    	
15877    	$('#advanced-options').find('.wiz-page').removeClass('wiz-page');
15878    	$('#advanced-options').find('#' + id).addClass('wiz-page');
15879    }
15880    
15881    _conAdvanced.changeConfirmOnCreate = function(element, event) {
15882    	if (_isLoading) { return; }
15883    	if (!_conAdvanced.canSaveChanges()) { return; }
15884    	
15885    	if (GLO.Info.providerPackage == 1) {
15886    		GLO.Provider.Advanced.saveField(element, event);
15887    		return;
15888    	}
15889    	
15890    	var jclient = $('#advanced-client');
15891    	var yesCount = jclient.attr('send_confirmation_email_count_sr');
15892    	
15893    	if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; }
15894    	
15895    	var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)';
15896    	var msg = '<p style="font-weight: bold;">Do you want to send clients a confirmation email when an appointment is created?</p>'
15897    			+ '<p><a onclick="' + link + '" style="font-size: smaller;">Current ' + yesCount + ' of your staff are setup to send confirmation emails to clients when an appointment is created</a></p>';
15898    	
15899    	var htm = '<div id="pop-confirm-email"> <h1 class="friendly-msg">Send Confirmation Email?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
15900    	
15901    	var fnYes = function() { GLO.Provider.Advanced.changeConfirmOnCreate2(element, event, true); }
15902    	var fnNo = function() { GLO.Provider.Advanced.changeConfirmOnCreate2(element, event, false); }
15903    	var jpop = new GLO.Popup.Confirm(htm, fnYes, fnNo).getPopup();
15904    	
15905    	var btnCancel = '<span class="btnCancel" style="position: inherit;">
15905<a onclick="GLO.Provider.Advanced.cancelCheckboxChange(\'' + $(element).attr('id') + '\', event)">Do Nothing</a></span>';
15906    	var jbtns = jpop.find('.pop-buttons-parent').addClass('pop-buttons-parent-responsive');
15907    	jbtns.find('.btnNo').addClass('btnDelete').removeClass('btnNo').css({ "width": "60px" }).after(btnCancel);
15908    	jbtns.find('.btnYes').addClass('btnSave').removeClass('btnYes').css({ "width": "60px" });
15909    }
15910    
15911    _conAdvanced.cancelCheckboxChange = function(checkboxId, event) {
15912    	var jcheckbox = $('#advanced-options').find('#' + checkboxId);
15913    	
15914    	_isLoading = true;
15915    	jcheckbox.prop('checked', !jcheckbox.prop('checked')).change();
15916    	_isLoading = false;
15917    	
15918    	GLO.Popup.close();
15919    }
15920    
15921    _conAdvanced.changeConfirmOnUpdate = function(element, event) {
15922		if (_isLoading) { return; }
15923    	if (!_conAdvanced.canSaveChanges()) { return; }
15924    	
15925    	if (GLO.Info.providerPackage == 1) {
15926    		GLO.Provider.Advanced.saveField(element, event);
15927    		return;
15928    	}
15929    	
15930    	var jclient = $('#advanced-client');
15931    	var yesCount = jclient.attr('confirm_on_update_count_sr');
15932    	
15933    	if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; }
15934    	
15935    	var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)';
15936    	var msg = '<p style="font-weight: bold;">Do you want to send clients a confirmation email when an appointment is UPDATED?</p>'
15937    			+ '<p><a onclick="' + link + '" style="font-size: smaller;">Current ' + yesCount + ' of your staff are setup to send confirmation emails to clients when an appointment is UPDATED</a></p>';
15938    	
15939    	var htm = '<div id="pop-confirm-email"> <h1 class="friendly-msg">Send Confirmation Email?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
15940    	
15941    	var fnYes = function() { GLO.Provider.Advanced.changeConfirmOnUpdate2(element, event, true); }
15942    	var fnNo = function() { GLO.Provider.Advanced.changeConfirmOnUpdate2(element, event, false); }
15943    	var jpop = new GLO.Popup.Confirm(htm, fnYes, fnNo).getPopup();
15944    	
15945    	var btnCancel = '<span class="btnCancel" style="position: inherit;"><a onclick="GLO.Provider.Advanced.cancelCheckboxChange(\'' + $(element).attr('id') + '\', event)">Do Nothing</a></span>';
15946    	var jbtns = jpop.find('.pop-buttons-parent').addClass('pop-buttons-parent-responsive');
15947    	jbtns.find('.btnNo').addClass('btnDelete').removeClass('btnNo').css({ "width": "60px" }).after(btnCancel);
15948    	jbtns.find('.btnYes').addClass('btnSave').removeClass('btnYes').css({ "width": "60px" });
15949	}
15950	
15951	_conAdvanced.changeConfirmOnCreate2 = function(element, event, isSend) {
15952    	var jclient = $('#advanced-client');
15953    	
15954    	_isLoading = true;
15955    	jclient.find('#Send_Confirmation_Email_fl').prop('checked', isSend).change();
15956    	_isLoading = false;
15957    	
15958    	if (isSend) {
15959    		jclient.attr('send_confirmation_email_count_sr', jclient.attr('staff_count_sr'));
15960    	} else {
15961    		jclient.attr('send_confirmation_email_count_sr', 0).attr('confirm_on_update_count_sr', 0);
15962    		
15963    		_isLoading = true;
15964	    	jclient.find('#Confirm_On_Update_fl').prop('checked', false).change();
15965	    	_isLoading = false;
15966    	}
15967    	
15968    	GLO.Provider.Advanced.saveField(element, event);
15969    }
15970	
15971	_conAdvanced.changeConfirmOnUpdate2 = function(element, event, isSend) {
15972    	var jclient = $('#advanced-client');
15973    	
15974    	_isLoading = true;
15975    	jclient.find('#Confirm_On_Update_fl').prop('checked', isSend).change();
15976    	_isLoading = false;
15977    	
15978    	if (isSend) {
15979    		jclient.attr('confirm_on_update_count_sr', jclient.attr('staff_count_sr'));
15980    	} else {
15981    		jclient.attr('confirm_on_update_count_sr', 0);
15982    	}
15983    	
15984    	GLO.Provider.Advanced.saveField(element, event);
15985    }
15986	
15987	_conAdvanced.changeEmailReminder = function(element, event) {
15988		if (_isLoading) { return; }
15989		if (!_conAdvanced.canSaveChanges()) { return; }
15990		
15991		clearTimeout(_timeoutChangeEmailReminder);
15992		if ($('#pop-confirm-email-reminder').closest('.glopop').length > 0) { return; }
15993		
15994		var jclient = $('#advanced-client');
15995		var fl = jclient.find('#Email_Reminder_fl');
15996		var isChecked = fl.prop('checked');
15997		var txt = jclient.find('#Email_Reminder_Day_sr');
15998		var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)';
15999    	
16000		if (isChecked && UTIL.coalesceInt(txt.val(), 0) === 0) { return; }
16001		if (txt.attr('original_value') === txt.val() && element.type === 'text') { return; }
16002		
16003		if (!isChecked) {
16004			var msg = '<p style="font-weight: bold; color: red;">Turn off email reminders for all appointments?</p>';
16005		} else {
16006			var msg = '<p style="font-weight: bold; color: green;">For all appointments, send email reminders to clients ' + txt.val() + ' days before the appointment?</p>';
16007		}
16008		
16009		var yesCount = jclient.attr('count_email_reminder_hr_sr');
16010    	if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; }
16011    	
16012		msg += '<p><a onclick="' + link + '" style="font-size: smaller;">Current ' + yesCount + ' of your staff are setup to send email reminders to clients</a></p>';
16013		
16014		var htm = '<div id="pop-confirm-email-reminder"> <h1 class="friendly-msg">Update Email Reminders?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
16015		
16016		var fnYes = function() { GLO.Provider.Advanced.changeEmailReminder2(element, event, isChecked); }
16017		var jpop = new GLO.Popup.Confirm(htm, fnYes);
16018	}
16019	
16020	_conAdvanced.changeTextReminder = function(element, event) {
16021		if (_isLoading) { return; }
16022		if (!_conAdvanced.canSaveChanges()) { return; }
16023		
16024		clearTimeout(_timeoutChangeTextReminder);
16025		if ($('#pop-confirm-text-reminder').closest('.glopop').length > 0) { return; }
16026		
16027		var jclient = $('#advanced-client');
16028		var fl = jclient.find('#Text_Reminder_fl');
16029		var isChecked = fl.prop('checked');
16030		var txt = jclient.find('#Text_Reminder_Hr_sr');
16031		var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config&highlight=report-column-remind-text", this)';
16032    	
16033		if (isChecked && UTIL.coalesceInt(txt.val(), 0) === 0) { return; }
16034		if (txt.attr('original_value') === txt.val() && element.type === 'text') { return; }
16035		
16036		if (jclient.attr('staff_count_sr') == 1 || GLO.Info.providerPackage === 1) {
16037			GLO.Provider.Advanced.changeTextReminder2(element, event, isChecked);
16038			return;
16039		}
16040		
16041		if (!isChecked) {
16042			var msg = '<p style="font-weight: bold; color: red;">Turn off text reminders for all appointments?</p>';
16043		} else {
16044			var msg = '<p style="font-weight: bold; color: green;">For all appointments, send text reminders to clients ' + txt.val() + ' hours before the appointment?</p>';
16045		}
16046		
16047		var yesCount = jclient.attr('count_text_reminder_hr_sr');
16048    	if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; }
16049    	
16050		msg += '<p><a onclick="' + link + '" style="font-size: smaller;">Currently ' + yesCount + ' of your staff are setup to send text reminders to clients</a></p>';
16051		
16052		var htm = '<div id="pop-confirm-text-reminder"> <h1 class="friendly-msg">Update Text Reminders?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
16053		
16054		var fnYes = function() { GLO.Provider.Advanced.changeTextReminder2(element, event, isChecked); }
16055		var jpop = new GLO.Popup.Confirm(htm, fnYes);
16056	}
16057	
16058	_conAdvanced.keyUpTextReminderSecond = function(element, event) {
16059    	if (_isLoading) { return; }
16060		
16061		clearTimeout(_timeoutChangeTextReminderSecond);
16062    	
16063    	if (UTIL.coalesceInt(element.value, 0) > 0) {
16064    		var jbox = $('#advanced-client #Text2_Reminder_fl');
16065    		
16066    		if (!jbox.prop('checked')) {
16067    			_isLoading = true;
16068    			jbox.prop('checked', true);
16069    			_isLoading = false;
16070    		}
16071    	}
16072    	
16073    	_timeoutChangeTextReminderSecond = setTimeout(function() {
16074    		_conAdvanced.changeTextReminderSecond(element, event);
16075    	}, 1500);
16076	}
16077	_conAdvanced.changeTextReminderSecond = function(element, event) {
16078		if (_isLoading) { return; }
16079		if (!_conAdvanced.canSaveChanges()) { return; }
16080		
16081		clearTimeout(_timeoutChangeTextReminderSecond);
16082		if ($('#pop-confirm-text-reminder2').closest('.glopop').length > 0) { return; }
16083		
16084		var jclient = $('#advanced-client');
16085		var fl = jclient.find('#Text2_Reminder_fl');
16086		var isChecked = fl.prop('checked');
16087		var txt = jclient.find('#Text2_Reminder_Hr_sr');
16088		var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config&highlight=report-column-remind-text2", this)';
16089    	
16090		if (isChecked && UTIL.coalesceInt(txt.val(), 0) === 0) { return; }
16091		if (txt.attr('original_value') === txt.val() && element.type === 'text') { return; }
16092		
16093		if (jclient.attr('staff_count_sr') == 1 || GLO.Info.providerPackage === 1) {
16094			GLO.Provider.Advanced.changeTextReminderSecond2(element, event, isChecked);
16095			return;
16096		}
16097		
16098		if (!isChecked) {
16099			var msg = '<p style="font-weight: bold; color: red;">Turn off text reminders #2 for all appointments?</p>';
16100		} else {
16101			var msg = '<p style="font-weight: bold; color: green;">For all appointments, send text reminders #2 to clients ' + txt.val() + ' hours before the appointment?</p>';
16102		}
16103		
16104		var yesCount = jclient.attr('count_text2_reminder_hr_sr');
16105    	if (yesCount == jclient.attr('staff_count_sr')) { yesCount = 'all'; }
16106    	
16107		msg += '<p><a onclick="' + link + '" style="font-size: smaller;">Currently ' + yesCount + ' of your staff are setup to send text reminders #2 to clients</a></p>';
16108		
16109		var htm = '<div id="pop-confirm-text-reminder2"> <h1 class="friendly-msg">Update Text Reminders #2?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
16110		
16111		var fnYes = function() { GLO.Provider.Advanced.changeTextReminderSecond2(element, event, isChecked); }
16112		var jpop = new GLO.Popup.Confirm(htm, fnYes);
16113	}
16114	_conAdvanced.changeTextReminderSecond2 = function(element, event, isChecked) {
16115    	var jclient = $('#advanced-client');
16116    	var isSend = jclient.find('#Text2_Reminder_fl').prop('checked');
16117    	var jelement = jclient.find('#Text2_Reminder_Hr_sr');
16118    	var hasMessagePackage = UTIL.parseBool(jclient.find('#cc-text-reminder2').attr('hasMessagePackage'));
16119    	
16120    	clearTimeout(_timeoutChangeTextReminderSecond);
16121    	
16122    	if (!isChecked) {
16123    		jelement.val('');
16124    	} else if (!_isValidTextReminderHr(true)); {
16125    		return;
16126    	}
16127    	
16128    	if (!hasMessagePackage) {
16129    		var label = '<b class="narrow-text">A Second Text Reminder for each Appointment</b>';
16130    		var link = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/message?helloback=advanced&tabback=client&highlight=cc-text-reminder2")\'>Message Plan</a>';
16131    		
16132    		var msg1 = '<p style="margin-bottom: 32px;">To enable ' + label + ' please enable the ' + link + ' <b class="narrow-text">Pay as Use</b> or another <b class="narrow-text">Message Plan</b></p>';
16133    		var msg2 = '<p>Text reminders cost 1 cent per message</p>';
16134    		var msg3 = '<p>Email reminders are free</p>';
16135    		
16136    		var htm = '<div id="pop-warn-staff-text-alerts-require-message-package">' + msg1 + msg2 + msg3 + '</div>';
16137    		var jpop = GLO.Popup.Warning.open(htm, 'Text Reminder #2 - Requires Message Package');
16138    		//GLO.Popup.Custom.singleButton(jpop, 'Close');
16139    		
16140    		jclient.find('#Text2_Reminder_fl').prop('checked', false);
16141    		jclient.find('#Text2_Reminder_Hr_sr').val('');
16142    		return;
16143    	}
16144    	
16145    	if (isSend) {
16146    		jclient.attr('count_text2_reminder_hr_sr', jclient.attr('staff_count_sr'));
16147    	} else {
16148    		jclient.attr('count_text2_reminder_hr_sr', 0);
16149    	}
16150    	
16151    	GLO.Provider.Advanced.saveField(jelement[0], event);
16152    }
16153	
16154	_conAdvanced.changeInstantTextConfirmation = function(element, event) {
16155		if (_isLoading) { return; }
16156		if (!_conAdvanced.canSaveChanges()) { return; }
16157		
16158		// clearTimeout(_timeoutInstantConfirmationTextReminder);
16159		if ($('#pop-confirm-instant-text-confirmation').closest('.glopop').length > 0) { return; }
16160		
16161		var jclient = $('#advanced-client');
16162		var fl = jclient.find('#Is_Send_Instant_Text_Confirmation_fl');
16163		var isChecked = fl.prop('checked');
16164
16165		var link = 'GLO.Uri.gotoUri("reports/StaffProfile?helloback=advanced&tabback=client#tab=report-client-config", this)';
16166    	
16167		if (jclient.attr('staff_count_sr') == 1 || GLO.Info.providerPackage === 1) {
16168			GLO.Provider.Advanced.changeInstantTextConfirmation2(element, event, isChecked);
16169			return;
16170		}
16171		
16172		if (!isChecked) {
16173			var msg = '<p style="font-weight: bold; color: red;">Turn off instant text confirmations for all appointments?</p>';
16174		} else {
16175			var msg = '<p style="font-weight: bold; color: green;">For all appointments created by staff, send text confirmations to clients immediately?</p>';
16176			msg += '<p><a onclick="' + link + '" style="font-size: smaller;">*Requires a paid message plan</a></p>';
16177		}
16178
16179		
16180		var htm = '<div id="pop-confirm-instant-text-confirmation"> <h1 class="friendly-msg">Update Instant Text Confirmation?</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
16181		
16182		var fnYes = function() { GLO.Provider.Advanced.changeInstantTextConfirmation2(element, event, isChecked); }
16183		var jpop = new GLO.Popup.Confirm(htm, fnYes);
16184	}	
16185
16186	_conAdvanced.changeReserveWithGoogle = function(element, event) {
16187		if (_isLoading) { return; }
16188		if (!_conAdvanced.canSaveChanges()) { return; }
16189		
16190		var jclient = $('#advanced-client');
16191		var jelement = jclient.find('#Reserve_with_Google_fl');
16192
16193		GLO.Provider.Advanced.saveField(jelement[0], event);
16194		
16195	}
16196
16197	_conAdvanced.keyUpEmailReminder = function(element, event) {
16198		if (_isLoading) { return; }
16199		
16200		clearTimeout(_timeoutChangeEmailReminder);
16201    	
16202    	if (UTIL.coalesceInt(element.value, 0) > 0) {
16203    		var jbox = $('#advanced-client #Email_Reminder_fl');
16204    		
16205    		if (!jbox.prop('checked')) {
16206    			_isLoading = true;
16207    			jbox.prop('checked', true);
16208    			_isLoading = false;
16209    		}
16210    	}
16211    	
16212    	_timeoutChangeEmailReminder = setTimeout(function() {
16213    		_conAdvanced.changeEmailReminder(element, event);
16214    	}, 1500);
16215	}
16216    
16217    _conAdvanced.keyUpTextReminder = function(element, event) {
16218    	if (_isLoading) { return; }
16219		
16220		clearTimeout(_timeoutChangeTextReminder);
16221    	
16222    	if (UTIL.coalesceInt(element.value, 0) > 0) {
16223    		var jbox = $('#advanced-client #Text_Reminder_fl');
16224    		
16225    		if (!jbox.prop('checked')) {
16226    			_isLoading = true;
16227    			jbox.prop('checked', true);
16228    			_isLoading = false;
16229    		}
16230    	}
16231    	
16232    	_timeoutChangeTextReminder = setTimeout(function() {
16233    		_conAdvanced.changeTextReminder(element, event);
16234    	}, 1500);
16235	}
16236	
16237	_conAdvanced.changeEmailReminder2 = function(element, event, isChecked) {
16238    	var jclient = $('#advanced-client');
16239    	var isSend = jclient.find('#Email_Reminder_fl').prop('checked');
16240    	var jelement = jclient.find('#Email_Reminder_Day_sr');
16241    	
16242    	clearTimeout(_timeoutChangeEmailReminder);
16243    	
16244    	if (!isChecked) {
16245    		jelement.val('');
16246    	}
16247    	
16248    	if (isSend) {
16249    		jclient.attr('count_email_reminder_hr_sr', jclient.attr('staff_count_sr'));
16250    	} else {
16251    		jclient.attr('count_email_reminder_hr_sr', 0);
16252    	}
16253    	
16254    	GLO.Provider.Advanced.saveField(jelement[0], event);
16255    }
16256	
16257	function _isValidTextReminderHr(isSecondText) {
16258		var jclient = $('#advanced-client');
16259    	var isSend = jclient.find('#Text_Reminder_fl').prop('checked');
16260    	var isSend2 = jclient.find('#Text2_Reminder_fl').prop('checked');
16261    	var textHr = jclient.find('#Text_Reminder_Hr_sr').val();
16262    	var textHr2 = jclient.find('#Text2_Reminder_Hr_sr').val();
16263    	
16264    	if (isSend && isSend2 && Math.abs(textHr - textHr2) < 8) {
16265    		var msg1 = '<p>Text Reminder #1 (' + UTIL.pluralLabel(textHr, 'hour') + ') and Text Reminder #2 (' + UTIL.pluralLabel(textHr2, 'hour') + ') must be 8 or more hours apart</p>';
16266    		var msg2 = '<p>Please change the Text Reminder or Text Reminder #2 hours sent before appointment</p>';
16267    		var htm = '<div id="pop-warning-text-reminder-hour">' + msg1 + msg2 + '</div>';
16268    		
16269    		var fn = function() {
16270    			if (isSecondText) {
16271    				var jhr = $('#advanced-client #Text2_Reminder_Hr_sr');
16272    			} else {
16273    				var jhr = $('#advanced-client #Text_Reminder_Hr_sr');
16274    			}
16275    			
16276    			UI.highlight(jhr);
16277    			jhr.focus();
16278    		};
16279    		
16280    		GLO.Popup.Warning.open(htm, 'Invalid Text Reminder Setting', fn);
16281    		return false;
16282    	}
16283    	
16284    	return true;
16285	}
16286	
16287    _conAdvanced.changeTextReminder2 = function(element, event, isChecked) {
16288    	var jclient = $('#advanced-client');
16289    	var isSend = jclient.find('#Text_Reminder_fl').prop('checked');
16290    	var jelement = jclient.find('#Text_Reminder_Hr_sr');
16291    	
16292    	clearTimeout(_timeoutChangeTextReminder);
16293    	
16294    	if (!isChecked) {
16295    		jelement.val('');
16296    	} else if (!_isValidTextReminderHr(false)) {
16297    		return;
16298    	}
16299    	
16300    	if (isSend) {
16301    		jclient.attr('count_text_reminder_hr_sr', jclient.attr('staff_count_sr'));
16302    	} else {
16303    		jclient.attr('count_text_reminder_hr_sr', 0);
16304    	}
16305    	
16306    	GLO.Provider.Advanced.saveField(jelement[0], event);
16307    }
16308    
16309    _conAdvanced.changeInstantTextConfirmation2 = function(element, event, isChecked) {
16310    	var jclient = $('#advanced-client');
16311    	var jelement = jclient.find('#Is_Send_Instant_Text_Confirmation_fl');
16312    	// var jelement = jclient.find('#Text_Reminder_Hr_sr');
16313    	
16314    	// clearTimeout(_timeoutInstantConfirmationTextReminder);
16315    	
16316    	GLO.Provider.Advanced.saveField(jelement[0], event);
16317    }
16318    
16319    _conAdvanced.setIsKeypadDevice = function(checkbox) {
16320    	if (checkbox.checked) {
16321    		var label = 'Use On-Screen Keyboard';
16322    		var isKeypadDevice = '1';
16323    	} else {
16324    		var label = 'Use Normal Keyboard';
16325    		var isKeypadDevice = '0';
16326    	}
16327    	
16328    	if (checkbox.checked == UTIL.parseBool(GLO.Data.provider.button_based_fl)) {
16329    		UTIL.setCookie('is-keypad-device', null);
16330    		
16331    		var msg = 'This device will use your normal On-Screen Keyboard setting which is <b class="narrow-text">' + label + '</b>';
16332    	} else {
16333    		UTIL.setCookie('is-keypad-device', isKeypadDevice);
16334    		
16335    		var msg = 'This device keyboard setting has been changed to <b class="narrow-text">' + label + '</b>';
16336    	}
16337    	
16338    	GLO.Popup.Success.open(msg, 'On Screen Keyboard', 65000);
16339    }
16340    _conAdvanced.setIsTouchDevice = function(checkbox) {
16341    	if (checkbox.checked) {
16342    		var isTouchScreen = '1';
16343    	} else {
16344    		var isTouchScreen = '0';
16345    	}
16346    	
16347    	UTIL.setCookie('is-touch-screen', isTouchScreen);
16348    }
16349    _conAdvanced.setIsButtonBased = function(element) {
16350    	GLO.Provider.Advanced.saveField(element, event);
16351    	GLO.Data.provider.button_based_fl = $(element).prop('checked');
16352    	
16353    	if (UTIL.isEmpty($.cookies.get('is-keypad-device'))) {
16354    		$('#Touch_Screen_fl').prop('checked', GLO.Data.provider.button_based_fl);
16355    	}
16356    }
16357    
16358    _conAdvanced.setThisDeviceCalHeaderSize = function(selectBox) {
16359    	var size = $(selectBox).find('option:selected').attr('value');
16360    	
16361    	UTIL.setCookie('cal-header-size', size);
16362    }
16363    _conAdvanced.setThisDeviceCalHeaderSticky = function(checkbox) {
16364    	if (checkbox.checked) {
16365    		var isChecked = '1';
16366    	} else {
16367    		var isChecked = '0';
16368    	}
16369    	
16370    	UTIL.setCookie('is-cal-header-sticky', isChecked);
16371    }
16372    
16373    _conAdvanced.gotoBirthdayEmailSetup = function(element, event) {
16374    	GLO.Uri.gotoUriWithSpinner('message/Birthday?helloback=advanced&tabback=client', element, event, true)
16375    }
16376    _conAdvanced.gotoNewClientEmailSetup = function(element, event) {
16377    	GLO.Uri.gotoUriWithSpinner('message/WelcomeClientMessage?helloback=advanced&tabback=client', element, event, true)
16378    }
16379    _conAdvanced.gotoHasFollowupEmailSetup = function(checkbox, event, btn) {
16380		if (_isLoading) { return; }
16381		
16382		if (!GLO.Provider.isPaidAccount()) {
16383			if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 39) {
16384				var msg = 'Automatic Follow-Up Messages Requires Paid Package';
16385				
16386				
16387				if (GLO.Info.isIosApp || GLO.Info.isProviderApp) {
16388					var url = '/hello/pricing';
16389				} else {
16390					var url = '/provider/profile/6';
16391				}
16392				
16393				var htm = '<div id="pop-followup-require-paid"><p>' + msg + '</p></div>';
16394				var jpop = GLO.Popup.Warning.open(htm, 'Paid Package Required').getPopup();
16395				var jbtns = jpop.find('.pop-buttons').css({ "margin-bottom": "12px" });
16396				var btnOk = jpop.find('.btnOk').css({ "width": "inherit" });
16397				var cssUpgrade = 'position: absolute; left: 2px; padding-top: 8px; padding-bottom: 6px;';
16398				
16399				if (innerWidth > 360) {
16400					jbtns.css({ "width": "100%", "max-width": "420px" });
16401				} else {
16402					cssUpgrade += ' letter-spacing: 0;';			//font-family: Arial; font-stretch: condensed;
16403				}
16404				
16405				var btnUpgrade = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)" style="' + cssUpgrade + '">Checkout Gold Package</a></span>';
16406				
16407				btnOk.find('>').text('Close').css({ "position": "absolute", "right": "2px", "padding": "8px 12px 6px" });
16408				btnOk.before(btnUpgrade);
16409				
16410				if (checkbox) {
16411					$(checkbox).prop('checked', false);
16412				}
16413				
16414				return;
16415			}
16416		}
16417		
16418		if (checkbox) {
16419			$(checkbox).prop('checked', !$(checkbox).prop('checked'));
16420		}
16421		
16422		if (btn) {
16423			GLO.Uri.gotoUriWithSpinner('message/AutoMarketing?helloback=advanced&tabback=client', btn, event, true);
16424		} else {
16425			GLO.Uri.gotoUriWithSpinner('message/AutoMarketing?helloback=advanced&tabback=client', checkbox, event, false);
16426		}
16427	}
16428    
16429    _conAdvanced.canSaveChanges = function(isRequireGold) {
16430    	if (isRequireGold && !GLO.Info.isRequireGold()) {
16431    		return false;
16432    	} else if (GLO.Provider.isPaidAccount(true) && GLO.Info.roleType > 219) {
16433    		return true;
16434    	}
16435    	//if (GLO.Data.provider.signupDetail == 50 || GLO.Data.provider.signupDetail == 52 || GLO.Data.provider.signupDetail == 200 || GLO.Data.provider.signupDetail == 400) { return true; }
16436    	
16437    	return false;
16438    }
16439    
16440    _conAdvanced.saveValue = function(fieldName, fieldValue, htmSaveSuccess, fnPostSave) {
16441    	if (!_conAdvanced.canSaveChanges()) { return; }
16442    	
16443    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedField';
16444    	
16445    	$.ajax({ type: "POST", url: uri, "cache": false, data: { "field": fieldName, "value": fieldValue } })
16446            .success(function(data, textStatus, jqXHR) {
16447                if (htmSaveSuccess) {
16448                	GLO.Popup.Success.open(htmSaveSuccess);
16449                }
16450                
16451            	if (fnPostSave) {
16452            		fnPostSave();
16453            	}
16454		    })
16455            .error(function(jqXHR, textStatus, errorThrown) {
16456                //_styleField(field, 0);
16457                //GLO.Popup.Error('Unable to save.  Please try again');
16458            });
16459    }
16460    _conAdvanced.saveField = function(element, event, htmSaveSuccess) {
16461    	if (!_conAdvanced.canSaveChanges()) { return; }
16462    	
16463    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedField';
16464        var jfield = $(element);
16465        var field = UTIL.coalesce(jfield.attr('ProfileField'), jfield.attr('name'), jfield.attr('id'));
16466        var value = jfield.val();
16467        var type = $.trim(jfield.attr('type')).toLowerCase();
16468        
16469        if (type === 'checkbox') {
16470    		value = jfield.prop('checked');
16471    	}
16472        
16473        _styleField(jfield);
16474        _initCalendarOptions();
16475		if (field == 'New_Client_Form_cd') {
16476			_toggleEasyLoginSetting(value);
16477		}
16478
16479        //_initOnlineBookingOptions();
16480        
16481        $.ajax({ type: "POST", url: uri, "cache": false, data: { "field": field, "value": value } })
16482            .success(function(data, textStatus, jqXHR) {
16483                _styleField(jfield, true, htmSaveSuccess);
16484                
16485                setTimeout(function() {
16486	                if (!UTIL.isEmpty(jfield.attr('original_value'))) {
16487	                	jfield.attr('original_value', value);
16488	                }
16489	            }, 800);
16490		    })
16491            .error(function(jqXHR, textStatus, errorThrown) {
16492                _styleField(field, 0);
16493                GLO.Popup.Error.open('Unable to save.  Please try again later', 'Change Setting Failed');
16494            });
16495    }
16496    
16497    function _styleField(jfield, isSuccess, htmSaveSuccess) {
16498    	var jlabel = $('label[for="' + jfield.attr('id') + '"]');
16499    	var label = UTIL.coalesce(jlabel.attr('success_htm'), jlabel.text(), jfield.attr('success_htm'));
16500    	var type = UTIL.coalesce($.trim(jfield.attr('type')).toLowerCase(), jfield.prop('type'));
16501    	var af = jfield.closest('.advanced-feature');
16502    	
16503    	if (!UTIL.isEmpty(htmSaveSuccess)) {
16504    		label = htmSaveSuccess;
16505    	} else if (type === 'radio') {
16506    		label = $.trim(af.find('.radio-label').text()) + label;
16507    	} else if (type === 'text' || type === 'number') {
16508    		if (!UTIL.isEmpty(jfield.val())) {
16509    			var label2 = '<i>
16509New Value: </i><b>' + jfield.val() + '</b>';
16510    		} else {
16511    			var label2 = '<b>Value Removed</b>';
16512    		}
16513    		
16514    		label = '<p>' + label + '</p><p style="text-align: center;">' + label2 + '</p>';
16515    	} else if (type === 'select-one') { 				//|| type === 'select-multiple') {
16516    		var value = jfield.find(':selected').text();
16517    		
16518    		if (!UTIL.isEmpty(value)) {
16519    			var label2 = UTIL.coalesce(jlabel.attr('success_htm'), jfield.attr('success_htm'));
16520    			
16521    			if (UTIL.isEmpty(label2) && jlabel.length === 2) {
16522	    			label = jlabel.eq(0).text() + ' <b>' + value + '</b> ' + jlabel.eq(1).text();
16523    			} else {
16524    				label = '<p>' + label + '</p><p style="text-align: center;"><i>New Value: </i><b>' + value + '</b></p>';
16525    			}
16526    		} else {
16527    			var label2 = '';
16528    			label = '<p>' + label + '</p><p style="text-align: center;"><b>Value Removed</b></p>';
16529    		}
16530    	}
16531    	
16532    	if (isSuccess) {
16533    		GLO.Popup.closeIfExist($('.pop-success.glopop'));
16534    		
16535    		var htm = '<div> <h1 class="friendly-msg">Change Saved</h1> <div class="friendly-msg3">' + label + '</div> </div>';
16536    		var jpop = new GLO.Popup.Success(htm).getPopup();
16537    		//jpop.find('.pop-icon').css({ "top": "50%" });
16538    		
16539    		setTimeout(function() {
16540	    		af.removeClass('updating-feature');
16541	    		jlabel.removeClass('updating-feature').removeClass('updating-feature-unchecked');
16542    		}, 6400);
16543    	} else {
16544    		af.addClass('updating-feature');
16545    		jlabel.addClass('updating-feature');
16546    		
16547    		if (type === 'checkbox' && !jfield.prop('checked')) {
16548    			jlabel.addClass('updating-feature-unchecked');
16549    		}
16550    	}
16551    	
16552    	if (jfield.attr('id') === 'Display_Print_fl') {
16553    		var jProfileMenu = $('#hd-profile-menu').find('.header-drop-menu');
16554    		var liLast = jProfileMenu.find('li:last');
16555    		var liPrint = jProfileMenu.find('#hd-profile-menu-print');
16556    		
16557    		if (jfield.prop('checked')) {
16558    			if (liPrint.length === 0) {
16559    				liLast.before('<li id="hd-profile-menu-print"><a onclick="SA.Menu.print()">Print</a></li>');
16560    			}
16561    		} else {
16562    			liPrint.remove();
16563    		}
16564    	}
16565    }
16566    
16567    _conAdvanced.afterSaveFieldText = function(jfield) {
16568		_styleField(jfield, 1);
16569	}
16570    
16571    _conAdvanced.deleteSyncedClients = function() {
16572    	if (!_conAdvanced.canSaveChanges()) { return; }
16573	    	
16574    	var h1 = 'Delete Synced Clients?';
16575    	var msg = 'Are you sure you want to delete the clients synced from phones and tablets?';
16576    	var htm = '<div id="pop-confirm-delete-sync"> <h1 class="friendly-msg">' + h1 + '</h1> <div class="friendly-msg2" style="max-width: 480px;">' + msg + '</div> </div>';
16577    	
16578    	var jpop = new GLO.Popup.Confirm(htm, GLO.Provider.Advanced.deleteSyncedClientsConfirmed).getPopup().addClass('no-persist');
16579    	jpop.find('.btnYes').addClass('btnDelete').removeClass('btnYes').find('>a').text('Delete');
16580    }
16581    
16582    _conAdvanced.deleteSyncedClientsConfirmed = function() {
16583    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/RemoveSyncedClients';
16584    	
16585    	var btns = $('.btnDeleteSyncClients');
16586        GLO.UI.Form.beginProcessing(btns);
16587        
16588        $.ajax({ type: "POST", url: uri, "cache": false })
16589            .success(function(data, textStatus, jqXHR) {
16590                GLO.UI.Form.resetProcessing(btns);
16591                var jd = $(data);
16592                
16593                if (jd.attr('id') === 'sync-results') {
16594                	var htm = '<div><h1 class="friendly-msg">Sync Clients Deleted</h1><div class="friendly-msg3">' + data + '</div></div>';
16595                	var jpop = new GLO.Popup.Success(htm, 8500).getPopup();
16596                } else {
16597                	var htm = '<div><h1 class="friendly-msg">Sync Clients Deleted</h1><div class="friendly-msg3">Synced Clients Removed</div></div>';
16598                	new GLO.Popup.Success(htm);
16599                }
16600		    })
16601            .error(function(jqXHR, textStatus, errorThrown) {
16602                GLO.Popup.Error('Unable to merge clients.  Please try again later.');
16603                GLO.UI.Form.resetProcessing(btns);
16604            });
16605    }
16606    
16607    
16608     _conAdvanced.Payment = (function() {
16609        function _conAdvancedPay() { }
16610        
16611        _conAdvancedPay.init = function() {
16612        	var isExtraPayIsTip = UTIL.parseBool($.cookies.get('keypad-extra-payment-is-tip'));
16613        	
16614        	if (isExtraPayIsTip) {
16615        		var j = $('#advanced-payment #advanced-payment-extra-payment-is-tip').removeClass('hide');
16616        		j.find('#extra-payment-is-tip').prop('checked', isExtraPayIsTip);
16617        	}
16618        }
16619        _conAdvancedPay.changeExtraPaymentIsTip = function(element) {
16620			var isExtraPayIsTip = $(element).prop('checked');
16621			
16622			UTIL.setCookie('keypad-extra-payment-is-tip', isExtraPayIsTip);
16623		}
16624        _conAdvancedPay.changeSelfCheckoutMode = function(element) {
16625			if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 79) {
16626        		var msg = '<p>Self-Checkout requires merchant account</p>';
16627        		var btn = '<div>
16627<a onclick="SA.Profile.OnlineBooking.requestAddMerchant()">Add a Merchant Account</a></div>';
16628        		var htm = '<div id="pop-warn-missing-merchant-account">' + msg + btn + '</div>';
16629        		
16630        		GLO.Popup.Warning.open(htm, 'Merchant Account Required');
16631			}
16632			
16633			GLO.Provider.Advanced.saveField(element, event);
16634		}
16635        
16636        return _conAdvancedPay;
16637    })();
16638	
16639	
16640    _conAdvanced.Calendar = (function() {
16641        function _conAdvancedCal() { }
16642        
16643        _conAdvancedCal.openAddFirstAvailableStaff = function() {
16644	    	var explanation = '<div style="font-size: 108%; cursor: help;" title="Clients will only be able to book an appointment for \"First Available\" if a staff is available during that time">'
16645	    						+ 'Allows clients to book appointments for the <i>First Available</i> staff'
16646	    					+ '</div>'
16647	    					+ '<div>and gives you the ability to assign which staff performs the service</div>';
16648	    	
16649	    	var cssExplanation = 'padding-left: 20px; padding-right: 12px; padding-bottom: 40px; letter-spacing: 1px; line-height: 180%;';
16650	    	var cssInput = 'display: inline-block; margin-bottom: 8px; letter-spacing: 1px;';
16651	    	var cssLabel = cssInput + ' margin-top: 8px; padding-left: 16px; padding-right: 8px; letter-spacing: 0; white-space: normal; font-size: 108%; color: #666;';
16652	    	
16653	    	var mp = '<select id="Mobile_Provider_cd" style="width: 140px; margin-left: 20px;">' + $('#cell-mobile-provider #cMobile_Provider_cd').html() + '</select>';
16654	    	var phoneInputType = "text";
16655        	if (GLO.Info.isAndroid) { phoneInputType = "tel"; }
16656	    	
16657	    	var htm = $('<div id="pop-first-available-add-staff" style="text-align: center;">'
16658	    				+ '<h1 style="letter-spacing: 2px; font-size: larger;">Add First Available Staff</h1>'
16659	    				+ '<div style="' + cssExplanation + '">' + explanation + '</div>'
16660	    				+ '<div>'
16661	    					+ '<label for="Name_vc" style="margin-right: 8px; letter-spacing: 1px; font-size: 100%; font-weight: bold;">Name / Label</label>'
16662	    					+ '<input type="text" id="Name_vc" placeholder="Name / Label" value="First Available" style="width: 280px; text-align: center; font-size: 108%;"/>'
16663	    				+ '</div>'
16664	    				+ '<div style="margin-top: 32px; margin-bottom: 12px; padding-bottom: 8px; text-align: center; border: 1px solid #444; color: #444;">'
16665	    					+ '<label style="' + cssLabel + '">Want to Get Notified When Clients Book Appointments for First Available?</label>'
16666	    					+ '<div style="margin-top: 12px;"> <input type="text" id="Email_vc" placeholder="Email Address" style="width: 280px; ' + cssInput + '"/> </div>'
16667	    					+ '<input type="' + phoneInputType + '" id="Phone_vc" placeholder="Phone" style="width: 120px; ' + cssInput + '"/>'
16668	    					+ mp
16669	    			+ '</div>');
16670	    	
16671	    	var jpop = new GLO.Popup.Custom(htm, GLO.Provider.Advanced.Calendar.saveAddFirstAvailableStaff).getPopup().addClass('no-persist');
16672	    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px" });
16673	    	
16674	    	if (innerWidth < 500) {
16675	    		jpop.find('label[for="Name_vc"]').css({ "display": "block", "margin": "0", "text-align": "center", "color": "#4F81BD", "": "" });
16676	    	}
16677	    	
16678	    	UI.phoneMask(jpop.find("#Phone_vc"));
16679	    	_conAdvanced.canSaveChanges();
16680	    }
16681	    
16682	    _conAdvancedCal.saveAddFirstAvailableStaff = function() {
16683	    	if (!_conAdvanced.canSaveChanges()) { return; }
16684	    	
16685	    	var jpop = $('#pop-first-available-add-staff').closest('.glopop');
16686	    	var name = jpop.find('#Name_vc').val();
16687	    	var email = jpop.find('#Email_vc').val();
16688	    	var phone = jpop.find('#Phone_vc').val();
16689	    	var mprovider = jpop.find('#Mobile_Provider_cd').val();
16690	    	
16691	    	var jd = { "name": name, "email": email, "phone": phone, "mprovider": mprovider };
16692	    	
16693	    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/AddFirstAvailableStaff';
16694	        GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
16695	        
16696	        $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
16697	            .success(function(data, textStatus, jqXHR) {
16698	                GLO.Popup.close(jpop);
16699	                new GLO.Popup.Success('First Available Staff Added');
16700	                
16701	                $('#add-first-available').remove();
16702	                $('#advanced-calendar #Has_First_Available_fl').prop('checked', true);
16703			    })
16704	            .error(function(jqXHR, textStatus, errorThrown) {
16705	                GLO.Popup.Error('Unable to save.  Please try again');
16706	                GLO.UI.Form.resetProcessing();
16707	            });
16708	    }
16709	    _conAdvancedCal.saveNotRequestBorderOnly = function(element, event) {
16710	    	_conAdvancedCal.setAppointmentNotRequestColor();
16711	    	
16712	    	var label = $('#Is_Request_Color_Rgb_fl option:selected').text();
16713	    	
16714	    	GLO.Provider.Advanced.saveField(element, event, 'Appointment ' + label + ' Color on Border Only');
16715	    }
16716	    _conAdvancedCal.setAppointmentNotRequestColor = function(isInit) {
16717	    	var j = $('#advanced-client-request');
16718	    	var jcolor = j.find('#Not_Request_Color_Rgb_vc');
16719	    	var color = jcolor.val();
16720	    	var jlabel = j.find('label[for="Not_Request_Color_Rgb_vc"]');
16721	    	var trBorderOnly = j.find('#advanced-client-request-border-only');
16722	    	var label = $('#Is_Request_Color_Rgb_fl option:selected').text();
16723	    	
16724	    	if (j.find('#Not_Request_Color_Rgb_fl').prop('checked')) {
16725	    		trBorderOnly.find('label').css({ "text-decoration": "" });
16726	    		trBorderOnly.find('input').prop('disabled', false);
16727	    		
16728	    		jlabel.css({ "visibility": "visible", "display": "" });
16729	    		
16730	    		if (!isInit && UTIL.isEmpty(color)) {
16731	    			jlabel.click();
16732	    			return;
16733	    		}
16734	    		
16735	    		if (j.find('#Not_Request_Border_Only_fl').prop('checked')) {
16736	    			var cssPropName = 'border-color';
16737	    			var cssPropNameRemove = 'background-color';
16738	    		} else {
16739	    			var cssPropName = 'background-color';
16740	    			var cssPropNameRemove = 'border-color';
16741	    		}
16742	    		
16743	    		jlabel.css(cssPropName, "#" + color);
16744	    		jlabel.css(cssPropNameRemove, '');
16745	    		return '<div style="' + cssPropName + ': #' + color + '">Appointment Color when Staff ' +  label + '</div>';
16746	    	} else {
16747	    		trBorderOnly.find('label').css({ "text-decoration": "line-through" });
16748	    		trBorderOnly.find('input').prop('disabled', true);
16749	    		
16750	    		jlabel.css({ "visibility": "hidden", "display": "none" });
16751	    		jcolor.val('');
16752	    		
16753	    		return 'Not Using Changing Appointment Color when Staff ' + label;
16754	    	}
16755	    }
16756	    _conAdvancedCal.saveNotRequestColor = function(event) {
16757	    	var j = $('#advanced-client-request');
16758	    	var jcolor = j.find('#Not_Request_Color_Rgb_vc');
16759	    	
16760	    	if (j.find('#Is_Request_Color_Rgb_fl option:selected').val() == 1) {
16761	    		jcolor.attr('ProfileField', 'Request_Color_Rgb_vc');
16762	    	} else {
16763	    		jcolor.attr('ProfileField', 'Not_Request_Color_Rgb_vc');
16764	    	}
16765	    	
16766	    	var htmSaveSuccess = _conAdvancedCal.setAppointmentNotRequestColor();
16767	    	
16768	    	GLO.Provider.Advanced.saveField(jcolor[0], event, htmSaveSuccess);
16769	    }
16770	    
16771	    _conAdvancedCal.changeHasFirstAvailable = function(element, event) {
16772	    	if (!GLO.Info.isRequireGold()) {
16773	    		element.checked = !element.checked;
16774	    		return false;
16775	    	}
16776	    	
16777	    	if (element.checked) {
16778	    		_conAdvancedCal.openAddFirstAvailableStaff();
16779	    	} else {
16780	    		_conAdvancedCal.removeFirstAvailableStaffConfirm();
16781	    	}
16782	    	
16783	    	element.checked = !element.checked;
16784	    }
16785	    
16786	    _conAdvancedCal.removeFirstAvailableStaffConfirm = function() {
16787	    	if (!_conAdvanced.canSaveChanges()) { return; }
16788	    	
16789	    	var h1 = 'Delete First Available?';
16790	    	var msg = 'Are you sure you want to delete the first available staff?';
16791	    	var htm = '<div id="pop-confirm-delete-first-available"> <h1 class="friendly-msg">' + h1 + '</h1> <div class="friendly-msg2">' + msg + '</div> </div>';
16792	    	
16793	    	var jpop = new GLO.Popup.Confirm(htm, GLO.Provider.Advanced.Calendar.removeFirstAvailableStaff).getPopup().addClass('no-persist');
16794	    	jpop.find('.btnYes').addClass('btnDelete').removeClass('btnYes').find('>a').text('Delete');
16795	    }
16796	    
16797	    _conAdvancedCal.removeFirstAvailableStaff = function() {
16798	    	if (!_conAdvanced.canSaveChanges()) { return; }
16799	    	
16800	    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/DeleteFirstAvailableStaff';
16801	        var jpop = $('#pop-confirm-delete-first-available').closest('.glopop');
16802	        GLO.UI.Form.beginProcessing( jpop.find('.btnDelete') );
16803	        
16804	        $.ajax({ type: "POST", url: uri, "cache": false })
16805	            .success(function(data, textStatus, jqXHR) {
16806	                GLO.Popup.close(jpop);
16807	                new GLO.Popup.Success('First Available Deleted');
16808	                
16809	                $('#advanced-calendar #Has_First_Available_fl').prop('checked', false);
16810			    })
16811	            .error(function(jqXHR, textStatus, errorThrown) {
16812	                GLO.Popup.Error('Unable to delete first available staff.  Please try again');
16813	                GLO.UI.Form.resetProcessing();
16814	            });
16815	    }
16816        
16817        _conAdvancedCal.enableTurnTracking = function(element, event) {
16818        	if (!GLO.Info.isRequireGold()) {
16819        		element.checked = !element.checked;
16820        		return false;
16821        	}
16822        	
16823        	GLO.Provider.Advanced.saveField(element, event);
16824        }
16825        
16826        _conAdvancedCal.changeStaffAlert = function(element, hasMessagePackage, label) {
16827        	var orig = $(element).attr('original_value');
16828        	
16829        	if (!hasMessagePackage && orig < 20) {
16830        		var link = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/message?helloback=advanced&tabback=appointment&highlight=advanced-feature-staff-alert-text")\'>Message Plan</a>';
16831        		var msg1 = '<p style="margin-bottom: 32px;">To enable ' + label + ' please enable the ' + link + ' <b class="narrow-text">Pay as Use</b> or another <b class="narrow-text">Message Plan</b></p>';
16832        		var msg2 = '<p>Text alerts cost 1 cent per message</p>';
16833        		var msg3 = '<p>In-app alerts are free</p>';
16834        		
16835        		var htm = '<div id="pop-warn-staff-text-alerts-require-message-package">' + msg1 + msg2 + msg3 + '</div>';
16836        		var jpop = GLO.Popup.Warning.open(htm, 'Staff Text Alerts Require Message Package');
16837        		//GLO.Popup.Custom.singleButton(jpop, 'Close');
16838        		
16839        		$(element).find('option[value="10"]').prop('selected', 'selected');
16840        		return;
16841        	}
16842        	
16843        	GLO.Provider.Advanced.saveField(element, event);
16844        }
16845        
16846        return _conAdvancedCal;
16847    })();
16848    
16849    
16850    _conAdvanced.Online = (function() {
16851        function _conAdvancedOnline() { }
16852        
16853        _conAdvancedOnline.openChangeBookOutDays = function(element) {
16854        	if (!_conAdvanced.canSaveChanges()) { return; }
16855        	
16856        	var jelement = $(element);
16857        	
16858        	var label1 = '<label for="Edit_Book_Out_Days_nr">Clients can book up to </label>';
16859        	var label2 = '<label for="Edit_Book_Out_Days_nr"> days in the future</label>';
16860        	var input = '<input type="text" id="Edit_Book_Out_Days_nr" value="' + element.value + '" onkeypress="UI.numberOnly(event)"/>';			// onchange="GLO.Provider.Advanced.saveField(this, event)"
16861        	var divInput = '<div style="margin-top: 12px; margin-bottom: 32px; text-align: center;">' + label1 + input + label2 + '</div>';
16862        	
16863        	var msg1 = '<p>How far in advance due you want to allow ' + GLO.Info.getScheduleAnyoneHtm(
16863) + ' to setup your schedule so clients can book online?</p>';
16864        	var msg2 = '<p>The default is 180 days (about 6 months) which works well for most businesses</p>';
16865        	var htm = '<div id="pop-book-days-out">' + msg1 + msg2 + divInput + '</div>';
16866			
16867        	var jpop = GLO.Popup.Custom.openSimple(htm, 'Schedule How Many Days in the Future', GLO.Provider.Advanced.Online.saveBookOutDays);
16868        	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "400px" });
16869        	jbtns.find('.btnCancel > a').css({ "font-weight": "bold" });
16870        	
16871        }
16872        _conAdvancedOnline.saveBookOutDays = function() {
16873        	if (!_conAdvanced.canSaveChanges()) { return; }
16874        	
16875        	var jpop = $('#pop-book-days-out').closest('.glopop');
16876        	var fieldElement = $('#advanced-online-booking #Book_Out_Days_nr')[0];
16877        	var htmSaveSuccess = null;
16878        	
16879        	fieldElement.value = jpop.find('#Edit_Book_Out_Days_nr').val();
16880        	GLO.Provider.Advanced.saveField(fieldElement, null, htmSaveSuccess);
16881        	GLO.Popup.close(jpop);
16882        }
16883        _conAdvancedOnline.saveBookOutDaysConfirmed = function() {
16884        	var jpop = $('#pop-booking-limit').closest('.glopop');
16885        	var limit = jpop.find('#Booking_Limit_sr').val();
16886        	var uri = GLO.Link.WebsiteDomain + 'provider/manage/BookingLimit?period=' + period + '&id=' + id;
16887        	
16888        	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
16889        	
16890	        $.ajax({ type: "POST", url: uri, "cache": false })
16891	            .success(function(data, textStatus, jqXHR) {
16892	                GLO.Popup.closeIfExist(jpop);
16893	                
16894			    })
16895	            .error(function(jqXHR, textStatus, errorThrown) { });
16896        }
16897        
16898        _conAdvancedOnline.openBookingLimit = function(element) {
16899        	if ($('#pop-booking-limit').closest('.glopop').length > 0) { return; }
16900        	
16901        	var jelement = $(element);
16902        	var jrow = jelement.closest('li.booking-limit-row');
16903        	var jclient = jelement.closest('#client-form');
16904        	
16905        	if (jclient.length) {
16906        		var clientName = UTIL.cleanString(jclient.find('#First_Name_vc').val()) + ' ' + UTIL.cleanString(jclient.find('#Last_Name_vc').val());
16907        	} else {
16908        		var clientName = '';
16909        	}
16910        	
16911        	var htm = _getBookingLimitPopup(jrow, clientName);
16912        	var jpop = GLO.Popup.Custom.openSimple(htm, 'Client Booking Limit', GLO.Provider.Advanced.Online.saveBookingLimit);
16913        	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
16914        	jbtns.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "font-weight": "bold" });
16915        	
16916        	if (!UTIL.isEmpty(jpop.find('#Schedule_Limit_id').val())) {
16917        		var btnDelete = '<span class="btnDelete" style="position: absolute; left: 8px; margin: 0;"><a onclick="GLO.Provider.Advanced.Online.deleteBookingLimit()">Delete</a></span>';
16918        		jbtns.prepend(btnDelete);
16919        	}
16920        }
16921        
16922        function _getBookingLimitPopup(li, clientName) {
16923        	var htm = '<div id="pop-booking-limit">';
16924        	var id = '', cid = '', period = '', limit = '', apptLimitTypeChecked = '';
16925        	
16926        	if (li && li.length) {
16927        		var jrow = $(li);
16928        		var apptLimit = UTIL.coalesceInt(jrow.attr('appt_limit_sr'));
16929        		id = UTIL.cleanString(jrow.attr('schedule_limit_id'));
16930        		cid = UTIL.cleanString(jrow.attr('client_id'));
16931        		period = UTIL.cleanString(jrow.attr('period_cd'));
16932        		limit = UTIL.coalesceInt(jrow.attr('service_limit_sr'), apptLimit);
16933        		
16934        		if (apptLimit > 0) {
16935        			apptLimitTypeChecked = ' selected="selected"';
16936        		}
16937        	}
16938        	
16939        	if (!UTIL.isEmpty(clientName)) {
16940        		clientName = UTIL.maxString(clientName, 12, true);
16941        	} else {
16942        		clientName = 'Each Client';
16943        	}
16944        	
16945        	var lbl1 = '<label for="Booking_Limit_sr">Limit ' + clientName + ' to</label>';
16946        	var lbl2 = '<label for="Period_cd"> per </label>';
16947        	
16948        	var inputId = '<input type="hidden" id="Schedule_Limit_id" value="' + id + '"/>';
16949        	var inputCount = '<input type="number" id="Booking_Limit_sr" value="' + limit + '"/>';
16950        	var selectLimitType = '<select id="Limit_Type_cd"> <option value="appointment"' + apptLimitTypeChecked + '>Appointment</option> <option value="service">Service</option> </select>';
16951        	var selectLimitPeriod = '<select id="Period_cd">'
16952        								+ '<option value="10"' + _getCheckedAttribute(period, 10) + '>Day</option>'
16953        								+ '<option value="20"' + _getCheckedAttribute(period, 20) + '>Week</option>'
16954        								+ '<option value="30"' + _getCheckedAttribute(period, 30) + '>Month</option>'
16955        								+ '<option value="70"' + _getCheckedAttribute(period, 70) + '>Year</option>'
16956        								+ '<option value="100"' + _getCheckedAttribute(period, 100) + '>All Upcoming</option>'
16957        							+ '</select>';
16958        	
16959        	return htm + inputId + lbl1 + inputCount + selectLimitType + lbl2 + selectLimitPeriod + '</div>';
16960        }
16961        
16962        _conAdvancedOnline.deleteBookingLimit = function() {
16963        	var htm = '<div id="pop-confirm-delete-booking-limit">Are you sure you want to delete this client booking limit?</div>';
16964        	var fn = function() { GLO.Provider.Advanced.Online.saveBookingLimit(true); };
16965        	
16966        	GLO.Popup.Confirm.open(htm, 'Confirm Delete Booking Limit', fn);
16967        }
16968        _conAdvancedOnline.saveBookingLimit = function(isDelete) {
16969        	var clientId = UTIL.cleanString($('#displayProfile-Client').find('#Client_id').val());
16970        	
16971        	if (UTIL.isEmpty(clientId) && !_conAdvanced.canSaveChanges()) { return; }
16972        	
16973        	if (isDelete) {
16974        		GLO.Popup.close($('#pop-confirm-delete-booking-limit').closest('.glopop'));
16975        	}
16976        	
16977        	var jpop = $('#pop-booking-limit').closest('.glopop');
16978        	var limit = jpop.find('#Booking_Limit_sr').val();
16979        	var period = jpop.find('#Period_cd').val();
16980        	var id = UTIL.cleanString(jpop.find('#Schedule_Limit_id').val());
16981        	var apptLimit = 0, svcLimit = 0;
16982        	
16983        	if (jpop.find('#Limit_Type_cd').find('option:selected').attr('value') === 'appointment') {
16984        		apptLimit = limit;
16985        	} else {
16986        		svcLimit = limit;
16987        	}
16988        	
16989        	_saveBookingLimit(id, period, apptLimit, svcLimit, isDelete, clientId);
16990        }
16991        function _saveBookingLimit(id, period, apptLimit, svcLimit, isDelete, clientId) {
16992	        var uri = GLO.Link.WebsiteDomain + 'provider/manage/BookingLimit?period=' + period + '&id=' + id;
16993        	var jd = { "svclimit": svcLimit, "apptlimit": apptLimit, "isdelete": isDelete };
16994        	var jtbl = $('#aob-booking-limit-list');
16995        	var jpop = $('#pop-booking-limit').closest('.glopop');
16996        	
16997        	if (!UTIL.isEmpty(clientId)) { uri += '&client=' + clientId; }
16998        	
16999        	if (isDelete) {
17000        		GLO.UI.Form.beginProcessing(jpop.find('.btnDelete'));
17001        	} else {
17002        		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
17003        	}
17004        	
17005	        $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
17006	            .success(function(data, textStatus, jqXHR) {
17007	                GLO.Popup.close(jpop);
17008	                jtbl.find('li[schedule_limit_id="' + id + '"]').remove();
17009	                
17010	                if (!isDelete) {
17011	                	jtbl.append(data);
17012	                }
17013			    })
17014	            .error(function(jqXHR, textStatus, errorThrown) { });
17015	    }
17016	    
17017        function _getCheckedAttribute(value1, value2) {
17018        	if (value1 == value2) {
17019        		return ' selected="selected"';
17020        	} else {
17021        		return '';
17022        	}
17023        }
17024        
17025        _conAdvancedOnline.changeWaitListMax = function(element) {
17026	    	UI.verifyNumberInput(element, true);
17027	    	
17028	    	if (element.value > 0) {
17029	    		var isChecked = true;
17030	    	} else {
17031	    		var isChecked = false;
17032	    	}
17033	    	
17034	    	$('#Enable_Today_Wait_List_Max_fl').prop('checked', isChecked);
17035	    }
17036	    
17037    	_conAdvancedOnline.saveExistingOnly = function(event) {
17038        	if (!_conAdvanced.canSaveChanges()) { return; }
17039        	
17040        	var uri = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedField';
17041        	var jfeature = $('#aob-allow-online-booking')
17042        	var jonline = jfeature.find('#Online_Booking_fl');
17043        	var jExistingCheck = jfeature.find('#aob-row-existing-client-only .html-character-checkbox');
17044        	var hasOnlineBooking = true;
17045        	
17046        	if (jExistingCheck.attr('id') === 'only-existing-is-off') {
17047        		var clientAccess = 2, isExistingOnly = true;
17048        		
17049        		jExistingCheck.replaceWith('<b id="only-existing-is-on" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.saveExistingOnly(event)">&#9745;</b>');
17050        	} else {
17051        		var clientAccess = 1, isExistingOnly = false;
17052        		
17053        		jExistingCheck.replaceWith('<b id="only-existing-is-off" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.saveExistingOnly(event)">&#9744;</b>');
17054        	}
17055        	
17056        	if (!jonline.prop('checked')) {
17057        		hasOnlineBooking = false;
17058        		
17059        		if (isExistingOnly) {
17060        			jonline.click();
17061        		} else {
17062        			_saveExistingOnlyComplete('Online Booking Disabled');
17063        			return;
17064        		}
17065        	}
17066	        
17067	        $.ajax({ type: "POST", url: uri, "cache": false, data: { "field": "Client_Access_cd", "value": clientAccess } })
17068	            .success(function(data, textStatus, jqXHR) {
17069	                if (isExistingOnly) {
17070	                	var msg = '<p style="text-align: center;">Online Booking Updated to: <b>Existing Clients Only</b></p>';
17071	                } else if (hasOnlineBooking) {
17072	                	var msg = '<p style="text-align: center;">Online Booking Updated to: <b>Anyone Can Book Only</b></p>'
17073	                			+ '<p style="font-size: smaller;">who completes new client form or has a client profile in your ' + GLO.Info.getScheduleAnyoneHtm() + ' account</p>';
17074	                }
17075	                
17076	                _saveExistingOnlyComplete(msg);
17077			    })
17078	            .error(function(jqXHR, textStatus, errorThrown) { });
17079	    }
17080	    
17081	    function _saveExistingOnlyComplete(msg) {
17082	    	var htm = '<div><h1 class="friendly-msg">Update Successful</h1><div class="friendly-msg3">' + msg + '</div></div>';
17083	        var jpop = new GLO.Popup.Success(htm, 8500).getPopup();
17084	    }
17085        
17086        _conAdvancedOnline.confirmAllowAnon = function(event, isConfirmSave) {
17087        	var hasOnlineBooking = $('#aob-allow-online-booking #Online_Booking_fl').prop('checked');
17088        	
17089        	if (!hasOnlineBooking) {
17090        		var msg1 = '<p style="max-width: 500px; margin: 8px; auto; padding: 2px 8px; text-align: center; background-color: rgba(0, 240, 0, .6);">Must Enable Online Booking</p>';
17091    		} else {
17092    			var msg1 = '';
17093    		}
17094    		
17095    		var aLoginLink = UserPortal.getProviderUri() + 'login';
17096    		var aLogin = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + aLoginLink + '\', this, null, true, \'BookOnline\')">Login</a>';
17097    		var aNewUser = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + aLoginLink + '/NewUser\', this, null, true, \'BookOnline\')">Create Client Profile</a>';
17098    		var msg2 = '<p>By default before a client can search for an available appointment, the client must ' + aNewUser + ' or ' + aLogin + '</p>';
17099    		
17100    		if (!isConfirmSave) {
17101    			var h1 = 'Online Booking - Appointment Search';
17102    			var msg3 = '<p>You can allow users to first search and find an available appointment before entering their <i>name</i>, <i>phone</i>, and <i>email</i> to create a client profile and book an appointment online</p>';
17103    		} else if ($('#allow-anon-search-on').length) {
17104    			var h1 = 'Disable Anonymous Appointment Search?';
17105    			var msg3 = '<p>Change to <b>Disable Anonymous Appointment Search</b> so client must first create profile <small>(by entering <i>name</i>, <i>phone</i>, and <i>email</i>) before can search for available appointment</p>';
17106    		} else {
17107    			var h1 = 'Allow Anonymous Appointment Search?';
17108    			var msg3 = '<p>Change to <b>Allow Anonymous Appointment Search</b> so client can first search and find available appointment before entering <i>name</i>, <i>phone</i>, and <i>email</i> to create client profile</p>';
17109    		}
17110    		
17111    		var aHow = '<a onclick="GLO.Provider.Advanced.Help.Online.openAppointmentSearch()">How Online Booking Works</a>';
17112    		var divHow = '<div style="margin-bottom: 16px; text-align: center; letter-spacing: 1px; font-weight: bold;">' + aHow + '</div>';
17113    		
17114			var htm = '<div id="pop-allow-anon-appt-search">
17114' + divHow + msg1 + msg2 + msg3 + '</div>';
17115			
17116        	if (isConfirmSave) {
17117        		var jpop = GLO.Popup.Confirm.open(htm, h1, GLO.Provider.Advanced.Online.confirmAllowAnon2);
17118        	} else {
17119        		var jpop = GLO.Popup.Custom.openSimple(htm, h1);
17120        		GLO.Popup.Custom.singleButton(jpop, 'Close');
17121        	}
17122        }
17123        _conAdvancedOnline.confirmAllowAnon2 = function() {
17124        	if ($('#allow-anon-search-on').length) {
17125        		var newFieldValue = 0;
17126        		var htmSaveSuccess = 'Client Must Create Profile before Searching for Appointment';
17127        	} else {
17128        		var newFieldValue = 1;
17129        		var htmSaveSuccess = 'Anonymous Appointment Search Enabled';
17130        	}
17131        	
17132        	var fnPostSave = function() {
17133        		var jfeature = $('#aob-row-allow-anon');
17134        		var jfield = jfeature.find('#allow-anon-search-on');
17135        		
17136        		if (jfield.length) {
17137        			var htm = '<b id="allow-anon-search-off" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmAllowAnon(event)">&#9744;</b>';
17138        		} else {
17139        			jfield = jfeature.find('#allow-anon-search-off');
17140        			var htm = '<b id="allow-anon-search-on" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmAllowAnon(event)">&#9745;</b>';
17141        		}
17142        		
17143        		jfield.replaceWith(htm);
17144        	}
17145        	
17146        	_conAdvanced.saveValue('Allow_Anonymous_Search_fl', newFieldValue, htmSaveSuccess, fnPostSave);
17147        }
17148        
17149        _conAdvancedOnline.confirmFA = function(event) {
17150        	if (!GLO.Info.isRequireGold()) {
17151	    		return false;
17152	    	}
17153        	
17154        	var jfeature = $('#aob-allow-online-booking')
17155        	var hasOnlineBooking = jfeature.find('#Online_Booking_fl').prop('checked');
17156        	
17157        	if (jfeature.find('#only-fa-is-on').length) {
17158        		if (hasOnlineBooking) {
17159	        		var msg1 = '<p>This will enable online booking for all staff</p>';
17160        		} else {
17161        			var msg1 = '<p>This will disable online booking for all staff</p>';
17162        		}
17163        		
17164        		var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column\', this)">Profile ' + UI.arrow + ' Staff</a>';
17165        		var anyone = '<b style="color: green;">Anyone</b>';
17166        		var existing = '<b style="color: orange;">Existing</b>';
17167        		var forbid = '<b style="color: red;">Forbid</b>';
17168        		var msg2 = '<p style="">You can go to ' + aProfile + ' and set the Client Online Booking option for each staff to ' + anyone + ', ' + existing + ', or ' + forbid + '</p>';
17169        		
17170        		var h1 = 'Confirm Cancel First Available Only';
17171        		var msg = msg1 + msg2;
17172        	} else {
17173        		var hasFA = $('#advanced-calendar #Has_First_Available_fl').prop('checked');
17174        		var staffCount = UTIL.coalesceInt(jfeature.attr('client_access_count_anyone_sr'), 0) + UTIL.coalesceInt(jfeature.attr('client_access_count_existing_sr'), 0);
17175        		var faAllowsOnlineBooking = jfeature.attr('fa_client_access_cd');
17176        		
17177        		if (hasFA) {
17178        			var msg = '<p>This will create a "First Available" column on the calendar and allow clients to book an appointment with First Available when the needed staff is available<p>';
17179        			
17180        			if (staffCount > 0) {
17181        				msg += '<p>And forbid online booking for any specific staff member<br/><small>(clients will not be able to book a specific staff only \'First Available\')</small></p>';
17182        			}
17183        		} else {
17184        			var msg = '';
17185        			
17186        			if (!faAllowsOnlineBooking) {
17187        				msg += '<p>This will allow clients to book an appointment with First Available when staff is available<p>';
17188        			}
17189        			
17190        			if (staffCount > 0) {
17191        				msg += '<p>This will forbid online booking for any specific staff member</p>';
17192        			}
17193        		}
17194        		
17195        		var h1 = 'Confirm Enable First Available Only';
17196        	}
17197        	
17198        	var aHelpFA = '<a onclick="GLO.Provider.Advanced.Help.C
17198alendar.openHasFirstAvailable2()">How First Available Works</a>';
17199        	msg += '<div style="margin-top: 16px; margin-bottom: 32px; text-align: center; letter-spacing: 1px;">' + aHelpFA + '</div>';
17200        	
17201        	//var htm = '<div id="pop-confirm-first-available-only" class="friendly-msg4"><h1 class="friendly-msg4">' + h1 + '</h1><div class="friendly-msg4">' + msg + '</div></div>';
17202        	var htm = '<div id="pop-confirm-first-available-only">' + msg + '</div>';
17203			GLO.Popup.Confirm.open(htm, h1, GLO.Provider.Advanced.Online.confirmFA2);
17204        }
17205        _conAdvancedOnline.confirmFA2 = function() {
17206        	var uri = GLO.Link.WebsiteDomain + 'provider/manage/FirstAvailableOnlineBookingOnly?';
17207	        var jfa = $('#advanced-calendar #Has_First_Available_fl');
17208	        var jfeature = $('#aob-allow-online-booking');
17209	        var jcheck = jfeature.find('#aob-row-restrict-fa .html-character-checkbox');
17210	        var hasOnlineBooking = jfeature.find('#Online_Booking_fl').prop('checked');
17211	        var total = UTIL.coalesceInt(jfeature.attr('client_access_count_forbid_sr', 0)) + UTIL.coalesceInt(jfeature.attr('client_access_count_existing_sr', 0)) + UTIL.coalesceInt(jfeature.attr('client_access_count_anyone_sr', 0));
17212	        
17213	        if (jfeature.find('#only-fa-is-off').length) {
17214	        	if (uri.substring(uri.length-1) !== '?') { uri += '&'; }
17215	        	uri += 'enable_fl=1';
17216	        	
17217	        	if (!jfa.prop('checked')) {
17218		        	if (uri.substring(uri.length-1) !== '?') { uri += '&'; }
17219		        	uri += 'must_create_fa=1';
17220		        	
17221		        	jfa.prop('checked', true);
17222		        }
17223	        	
17224	        	jfeature.find('#Online_Booking_fl').prop('checked', true);
17225	        	jfeature.attr('fa_client_access_cd', '1');
17226	        	
17227	        	jfeature.attr('client_access_count_forbid_sr', total);
17228	        	jfeature.attr('client_access_count_existing_sr', '0');
17229	        	jfeature.attr('client_access_count_anyone_sr', '0');
17230	        	
17231	        	jcheck.replaceWith('<b id="only-fa-is-on" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmFA(event)">&#9745;</b>');
17232	        } else {
17233	        	if (hasOnlineBooking) {
17234		        	jfeature.attr('fa_client_access_cd', '1');
17235		        	
17236		        	jfeature.attr('client_access_count_forbid_sr', '0');
17237		        	jfeature.attr('client_access_count_existing_sr', '0');
17238		        	jfeature.attr('client_access_count_anyone_sr', total);
17239		        } else {
17240		        	jfeature.attr('fa_client_access_cd', '3');
17241		        	
17242		        	jfeature.attr('client_access_count_forbid_sr', total);
17243		        	jfeature.attr('client_access_count_existing_sr', '0');
17244		        	jfeature.attr('client_access_count_anyone_sr', '0');
17245		        }
17246		        
17247		        jcheck.replaceWith('<b id="only-fa-is-off" class="html-character-checkbox" onclick="GLO.Provider.Advanced.Online.confirmFA(event)">&#9744;</b>');
17248	        }
17249	        
17250	        $.ajax({ type: "POST", url: uri, "cache": false })
17251	            .success(function(data, textStatus, jqXHR) {
17252	                var msg = '<p style="text-align: center;">First Available Only Online Booking Status Updated</p>';
17253	                var htm = '<div><h1 class="friendly-msg">Update Successful</h1><div class="friendly-msg3">' + msg + '</div></div>';
17254	                var jpop = new GLO.Popup.Success(htm, 8500).getPopup();
17255			    })
17256	            //.error(function(jqXHR, textStatus, errorThrown) { });
17257        }
17258        
17259        _conAdvancedOnline.saveServiceGroupAccessType = function(element, event) {
17260	    	if (!_conAdvanced.canSaveChanges()) { return; }
17261	    	
17262	    	var jpop = $('#pop-service-group-access-type').closest('.glopop');
17263	    	var label = '<div>' + jpop.find('h1').text() + ' updated to: </div> <div>' + jpop.find('label[for="' + $(element).attr('id') + '"]').outerHTML() + '</div>';
17264	    	var sgid = jpop.find('h1').attr('service_group_id');
17265	    	var jd = { "service_group_id": sgid, "access_type_cd": element.value };
17266	    	
17267	    	if (jd.access_type_cd == 0) {
17268	        	var arrowRight = '<b class="arrow-right" style="padding: 0 8px;">&#10140;</b>';
17269    			var aServiceProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/4\', this, event, true)">Profile' + arrowRight + 'Service</a>';
17270	        	var htm = '<div id="pop-warn-customize-by-service">To customize the client access by service go to ' + aServiceProfile + '</div>';
17271	        	
17272	        	GLO.Popup.Info.open(htm, 'Customize by Service');
17273	        	GLO.Popup.close(jpop);
17274	        	return;
17275	        }
17276	    	
17277	    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/ServiceGroupAccessType';
17278	        GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
17279	        
17280	        $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
17281	            .success(function(data, textStatus, jqXHR) {
17282	                GLO.Popup.close(jpop);
17283	                new GLO.Popup.Success(label);
17284	                
17285	                var j = $('#aob-summary-service-group');
17286	                var jrow = j.find('#aob-summary-service-type').find('.advanced-feature[service_group_id="' + sgid + '"]');
17287	                jrow.attr('access_type_cd', jd.access_type_cd);
17288	                jrow.find('.access-type-icon').attr('id', 'access-type-icon' + jd.access_type_cd);
17289	                
17290	                var onlineCount = j.find('.advanced-feature[access_type_cd="1"]').length;
17291	                j.find('#aob-service-group-online-count').text(onlineCount);
17292	                
17293	                var viewCount = onlineCount + j.find('.advanced-feature[access_type_cd="2"]').length + j.find('.advanced-feature[access_type_cd="3"]').length;
17294	                j.find('#aob-service-group-view-count').text(viewCount);
17295			    })
17296	            .error(function(jqXHR, textStatus, errorThrown) {
17297	                GLO.Popup.Error('Unable to save.  Please try again');
17298	                GLO.UI.Form.resetProcessing();
17299	            });
17300	    }
17301	    
17302	    _conAdvancedOnline.saveWaitListClientAccess = function(element, event) {
17303	    	if (!_conAdvanced.canSaveChanges()) { return; }
17304	    	_conAdvancedOnline.greyClientAccess($(element).prop('checked'));
17305	    	GLO.Provider.Advanced.saveField(element, event);
17306	    }
17307	    
17308	    _conAdvancedOnline.saveWaitListToday = function(element, event) {
17309	    	if (!_conAdvanced.canSaveChanges()) { return; }
17310	    	_conAdvancedOnline.greyToday($(element).prop('checked'));
17311	    	GLO.Provider.Advanced.saveField(element, event);
17312	    }
17313	    
17314	    _conAdvancedOnline.greyClientAccess = function(isEnabled) {
17315	    	if (isEnabled) {
17316	    		$('#aob-waiting-list-date-row').css({ "background-color": "" });
17317	    		$('#aob-waiting-list-client-access-today').css({ "background-color": "" });
17318	    	} else {
17319	    		$('#aob-waiting-list-date-row').css({ "background-color": "rgba(80,80,80,.4)" });
17320	    		$('#aob-waiting-list-client-access-today').css({ "background-color": "rgba(80,80,80,.4)" });
17321	    	}
17322	    }
17323	    
17324	    _conAdvancedOnline.greyToday = function(isEnabled) {
17325	    	if (isEnabled) {
17326	    		$('#aob-waiting-list-today-row').find('#aob-notify-client-when-next, #aob-customize-client-signin').css({ "background-color": "" });
17327	    		$('#aob-waiting-list-client-access-today').css({ "background-color": "" });
17328	    	} else {
17329	    		$('#aob-waiting-list-today-row').find('#aob-notify-client-when-next, #aob-customize-client-signin').css({ "background-color": "rgba(80,80,80,.4)" });
17330	    		$('#aob-waiting-list-client-access-today').css({ "background-color": "rgba(80,80,80,.4)" });
17331	    	}
17332	    }
17333	    
17334	    _conAdvancedOnline.saveWaitListHourRange = function(element, event) {
17335	    	if (!_conAdvanced.canSaveChanges()) { return; }
17336	    	
17337	    	var jelement = $(element);
17338	    	var id = jelement.attr('id');
17339	    	var isStart = (id == 'Wait_List_Start_cd');
17340	    	
17341	    	var j = $('#aob-waiting-list-row');
17342	    	var jstart = j.find('#Wait_List_Start_cd');
17343	    	var jend = j.find('#Wait_List_End_cd');
17344	    	var label = 'Client Access to Waiting List ';
17345	    	
17346	    	if (element.value == '') {
17347    			jstart.val('');
17348    			jend.val('');
17349    		} else if (UTIL.isEmpty(jstart.val())) {
17350				jstart.val(1015);
17351				
17352			} else if (UTIL.isEmpty(jend.val())) {
17353    			jend.val(4970);
17354    		}
17355    		
17356    		label += 'Enabled during your defined hour range of: ' + jstart.find(':selected').text() + ' - ' + jend.find(':selected').text();
17357	    	
17358	    	var json = { "Wait_List_Start_cd": jstart.val(), "Wait_List_End_cd": jend.val() };
17359	    	_saveWaitListHourRange2(json, label);
17360	    	//_enableTodayWaitListForClients();
17361	    }
17362	    
17363	    function _enableTodayWaitListForClients() {
17364	    	var j = $('#advanced-online-booking');
17365	    	var jWaitToday = j.find('#Enable_Wait_List_Today_fl');
17366	    	var jWaitClient = j.find('#Enable_Wait_List_fl');
17367	    	
17368	    	if (!jWaitToday.prop('checked')) {
17369	    		jWaitToday.prop('checked', true).change();
17370	    	}
17371	    	
17372	    	if (!jWaitClient.prop('checked')) {
17373	    		jWaitClient.prop('checked', true).change();
17374	    	}
17375	    }
17376	    
17377	    function _saveWaitListHourRange2(json, label) {
17378	    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/WaitListHourRange';
17379	        
17380	        $.ajax({ type: "POST", url: uri, "cache": false, data: json })
17381	            .success(function(data, textStatus, jqXHR) {
17382	                new GLO.Popup.Success(label);
17383			    })
17384	            .error(function(jqXHR, textStatus, errorThrown) {
17385	            });
17386	    }
17387        
17388        return _conAdvancedOnline;
17389    })();
17390    
17391    
17392    _conAdvanced.CustomApp = (function() {
17393        function _conAdvancedApp() { }
17394        
17395        _conAdvancedApp.initCustomAppInfo = function() {
17396        	
17397        }
17398        
17399        _conAdvancedApp.saveCustomAppRequest = function() {
17400        	var uri = GLO.Link.WebsiteDomain + 'provider/manage/CustomApp';
17401	        var note = UTIL.htmlEncode($('#custom-app-note').val());
17402	        
17403	        var btn = $('.btnCustomAppRequest');
17404	        GLO.UI.Form.beginProcessing(btn);
17405	        
17406	        $.ajax({ type: "POST", url: uri, "cache": false, data: { "note": note } })
17407	            .success(function(data, textStatus, jqXHR) {
17408	                GLO.UI.Form.resetProcessing(btn);
17409	                
17410	                var msg = '<p style="text-align: center;">Thank You for Your Custom App Request</p> <p>A ' + GLO.Info.getScheduleAnyoneHtm() + ' custom app specialist will contact you soon</p>';
17411	                var htm = '<div><h1 class="friendly-msg">Custom App Requested</h1><div class="friendly-msg3">' + msg + '</div></div>';
17412	                
17413	                var jpop = new GLO.Popup.Success(htm, 8500).getPopup();
17414    				jpop.css({ "background-color": "#222" });					//.css({ "background-color": "rgba(220, 240, 200, .4)" });
17415    				jpop.find('.msg').css({ "color": "rgb(80, 240, 20)" });
17416    				//jpop.find('.pop-icon').css({ "top": "36%" });
17417    				
17418    				var jsa = jpop.find('.sa-brand');
17419    				jsa.find('b').css({ "color": "rgb(0, 200, 240)" });
17420    				jsa.find('i').css({ "color": "rgb(80, 240, 20)" });
17421    				
17422	                setTimeout(function() {
17423	                	$('.hello-bar-container').find('.hello-bar-label').click();
17424	                }, 3600);
17425			    })
17426	            .error(function(jqXHR, textStatus, errorThrown) {
17427	                GLO.UI.Form.resetProcessing();
17428	            });
17429	    }
17430        
17431        return _conAdvancedApp;
17432    })();
17433    
17434    
17435    _conAdvanced.Client = (function() {
17436        function _conAdvancedClient() { }
17437    	
17438    	_conAdvancedClient.changeTextPackage = function(element, event, helloback) {
17439    		if (_isLoading) { return; }
17440    		
17441    		var jclient = $('#advanced-client');
17442    		var email_package_cd = UTIL.coalesceInt(jclient.attr('email_package_cd'), 0);
17443    		var textPackage = 20;
17444    		var isChecked = $(element).prop('checked');
17445    		
17446    		if (!isChecked) { textPackage = 0; }
17447    		
17448    		if (email_package_cd > 0 || textPackage === 0) {
17449    			GLO.Message.Marketing.saveTextPackage(textPackage);
17450    		} else {
17451    			$(element).prop('checked', !isChecked);
17452    			var url = 'provider/manage/Upgrade?reason=email-blast&highlight=message-package';
17453    			
17454    			if (!UTIL.isEmpty(helloback)) {
17455    				url += '&' + helloback;
17456    			}
17457    			
17458    			GLO.Uri.gotoUri(url, this);
17459    		}
17460    	}
17461        
17462        return _conAdvancedClient;
17463    })();
17464    
17465    
17466    _conAdvanced.Help = (function() {
17467        function _conAdvancedHelp() { }
17468        var _ojPop = null;
17469        
17470        _conAdvancedHelp.realign = function() {
17471        	if (_ojPop) {
17472        		_ojPop.realign();
17473        	}
17474        }
17475        
17476        function _open(h1, msg, mustRemovePadding) {
17477        	var jhtm = $('<div><h1 class="friendly-msg">' + h1 + '</h1><div class="friendly-msg3">' + msg + '</div></div>');
17478        	_ojPop = new GLO.Popup.Custom(jhtm);
17479        	var jpop = _ojPop.getPopup().addClass('pop-help');
17480        	
17481        	var jbtns = jpop.find('.pop-buttons');
17482        	jbtns.find('.btnSave').remove();
17483        	jbtns.find('.btnCancel').addClass('btnOk').addClass('btnCancelWhite').css({ "float": "none", "margin": 0, "padding": 0 }).find('>a').css({ "padding": "4px 10px 3px" }).text('Close');
17484        	
17485        	if (mustRemovePadding) {
17486        		jpop.find('h1').css({ "margin-bottom": "0" });
17487        		var jmsg = jpop.find('.msg').css({ "padding": "0" });
17488        		jmsg.find('p').css({ "margin-left": "20px", "margin-right": "4px" });
17489        	}
17490        	
17491        	return jpop;
17492        }
17493        
17494        _conAdvancedHelp.open = function(h1, msg, mustRemovePadding) {
17495        	return _open(h1, msg, mustRemovePadding);
17496        }
17497        
17498        _conAdvancedHelp.openAboutQuestionMark = function() {
17499        	var questionMark = '<span class="helpIcon2 sa-sprite" style="float: left; margin-top: 3px; margin-left: 4px;"></span>';
17500        	var msg1 = '<span style="float: left;">Whenever you see a blue question mark </span>';
17501        	var msg2 = '<span style="float: left; clear: both; margin-bottom: 12px;"> press it to see more information on that subject</span>';
17502        	var msg3 = '<div style="clear: both;"> </div>';
17503        	
17504        	_open('Blue Question Mark', '<div>' + msg1 + questionMark + msg2 + msg3 + '</div>');
17505        }
17506        
17507        _conAdvancedHelp.openClientEmail = function() {
17508        	var url1 = '/provider/webtemplate/email?helloback=advanced&tabback=client';
17509        	var url2 = '/provider/profile/1?helloback=advanced&tabback=client';
17510        	
17511        	var msg1a = 'You can have ' + GLO.Info.getScheduleAnyoneHtm(
17511) + ' email your clients reminders, confirmations, receipts, appointment follow-ups, and marketing messages';
17512        	var msg1b = 'Go to your <a onclick="GLO.Uri.gotoUri(\'' + url1 + '\', this)">Email Template</a> to customize the emails your clients receive';
17513        	var msg2 = '';
17514        	
17515        	/*
17516        	var aProfileMe = '<a onclick="GLO.Uri.gotoUri(\'' + url2 + '\', true)">Profile -> Me</a>';
17517        	var btnClientSetup = '<span class="btnAdd btnAction2 btnClientSetup"> <a style="padding: 0 8px;">Client Setup</a> </span>';
17518        	msg2 = 'Go to ' + aProfileMe + ' and press the ' + btnClientSetup + ' button to set when reminders are sent to your clients and if you want confirmations to also be sent to your clients';
17519        	msg2 = <p style="margin-top: 20px;">' + msg2 + '</p>';
17520        	*/
17521        	
17522        	var htm = '<p>' + msg1a + '</p> <p style="padding-bottom: 8px; border-bottom: 1px solid #444;">' + msg1b + '</p>' + msg2;
17523        	
17524        	_open('Customize Emails To Your Clients', htm).css({ "background-color": "rgb(240, 250, 250)" });
17525        }
17526        
17527        
17528        _conAdvancedHelp.Calendar = (function() {
17529        	function _conAHelpCal() { }
17530        	
17531        	_conAHelpCal.openSignin = function() {
17532        		var h1 = 'Client Self Sign-In Screen';
17533        		var header = '<p>Change What Happens When a Client Signs In</p>';
17534        		var waitIcon = '<span id="wait-list-icon" class="letter-over-background wait-list-icon-fixed" onclick="GLO.WaitList.open()" title="1 clients on the waiting list">W</span>';
17535        		var commingSoon = '<b class="sa-soon" style="font-size: 14px;">Comming Soon</b>';
17536        		var commingSoon2 = '<b class="sa-soon">Comming Oct 2024</b>';
17537        		
17538        		var label1 = '<h3>Add to Waiting List <i style="font-size: small;">Default</i></h3>';
17539        		var ul1 = GLO.Template.ClientSignin.helpWaitListItem();
17540        		var msg1 = 'All client sign-ins added to the Waiting List, press ' + waitIcon + ' at the top of the Calendar to open wait list and see your sign-ins';
17541        		var opt1 = label1 + '<div class="sign-in-option">' + '<p>' + msg1 + '</p>' + ul1 + '</div>';
17542        		
17543        		var label2 = '<h3>Auto Check-In Existing Appointment</h3>';
17544        		var msg2 = 'When a client signs-in';
17545        		var li2a = '<li>if client has pre-booked appointment <b class="html-arrow"></b> Check-In Appointment</li>';
17546        		var li2b = '<li>if client has no appointment <b class="html-arrow"></b> Add Sign-In to the Waiting List</li>';
17547        		var opt2 = label2 + '<div class="sign-in-option">' + '<p>' + msg2 + '</p>' + '<ul>' + li2a + li2b + '</ul></div>';
17548        		
17549        		var label3 = '<h3>' + 'Auto Sign-In Appointment</h3>';
17550        		var msg3 = 'When a client signs-in';
17551        		var li3a = '<li>if client has pre-booked appointment <b class="html-arrow"></b> Sign-In Appointment</li>';
17552        		var li3b = '<li>if client has no appointment <b class="html-arrow"></b> Create Appointment</li>';
17553        		var opt3 = label3 + '<div class="sign-in-option">' + '<p>' + msg3 + '</p>' + '<ul>' + li3a + li3b + '</ul></div>';
17554        		
17555        		var label4 = '<h3>' + commingSoon + 'Auto Create Appointment</h3>';
17556        		var msg4 = commingSoon2 + 'When a client signs-in';
17557        		var how4b = '<a onclick="GLO.Provider.Advanced.Help.Calendar.autoCreateAppt()" style="display: inline-block; margin-left: 4px; font-weight: bold;">How this works</a>';
17558        		var li4a = '<li>if client has pre-booked appointment <b class="html-arrow"></b> Check-In Appointment</li>';
17559        		var li4b = '<li>if client has no appointment <b class="html-arrow"></b> Create Appointment' + how4b + '</li>';
17560        		var opt4 = label4 + '<div class="sign-in-option">' + '<p>' + msg4 + '</p>' + '<ul>' + li4a + li4b + '</ul></div>';
17561        		
17562        		return _open(h1, '<div id="pop-help-signin-options">' + header + opt1 + opt2 + opt3 + opt4 + '</div>');
17563        	}
17564        	_conAHelpCal.autoCreateAppt = function() {
17565        		var h1 = 'Client Self Sign-In: Auto-Create';
17566        		var commingSoon = '<b class="sa-soon">Comming Soon</b>';
17567        		var bFeature = '<b style="color: rgb(40, 80, 240);">';
17568        		var bArrow = '<b class="html-arrow"></b>';
17569        		var small = '<small style="letter-spacing: 0;">';
17570        		
17571        		var p1 = '<p>' + commingSoon + '<b>Auto Sign-In Existing Appointment or Create Appointment</b></p>';
17572        		var p2 = '<p>Client Signs in and does not have an appointment, then appointment is automatically created</p>';
17573        		var p3 = '<p>This feature requires enabling ' + bFeature + 'First Available</b> or ' + bFeature + 'Turn Tracking</b> to know which staff to assign to appointment</p>';
17574        		var msg = p1 + p2 + p3;
17575        		
17576        		var li1a = '<li>if staff is available within 15 minutes ' + bArrow + ' create appointment</li>';
17577        		var li1b = '<li>if staff not available within 15 minutes ' + bArrow + ' add to wait list</li>';
17578        		var ol1 = '<ul style="">' + li1a + li1b + '</ul>';
17579        		var li1 = '<li>' + bFeature + 'Staff Selected</b> If client selects staff ' + small + '(when sigin in)</small>' + bArrow + 'run search to verify staff is available' + ol1 + '</li>';
17580        		
17581        		var small2 = small + 'who does the service(s) + is available</small>';
17582        		var li2 = '<li>' + bFeature + 'Turn Tracking</b> If no staff selected during sign-in and using turn tracking, then assign staff by finding which staff is next ' + small2 + '</li>';
17583        		
17584				var li3 = '<li>' + bFeature + 'First Available</b> If no staff selected and not using turn tracking ' + bArrow + ' create appointment under First Available</li>';
17585				var li4 = '<li>' + bFeature + 'Wait List</b> If cannot assign staff then adds sign-in to Waiting List</li>';
17586        		
17587        		return _open(h1, '<div id="pop-help-signin-auto-create">' + msg + '<ol>' + li1 + li2 + li3 + li4 + '</ul></div>');
17588        	}
17589        	
17590        	_conAHelpCal.openPrintTraveler = function() {
17591        		var h1 = 'Print Traveler';
17592        		var imgTraveler = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/print-traveler2.png" style="min-height: 120px; width: 90%; max-width: 320px; margin-bottom: 0;"></div>';
17593        		
17594        		var label1 = '<h3 style="margin-top: 0;">None</h3>';
17595        		var msg1 = '<p>Do Not Print Traveler</p>';
17596        		
17597        		var label2 = '<h3>Display Print Option on Check-In</h3>';
17598        		var msg2 = '<p>When Check-In Appointment have option to <b>Check-In & Print Traveler</b></p>';
17599        		
17600        		var label3 = '<h3>On Check-In</h3>';
17601        		var msg3 = '<p>Automatically Print Traveler when Check-In Appointment</p>';
17602        		
17603        		var label4 = '<h3>On Check-In (Walk-Ins Only)</h3>';
17604        		var msg4 = '<p>Only Automatically Print Traveler when Check-In Walkin Appointment (if appointment pre-booked do not print traveler)</p>';
17605        		
17606        		var imgEditApptUrl = GLO.Data.cdnDirectory + 'image/faq/appointment/edit/checkin-and-print-traveler2.png';
17607        		var imgEditAppt = '<div><img src="' + imgEditApptUrl + '" style="min-height: 120px; width: 90%; max-width: 480px; margin-bottom: 0;"></div>';
17608        		var noteList = '<ol><li>Open appointment</li><li>Press blue triangle to right of client name</li><li>Select "Print Appointment"</li></ol>';
17609        		var notePrintAppt = '<div id="pop-help-print-traveler-note"><p style="margin-top: 32px;">Also, you can always Print Appointments</p>' + noteList + '</div>';
17610        		
17611        		var aInvoice = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=other&id=faq-other-pay-invoice-online\', null, this, event)">Invoices</a>';
17612        		var aReceipt = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/receipt?helloback=advanced&tabback=payment\', this, event, true)">Receipts</a>';
17613        		var notePrintReceipt = '<div id="pop-help-print-traveler-receipt"><p style="margin-top: 32px;">You can also print ' + aInvoice + ' and ' + aReceipt + '</p></div>';
17614        		
17615        		var urlCustomize = 'provider/manage/traveler?helloback=advanced&tabback=appointments';
17616        		var btnCustomize = '<span class="btnAdd btnCustomize">
17616<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlCustomize + '\', this, event, true)">Customize</a></span>';
17617        		
17618        		var htm = btnCustomize + imgTraveler + label1 + msg1 + label2 + msg2 + label3 + msg3 + label4 + msg4 + imgEditAppt + notePrintAppt + notePrintReceipt;
17619        		var jpop = _open(h1, '<div id="pop-help-print-traveler">' + htm + '</div>');
17620        		jpop.find('.msg').css({ "max-width": "720px" });
17621        		
17622        		setTimeout(function() {
17623        			if (_ojPop && _ojPop.realign) {
17624        				_ojPop.realign();
17625        			}
17626        		}, 1200);
17627        	}
17628        	
17629        	_conAHelpCal.openRequireClient = function() {
17630        		var h1 = 'Require Client on Create Appointment';
17631        		var msg1 = '<p>Leave un-checked if you want to create appointments without including a client on the appointment</p>';
17632        		var msg2 = '<p>If this is turned on, when attempting to create an appointment without a client name will trigger this message:</p>';
17633        		var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/create-appt-require-client-name.png" style="max-width: 300px; min-height: 200px; width: 80%; border-radius: 20px;"/> </div>';
17634        		var msgZ = '<p>This setting does <b>not</b> affect Personal Time Appointments (Off, Lunch, Vacation, etc) which never include a client</p>';
17635        		
17636        		return _open(h1, '<div>' + msg1 + msg2 + img + msgZ + '</div>');
17637        	}
17638        	
17639        	_conAHelpCal.openDisplayClientRequest = function() {
17640        		var h1 = 'Display Client Request Checkbox';
17641        		var msg1 = '<p>You can include a client request checkbox to indicate if the client specifically requested the given staff member</p>';
17642        		var msg2 = '<p>This will add a checkbox to the create appointment and the edit appointment popups</p>';
17643        		
17644        		var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/create-appointment-client-requested.png" style="max-width: 300px; min-height: 200px; width: 80%;"/> </div>';
17645        		var img2 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/edit-appointment-client-requested.png" style="max-width: 480px; min-height: 24px; width: 80%;"/> </div>';
17646        		
17647        		var msg3 = '<p>If there are multiple staff on an appointment clicking the client requested checkbox allows you to select staff</p>';
17648        		var img3 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/staff-requested-by-client.jpg" style="max-width: 300px; min-height: 40px; width: 80%;"/> </div>';
17649        		
17650        		var a = '<b onclick="GLO.Provider.Advanced.Help.Calendar.openDisplayRunningTotal()" style="color: rgb(40, 80, 240); cursor: pointer;">Display Turn Tracking (Who is Next)</b>';
17651        		var msgZ = '<p>If you are using ' + GLO.Info.getScheduleAnyoneHtm() + ' to determine who gets the next walkin (by using the ' + a + ' option) then requested clients are ignored in determining who\'s next</p>';
17652        		
17653        		_open(h1, '<div>' + msg1 + msg2 + img1 + img2 + msg3 + img3 + msgZ + '</div>').css({ "background-color": "rgb(240, 250, 250)" });
17654        	}
17655        	
17656        	_conAHelpCal.openHasFirstAvailable = function() {
17657        		var h1 = 'First Available';
17658        		var css1 = 'margin-bottom: 16px; padding: 6px; padding-left: 20px; text-align: left; border-bottom: 1px solid #444; background-color: pink;';
17659        		var msg1 = '<div style="' + css1 + '">First Available gives you more control over your clients and staff, with the ability to benefit from the time savings, productivity, and increased sales that online booking offers</div>';
17660        		
17661        		var msg2 = '<p>With First Available you can restrict online booking so clients only book appointments with "First Available" and then at your convenience you assign the client to the desired staff</p>';
17662        		var msg3 = '<p>The appointment search looks at how many staff you have working at the desired time, what services the staff perform, and then returns openings for "First Available" based on availability</p>';
17663        		
17664        		var msg4 = '<p>The appointment is then saved under the first available column on the calendar</p>';
17665        		var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/first-available-calendar.png" style="max-width: 600px; min-height: 120px; width: 98%;"/> </div>';
17666        		
17667        		var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column\', this)">Profile ' + UI.arrow + ' Staff</a>';
17668        		var anyone = '<b style="color: green;">Anyone</b>';
17669        		var existing = '<b style="color: orange;">Existing</b>';
17670        		var msgZ = '<p style="">Go to ' + aProfile + ' and set the Client Online Booking option for "First Available" to ' + anyone + ' or ' + existing + ', then set the online booking option as desired for all other staff</p>';
17671        		
17672        		var jpop = _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + img + msgZ + '</div>', true);
17673        		jpop.find('.msg > div').css({ "padding": "0" });
17674        	}
17675        	
17676        	_conAHelpCal.openHasFirstAvailable2 = function() {
17677        		var h1 = 'First Available';
17678        		var css1 = 'margin-bottom: 16px; padding: 6px; padding-left: 20px; text-align: left; border-bottom: 1px solid #444; background-color: pink;';
17679        		var msg1 = '<div style="' + css1 + '">First Available gives you more control over your clients and staff, while benef
17679iting from the time savings, productivity, and increased sales of having online booking</div>';
17680        		
17681        		var msg2 = '<li>When a client searches for an appointment, ' + GLO.Info.getScheduleAnyoneHtm() + ' looks at how many staff you have working at the requested time, what services the staff perform, and then returns openings for "First Available" based on your staff available</li>';
17682        		
17683        		var msg3 = '<li>The appointment is saved under the first available column on the calendar</li>';
17684        		var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/first-available-calendar.png" style="max-width: 600px; min-height: 120px; width: 98%;"/> </div>';
17685        		
17686        		var msg4 = '<li>Then at your convenience you assign the client to the staff that fits best</li>';
17687        		
17688        		/*
17689        		var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column\', true)">Profile -> Staff</a>';
17690        		var anyone = '<b style="color: green;">Anyone</b>';
17691        		var existing = '<b style="color: orange;">Existing</b>';
17692        		var msgZ = '<p style="">Go to ' + aProfile + ' and set the Client Online Booking option for "First Available" to ' + anyone + ' or ' + existing + ', then set the online booking option as desired for all other staff</p>';
17693        		*/
17694        		
17695        		var msg5 = '<p style="font-size: initial;">This also defaults appointment requests and the waiting list (if enabled) to "First Available"</p>';
17696        		
17697        		var msgMain = '<ol>' + msg2 + msg3 + msg4 + '</ol>';
17698        		var jpop = _open(h1, '<div>' + msg1 + msgMain + img + msg5 + '</div>', true);
17699        		
17700        		if (innerWidth > 700) {
17701        			jpop.css({ "max-width": "90%" });
17702        		}
17703        		
17704        		setTimeout(function() {
17705        			GLO.Provider.Advanced.Help.realign();			//= gives the image a little time to load.
17706        		}, 900);
17707        		
17708        		GLO.Provider.Advanced.Help.realign();
17709        		return jpop.find('.msg > div').css({ "padding": "0" });
17710        	}
17711        	
17712        	_conAHelpCal.openDisplayRunningTotal = function() {
17713        		var h1 = 'Turn Tracking (Who is Next)';
17714        		var css1 = 'margin-bottom: 16px; padding: 6px; padding-left: 20px; text-align: left; border-bottom: 1px solid #444; background-color: pink;';
17715        		var msg1 = '<div style="' + css1 + '">Use ' + GLO.Info.getScheduleAnyoneHtm() + ' to calculate which staff member gets the next walkin client</div>';
17716        		
17717        		var signin = '<span style="display: inline-block; height: 28px; padding: 0 4px; border-top-left-radius: 6px; border-top-right-radius: 6px; background-color: rgba(136,136,136,.8); color: white;">sign-in</span>';
17718        		var clockInHelp = '<span class="helpIcon2 sa-sprite" onclick="GLO.Provider.Commission.openReportHelp(1)" title="Overview of Clock In/Out, Wages, and Timesheets"></span>';
17719        		var ol1a = '<div style="max-width: 680px;">If you want to track staff hours you can have your clients clock in/out' + clockInHelp + '</div>';
17720        		var ol1 = '<li>Staff check-in when they arrive: <small>by clicking ' + signin + ' above their name on the calendar</small>' + ol1a + '</li>';
17721        		
17722        		var ol2 = '<li><b style="color: rgb(40, 80, 240);">Who is Next</b> is determined by the order the staff checks in and how many walkins they have had today</li>';
17723        		var ol3 = '<li>The staff with the green calendar header gets the current walkin</li>';
17724        		var ol4 = '<li>The staff with the yellow calendar header gets the next walkin</li>';
17725        		var ol5 = '<li>Each staff\'s daily sales total is displayed at the top of the calendar <i style="display: block; padding-left: 8px;">(this amount can be displayed in dollar amount or in hours)</i></li>';
17726        		var ol6 = '<li>Click the calendar header to sign-out the staff or re-arrange the staff order on the calendar</li>';
17727        		
17728        		var ol = '<ol style="margin-left: 40px;">' + ol1 + ol2 + ol3 + ol4 + ol5 + ol6 + '</ol>';
17729        		var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/front-desk-cal-who-is-next.png" style="max-width: 600px; min-height: 80px; width: 96%;"/> </div>';
17730        		
17731        		return _open(h1, '<div>' + msg1 + ol + img + '</div>', true);
17732        	}
17733        	
17734        	function _getButtonCheckinHelp() {
17735        		var btnCheckin = '<span style="padding: 2px 8px; letter-spacing: 1px; border: 1px solid #c5dbec; border-radius: 20px; font-weight: bold; font-size: 12px; color: black;">Check-In</span>';
17736        		return '<span style="display: inline-block; border-radius: 20px; background-color: rgba(220,240,0, .8);">' + btnCheckin + '</span>';
17737        	}
17738        	function _getButtonCheckoutHelp() {
17739        		var btnCheckout2 = '<span style="padding: 2px 8px; letter-spacing: 1px; border: 1px solid #c5dbec; border-radius: 20px; font-weight: bold; font-size: 12px; color: rgb(240,240,240);">
17739Check-Out</span>';
17740        		return '<span style="display: inline-block; border-radius: 20px; background-color: rgba(20,200,120,.8);">' + btnCheckout2 + '</span>';
17741        	}
17742        	function _getButtonPosHelp() {
17743        		var css = 'position: relative; display: inline-block; height: 16px; width: 60px; padding: 4px 12px 3px; line-height: 1.2; font-size: 14px; background-color: black; color: white;';
17744        		var cssSmall = 'position: absolute; top: 7px; left: 10px; padding-right: 2px; letter-spacing: 0; font-size: 10px;'
17745        		
17746        		var btnInner = '<small style="' + cssSmall + '">go to</small><b style="position: absolute; top: 6px; right: 12px;">POS</b>';
17747        		var btnPOS2 = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'/pos\', this, event, true)" style="' + css + '">' + btnInner + '</a>';
17748        		
17749        		return '<span id="btnGoToPos" class="btnAdd">' + btnPOS2 + '</span>';
17750        	}
17751        	function _getButtonRefreshHelp() {
17752        		return '<b id="cal-refresh-icon" class="fa fa-refresh" style="position: relative; top: inherit; right: inherit; color: black;">&#x21bb;</b>';
17753        	}
17754        	function _getPosModeNote(isCheckout) {
17755        		var btnRefresh = _getButtonRefreshHelp();
17756        		var btnCheckIn = _getButtonCheckinHelp();
17757        		var btnCheckout = _getButtonCheckoutHelp();
17758        		var btnPOS = _getButtonPosHelp();
17759        		
17760        		var threeBtns = 'Adds 4 buttons to <b class="calendar-mode">Front Desk Calendar</b> ' + btnCheckIn + ' ' + btnCheckout + ' ' + btnRefresh + ' ' + btnPOS;
17761        		//var viewInSmall = '<small style="letter-spacing: 0;">(upper-right corner)</small>';
17762        		//var viewIn = '<p><i>Edit Appointment popup</i> press appointment length ' + viewInSmall + ' to open appointment in POS Screen</p>';
17763        		var h4 = '<h4 style="margin-bottom: 4px; padding: 2px; text-align: center; border-radius: 24px; font-size: 16px; background-color: rgba(0,0,0,.8); color: white;">Full P.O.S. Mode</h4>';
17764        		
17765        		if (isCheckout) {
17766        			var msg = 'Quickly Check-Out clients on both <b class="calendar-mode">Calendar</b> and <b class="pos-mode">P.O.S. Screen</b>';
17767        		} else {
17768        			var msg = 'Quickly Check-In and Check-Out appointments on both <b class="calendar-mode">Calendar</b> and <b class="pos-mode">P.O.S. Screen</b>';
17769        		}
17770        		
17771        		var msg2 = '<p>With Quick Check-In and Check-Out there is no need to enter appointment time ' + GLO.Info.getScheduleAnyoneHtm() + ' automatically calculates that for you</p>';
17772        		var msg3 = '<p>The <b class="calendar-mode">Calendar</b> and <b class="pos-mode">P.O.S.</b> integrate giving you all the scehduling features along with the ease of use of the <b class="pos-mode">P.O.S. Screen</b></p>';
17773        		
17774        		return '<div style="margin-top: 48px; font-size: smaller;">' + h4 + '<p>' + msg + '</p><p>' + threeBtns + '</p>' + msg2 + msg3 + '</div>';
17775        	}
17776        	_conAHelpCal.openPosNote = function() {
17777        		var msg1 = '<p>Add the P.O.S. buttons to the top of the front desk calendar to speed up checking in and out clients</p>';
17778        		var msg2 = '<p style="font-style: italic;">The front desk calendar is the calendar with all your staff on 1 screen</p>';
17779        		
17780        		var note = _getPosModeNote();
17781        		var htm = '<div id="pop-help-check-settings">' + msg1 + msg2 + note + '</div>';
17782        		return _open('Quick Check-In/Out', htm);
17783        	}
17784        	_conAHelpCal.openCheckInSettings = function() {
17785        		var b = '<b style="letter-spacing: 0; font-family: arial; font-size: large; color: black;">';
17786        		var small = '<small style="display: block; margin-top: 4px; margin-left: 24px; letter-spacing: 0;">';
17787        		var li1 = b + 'Normal</b> Automatically Check-In New Appointment ' + small + ' when create new appointment that start within 10 minutes, 20 minutes if paid</small>';
17788        		//var li2 = b + 'Check-In button on Calendar</b> add ' + _getButtonCheckinHelp() + ' to <b class="calendar-mode">Front Desk Calendar</b> to easily lookup appointment for quick check-in and adjustments</small>';
17789        		//var li2 = '<b>Normal with Refresh</b> Adds refresh button at top of <b class="calendar-mode">Front Desk Calendar</b> ' + _getButtonRefreshHelp();
17790        		//var li3 = '<b>Quick, Auto Check-In with POS</b> Adds <b class="pos-mode">P.O.S.</b> Mode to <b class="calendar-mode">Front Desk Calendar</b> ' + small + 'to easily lookup appointment for quick check-in</small>';
17791        		var li2 = b + 'Strict</b> Do Not Automatically Check-In Appointments';
17792        		var ul = '<ul id="pop-help-check-settings-list"> <li>' + li1 + '</li> <li>' + li2 + '</li> </ul>';
17793        		
17794        		var msg = '';
17795        		var note = _getPosModeNote();
17796        		var htm = '<div id="pop-help-check-settings">' + msg + ul + note + '</div>';
17797        		return _open('Check-In Settings', htm);
17798        	}
17799        	_conAHelpCal.openCheckOutSettings = function() {
17800        		var span = '<span style="display: inline-block; margin-left: 24px;">';
17801        		
17802        		var li1 = '<b>Normal</b> Automatically checkout appointment when paid during appointment'
17803        				+ span + 'specifically paid 30 minutes before apointment, during appointment, or after appointment</span>';
17804        		
17805        		//var li2 = '<b>Normal with P.O.S.</b>';
17806        				
17807        		var li2 = '<b>Quick</b> Similar to normal but also ends appointment when Checkout'
17808        				+ span + 'When appointment checked out automatically mark current time as end of appoinment '
17809        				+ '<small>(if appointment has already started)</small> so staff can start on next client</span>';
17810        				// automatically adjusts service time so appointment ends at Check-Out time
17811        		
17812        		var li3 = '<b>Review</b> Keep ticket open after payment'
17813        				+ span + 'During checkout, when pay full amount with credit card do not auto-close ticket</span>';
17814        		
17815        		var li4 = '<b>Review if no Tip</b> Keep ticket open after payment'
17816        				+ span + 'During checkout, when pay full amount with credit card do not auto-close ticket if the ticket has no tip</span>';
17817        		
17818        		//var li4 = '<b>Quick with P.O.S.</b>';
17819        		var ul = '<ul style="margin-left: 0;"> <li>' + li1 + '</li> <li>' + li2 + '</li> <li>' + li3 + '</li>  <li>' + li4 + '</li> </ul>';
17820        		
17821        		var btnCheckout = _getButtonCheckoutHelp();
17822        		var msg1 = '';		//'<b>Normal</b> works best for most businesses';
17823        		//var msg2 = '<b>Quick</b> adds ' + btnCheckout + ' button at the top of <b class="calendar-mode">Front Desk Calendar</b> to use <b class="pos-mode">Quick Check-In mode</b> which helps find: appointment, client, and add/change services';
17824        				//When add service: automatically uses previous service\'s staff
17825        		var msg = '<div style="margin-bottom: 32px; border-bottom: 1px grey solid; font-size: smaller;"><p>' + msg1 + '</p></div>';
17826        		
17827        		var note = _getPosModeNote();
17828        		var htm = '<div id="pop-help-check-settings">' + ul + note + '</div>';
17829        		return _open('Check-Out Settings', htm);
17830        	}
17831        	_conAHelpCal.openCheckoutRestriction = function() {
17832        		var li = '<li style="margin-bottom: 20px;">';
17833        		var span = '<span style="display: block; margin-left: 24px;">';
17834        		var small = '<small style="display: inline-block; margin-left: 4px; letter-spacing: 0; white-space: nowrap;">';
17835        		
17836        		var li1 = '<b>No Payment Restriction</b>' + span + 'Can checkout an appointment that is not fully paid</span>';
17837        		
17838        		var li2 = '<b>Receptionists and Other Staff Require Payment</b>'
17839        				+ span + 'Receptionists cannot checkout appointment that is not fully paid</span>'
17840        				+ span + 'Once an appointment is checked-out the appointment date cannot be changed</span>'
17841        				+ span + small + '(only staff with manager or admin role can checkout appointment that is not fully paid or move appointment that is checked-out)</small></span>';
17842        		
17843        		var li3 = '<b>Full Payment Required to Checkout Appointment</b>'
17844        				+ span + 'No one can checkout appointment that is not fully paid</span>'
17845        				+ span + 'Once an appointment is checked-out the appointment date cannot be changed</span>'
17846        				+ span + small + '(Even Manager/Admin cannot checkout un-paid tickets; to move checked-out appointment first must change appointment status)</small></span>';
17847        		
17848        		var ul = '<ul style="margin-left: 0;"> <li>' + li1 + '</li> <li>' + li2 + '</li> <li>' + li3 + '</li> </ul>';
17849        		
17850        		var btnCheckout = _getButtonCheckoutHelp();
17851        		var note = '<div style="font-style: italic; font-size: smaller;"> <b>Fully Paid</b> <span>when ticket payment >= ticket price</span> </div>';
17852        		var htm = '<div id="pop-help-check-settings">' + ul + note + '</div>';
17853        		
17854        		return _open('Check-Out Payment Restriction', htm);
17855        	}
17856        	
17857        	_conAHelpCal.openStaffTextAlert = function() {
17858        		var alerts = '<b class="narrow-text">Check-In / Sign-In alerts</b>';
17859        		var inApp = '<i class="narrow-text">in-app notifications</i>';
17860        		var text = '<i class="narrow-text">text messages</i>';
17861        		var saApp = GLO.Info.getScheduleAnyoneHtm(false, true) + ' app';
17862        		
17863        		var aEnableText = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/advanced?open=tab-appointment&highlight=advanced-feature-staff-alert-text")\'>Staff Alert Texts Enabled</a>'
17864        		var aEnableInApp = '<a onclick=\'GLO.Uri.gotoUri2("help#tab=message&id=faq-message-staff-in-app-notifications")\'>Enable Notifications</a>';
17865        		var aResetInApp = '<a onclick=\'GLO.Uri.gotoUri2("help#tab=message&id=faq-message-staff-in-app-notifications-reset")\'>Reset In-App Notifications</a>';
17866        		
17867        		var inAppEnable = ' <small class="narrow-text">(must ' + aEnableInApp + ' in the ' + saApp + ')</small>';
17868        		var textEnable = ' <small class="narrow-text">(must have ' + aEnableText + ' | texts cost 1 cent per message)</small>';
17869      			
17870        		var msg1 = '<p style="margin-bottom: 0;">When ' + aEnableText + ' staff can choose if they want ' + alerts + ' to be:</p>';
17871        		var li = '<li style="line-height: 1.2;">';
17872        		var ul1 = '<ul>' + li + inApp + inAppEnable + '</li>
17872' + li + 'or ' + text + textEnable + '</li></ul>';
17873        		
17874        		var msg2 = '<p>Staff can go to their profile in the ' + saApp + ' to enable ' + alerts + '</p>';
17875        		var msg3 = '<p style="margin-bottom: 24px; line-height: 1.2;">Receptionists and admin can view and change ' + alerts + ' settings for each staff '
17876        						+ '<span class="narrow-text" style="white-space: normal;">(but only staff can enable ' + inApp + ' on their phone in the ' + saApp + ')</span></p>';
17877        		var msg4 = '<p>Instructions to ' + aEnableInApp + ' in the ' + saApp + '</p>';
17878        		var msg5 = '<p>Instructions to ' + aResetInApp + '</p>';
17879        		
17880        		return _open('Staff Sign-In & Check-In Alerts', '<div id="pop-help-staff-alerts">' + msg1 + ul1 + msg2 + msg3 + msg4 + msg5 + '</div>');
17881        	}
17882        	
17883        	_conAHelpCal.openHasAppointment = function() {
17884        		var h1 = 'Offer Appointments';
17885        		var msg = '<p style="padding-left: 20px; padding-top: 12px;">Check this box if your business schedules appointments with clients</p>';
17886        		
17887        		return _open(h1, '<div>' + msg + '</div>');
17888        	}
17889        	
17890        	_conAHelpCal.openHasClassOrEvent = function() {
17891        		var h1 = 'Classes or Events';
17892        		var msg1 = '<p>Does your business offer classes that your clients can attend or do you have events that your clients attend?</p>';
17893        		var msg2 = '<p>With ' + GLO.Info.getScheduleAnyoneHtm() + ' classes work similar to appointments, the differences are that with classes:</p>';
17894        		
17895        		var ul = '<ul>'
17896        					+ '<li>You first create the class, then open the class to add clients</li>'
17897        					+ '<li>You can add as many clients as you want to a class</li>'
17898        					+ '<li>If you offer online booking, you set the maximum number of clients that can reserve a spot in the class <small style="display: block;">(although it does not limit how many staff you can add to a class)</small></li>'
17899        					+ '<li>If you offer online booking clients don\'t create classes, they reserve a spot in classes that you have already created</li>'
17900        				+ '</ul>'
17901        		
17902        		var aProfileService = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/4?helloback=advanced&tabback=calendar\', this)">Profile ' + UI.arrow + ' Service</a>';
17903        		var aCalendar = '<a onclick="GLO.Uri.gotoUri(\'provider/calendar\', this)">Schedule -> Calendar</a>';
17904        		var msg3 = '<p style="line-height: 180%;">Once you have enabled class or events go to ' + aProfileService + ' to create class services, then you can go to ' + aCalendar + ' to create and edit classes</p>';
17905        		
17906        		return _open(h1, '<div>' + msg1 + msg2 + ul + msg3 + '</div>');
17907        	}
17908        	
17909        	_conAHelpCal.getStartDayOfWeek = function(day, isMobile) {
17910        		var dayLabel, day = UTIL.coalesceInt(day, GLO.Data.firstWeekDay);
17911        		
17912        		if (day === 1) {
17913        			dayLabel = 'Sunday';
17914        		} else if (day === 2) {
17915        			dayLabel = 'Monday';
17916        		} else if (day === 3) {
17917        			dayLabel = 'Tuesday';
17918        		} else if (day === 4) {
17919        			dayLabel = 'Wednesday';
17920        		} else if (day === 5) {
17921        			dayLabel = 'Thursday';
17922        		} else if (day === 6) {
17923        			dayLabel = 'Friday';
17924        		} else if (day === 7) {
17925        			dayLabel = 'Saturday';
17926        		}
17927        		
17928        		if (isMobile) {
17929        			return dayLabel.substring(0,3);
17930        		} else {
17931        			return dayLabel;
17932        		}
17933        	}
17934        	_conAHelpCal.openWeekStartDayQuick = function() {
17935        		var msg = 'The start day of the week is: ' + _conAHelpCal.getStartDayOfWeek();
17936        		var url = 'provider/manage/advanced?open=tab-appointment&highlight=advanced-cal-week-start';
17937        		var btnAdd = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)">Change Start of Week</a></span>';
17938        		var htm = '<div><p>' + msg + '</p><div style="margin-top: 12px; margin-bottom: 24px;">' + btnAdd + '</div></div>';
17939        		
17940        		GLO.Popup.Info.open(htm);
17941        	}
17942        	_conAHelpCal.openWeekStartDay = function(isAdvancedProfile) {
17943        		var h1 = 'First Day of the Week';
17944        		var aCal = '<a onclick="GLO.Uri.gotoUri(\'provider/calendarOne?sfilter=' + GLO.Info.StaffId + '#vw=agendaWeek\', this)">Calendar\'s Week View</a>';
17945        		var msg0 = '', msg3 = '', msg2 = '', msg1 = '<p style="padding-top: 8px; padding-bottom: 8px;">You can change the first day of the week on your ' + aCal + '</p>';
17946        		
17947        		if (GLO.Info.providerPackage != 1) {
17948        			/* if (GLO.Info.providerPackage === 2 || GLO.Info.providerPackage === 10) {
17949        				var rptPayroll = '<a onclick="GLO.Uri.gotoUri(\'report/payroll\', this)">Payroll</a>';
17950        				var rptTimesheet = '<a onclick="GLO.Uri.gotoUri(\'report/timesheet\', this)">Timesheet</a>';
17951        				var rptGoal = '<a onclick="GLO.Uri.gotoUri(\'report/StaffGoal?isActiveStaffOnly=1\', this)">Staff Goals</a>';
17952        				msg2 = '<p>this also changes the week start date on reports: ' + rptPayroll + ', ' + rptTimesheet + ', ' + rptGoal + '</p>';
17953        			} */
17954        			
17955        			msg3 = '<p>Changing this changes it for all staff members</p>';
17956        		}
17957        		
17958        		var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/week-calendar-start-sun.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>';
17959        		var img2 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/week-calendar-start-mon.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>';
17960        		var img3 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/week-calendar-start-tue.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>';
17961        		
17962        		if (!isAdvancedProfile) {
17963        			var link = '<a onclick="GLO.Uri.gotoUri(\'provider/manage/advanced?open=tab-appointment&highlight=advanced-cal-week-start\', this, event, true)">Profile -> Advanced, Appointment tab</a>';
17964        			msg0 = '<div>Change now: ' + link + '</div>';
17965        		}
17966        		
17967        		return _open(h1, '<div>' + msg0 + msg1 + img1 + img2 + img3 + msg2 + msg3 + '</div>');
17968        	}
17969        	
17970        	_conAHelpCal.getStaffOrderList = function(msg) {
17971        		var aCalendar = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/calendar\', this, event, true)">Front Desk Calendar</a>';
17972        		var aPos = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'pos\', this, event, true)">P.O.S. Screen</a>';
17973        		
17974        		var urlGallery = UserPortal.getProviderUri() + 'gallery/staff?helloback=advanced&tabback=appointments';
17975        		var aGallery = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlGallery + '\', this, event, true)">Website Staff Gallery</a>';
17976        		
17977        		msg = '<p id="staff-order-sort-help" style="margin-top: 16px; margin-bottom: 0; padding-bottom: 2px;">' + msg + '</p>';
17978        		
17979        		return '<div id="staff-order-sort-help">' + msg + '<ul id="staff-order-sort-list-help"> <li>' + aCalendar + '</li> <li>' + aPos + '</li> <li>' + aGallery + '</li> </ul> </div>';
17980        	}
17981        	_conAHelpCal.openStaffOrder = function() {
17982        		var h1 = 'Staff Order';
17983        		var msg1 = '<p>As staff clock-in they are moved to the start of the staff list on the <b class="narrow-text">P.O.S. Screen</b></p>';
17984        		var msg2 = '<p>By default your staff are displayed in alphabetical order</p>';
17985        		var msg3 = _conAHelpCal.getStaffOrderList('You can change the default order your staff are displayed on');
17986        		
17987        		return _open(h1, '<div id="pop-help-staff-order">' + msg1 + msg2 + msg3 + '</div>');
17988        	}
17989        	
17990        	return _conAHelpCal;
17991    	})();
17992        
17993        
17994        _conAdvancedHelp.Payment = (function() {
17995        	function _conAHelpPayment() { }
17996        	
17997        	function _currentSelfCheckoutSetting(aCustomApp) {
17998        		var aSetting = '<a onclick="GLO.Uri.gotoUri(\'provider/manage/advanced?open=tab-payment&highlight=advanced-payment-self-checkout\', this, event, true)">Self Checkout Setting</a>';
17999        		var msgStyle = ' style="margin-bottom: 0; padding-bottom: 2px; line-height: 1.4;"';
18000        		var msgHtm = '<p' + msgStyle + '>Based on the your ' + aSetting + ' clients can pay for their appointment from the</p>';
18001        		
18002        		var liLink = '<li>Self-Checkout Link</li>';
18003        		var liWeb = '<li>Client profile on your website</li>';
18004        		var liApp = '<li>' + aCustomApp + '</li>';
18005        		
18006        		if (GLO.Data.provider.self_checkout_cd < 20) {
18007        			liWeb = liApp = '';
18008        		//} else if (GLO.Data.provider.self_checkout_cd > 19 || GLO.Data.provider.self_checkout_cd < 40) {
18009        		} else if (GLO.Data.provider.self_checkout_cd > 59) {
18010        			//liLink = '<b style="color: red;">Self-Checkout Not Allowed</b>';
18011        			var aInvoiceLink = '<a onclick="GLO.FAQ.gotoQuestion(\'faq-other-pay-invoice-online\', \'other\', this, event)">Text/Email Client Invoice</a>';
18012        			
18013        			liLink = '<li>Only if ' + aInvoiceLink + '</li>';
18014        			liWeb = liApp = '';
18015        		}
18016        		
18017        		var listStyle = ' style="margin: 0; margin-bottom: 24px; padding-left: 32px; padding-bottom: 2px; line-height: 1.4;"';
18018        		var listHtm = '<ul' + listStyle + '>' + liLink + liWeb + liApp + '</ul>';
18019        		
18020        		return '<div style="padding-top: 4px; padding-left: 6px; background-color: rgba(20,200,100, .4);">' + msgHtm + listHtm + '</div>';
18021        	}
18022        	
18023        	_conAHelpPayment.openHowSelfCheckoutWorks = function() {
18024        		var aApptSurvey = '<a onclick="GLO.Uri.gotoUri(\'repman\', this)">Reputation Management</a>';
18025        		var aCustomApp = '<a onclick="GLO.Uri.gotoUri(\'provider/manage/CustomApp\', this, event, true)">Custom Mobile App</a>';
18026        		var aAllowTip = '<a id="goto-disable-tipping" onclick="GLO.Provider.Advanced.goToItem(\'payment\', \'advanced-payment-product-tip\', this)">Go here to disable tip option</a>';
18027        		var h1 = 'How Self Checkout Works';
18028        		
18029        		var msg1 = '<p>Allow clients to pay for their appointment on their phone</p>';
18030        		var msg2 = '<p></p>';
18031        		var msg3 = '<p style="margin-bottom: 2px;"></p>';
18032        		
18033        		var li1 = '<li>When open appointment or ticket select <b>Ready to Pay</b> or <b>Self-Checkout</b> to text client a link they can use to pay online</li>';
18034        		var li2 = '<li>Client clicks link in the text message which opens ticket summary</li>';
18035        		var li3 = '<li>In the ticket summary client presses <b>Pay Now</b></li>';
18036        		var li4 = '<li>
18036Client enters tip amount' + aAllowTip + '</li>';
18037        		var li5 = '<li>Client enters or selects credit card</li>';
18038        		var li6 = '<li>Receipt emailed to client</li>';
18039        		var li7 = '<li>If ' + aApptSurvey + ' enabled, client sees brief appointment survey and if they liked the appointment ' 
18040        					+ UI.arrow + ' the client is sent to your social media to leave a 5 star review!</li>';
18041        		
18042        		var currentSetting = _currentSelfCheckoutSetting(aCustomApp);
18043        		var staffOnlyNote = '<i class="narrow-text">(client not texted self-checkout link and cannot pay on website)</i>';
18044        		
18045        		var hSettings = '<h3 class="glopop-sub-header">Self Checkout Settings</h3>';
18046        		var opt1 = '<div><label>Require Ready to Pay</label> <span>Client can only pay with link texted to their phone when mark appointment as <b>Ready to Pay</b> or <b>Self-Checkout</b></span> </div>';
18047        		var opt2 = '<div><label>Allow on Day of Appointment</label> <span>Client can pay with self-checkout link and on the day of the appointment on your website or ' + aCustomApp + '</span> </div>';
18048        		var opt3 = '<div><label>Allow Anytime</label> <span>Client can pay with self-checkout link, your website, or ' + aCustomApp + '</span> </div>';
18049        		var opt4 = '<div><label>Staff Use Only</label> <span> <b>Ready to Pay</b> option only used by staff to indicate all services, add-ons, products, etc have been included on ticket and is ready for payment ' + staffOnlyNote + ' </span> </div>';
18050        		var opt5 = '<div><label>Disabled</label> <span>Do Not display <b>Ready to Pay</b> or <b>Self-Checkout</b> options</span></div>';
18051        		
18052        		var cssSetting = '';				//'padding-top: 8px; border-top: 1px solid;';		//font-size: smaller; 
18053        		var htmSetting = '<div id="help-self-checkout-options" style="' + cssSetting + '">' + hSettings + currentSetting + opt1 + opt2 + opt3 + opt4 + opt5 + '</div>';
18054        		
18055        		var hLink = '<h3 class="glopop-sub-header">Ready to Pay + Self-Checkout Link</h3>';
18056        		var p1 = '<p>New appointment status <b class="narrow-text">Ready to Pay</b> can be set on any appointment</p>';
18057        		var p2 = '<p>Marking appointment as <b class="narrow-text">Ready to Pay</b> or <b class="narrow-text">Self-Checkout</b> sends client a text message with a link they can use to pay for their appointment</p>';
18058    			var p3 = '<p>Before client is sent the text message with their <b class="narrow-text">Self-Checkout Link</b> you have option to include a short note in the text message</p>';
18059    			var p4 = '<p>Each <b class="narrow-text">Self-Checkout Link</b> is unique for each appointment</p>';
18060    			var p5 = '<p>The Self Checkout Link also acts as an <b class="narrow-text">automatic login link</b> for your client so they can easily pay with a card-on-file and book their next appointment</p>';
18061        		var htmLink = '<div id="help-self-checkout-options" style="' + cssSetting + '">' + hLink + p1 + p2 + p3 + p4 + p5 + '</div>';
18062        		
18063        		var hBenefits = '<h3 class="glopop-sub-header">Benefits</h3>';
18064        		var benefit1 = '<p>Helps build your client database: full client name, phone number, email, and card-on-file</p>';
18065        		var benefit2 = '<p>Allows clients to pay comfortably in the chair or room they are receiving services</p>';
18066    			var benefit3 = '<p>Allows faster checkout on days you are busiest</p>';
18067    			var benefit4 = '<p>When used with Reputation management generate more 5 star reviews in Google and Facebook</p>';
18068    			var benefit5 = '<p>Client automatically logged into their profile making it easier for them to book their next appointment</p>';
18069        		var htmBenefits = '<div id="help-self-checkout-benefits" style="' + cssSetting + '">' + hBenefits + benefit1 + benefit2 + benefit3 + benefit4 + benefit5 + '</div>';
18070        		
18071        		//var imgCSS = 'width: 90%; max-width: 480px; margin: 0; margin-left: -8px; padding: 2px 4px; border: 1px inset grey; border-radius: 8px;';
18072        		//var img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/online-booking-appointment-search.png" style="' + imgCSS + '"/> </div>';
18073        		
18074        		var jpop = _open(h1, '<div id="pop-help-self-checkout">' + msg1 + msg2 + msg3 + '<ol>' + li1 + li2 + li3 + li4 + li5 + li6 + li7 + '</ol>' + htmSetting + htmLink + htmBenefits + '</div>');
18075        		_conAdvancedHelp.realign();
18076        	}
18077        	
18078        	return _conAHelpPayment;
18079    	})();
18080        
18081        
18082        _conAdvancedHelp.Online = (function() {
18083        	function _conAHelpOnline() { }
18084        	
18085        	_conAHelpOnline.openOnlineBookingGuide = function(stepNumber) {
18086        		SA.Help.openReportHelp('#pop-how-to-guide-online-booking', stepNumber, 'info/HelpGuide?name=OnlineBookingHelp');
18087        	}
18088        	
18089        	_conAHelpOnline.openAppointmentSearch = function() {
18090        		var h1 = 'Online Booking Appointment Search';
18091        		
18092        		var msg1 = '<p>When client books online they cannot see your schedule</p>';
18093        		var msg2 = '<p>Client enters desired appointment then searches for best available opening</p>';
18094        		var msg3 = '<p style="margin-bottom: 2px;">
18094To book online, client enters</p>';
18095        		var li1 = '<li>Desired service(s)</li>';
18096        		var li2 = '<li>Desired staff <small>(or can leave blank if want first available)</small></li>';
18097        		var li3 = '<li>Day and time <small>(or can leave blank if want first available)</small></li>';
18098        		var li4 = '<li>Press search to see best available openings</li>';
18099        		var li5 = '<li>Select desired opening</li>';
18100        		
18101        		var imgMsg = '<p style="margin: 0; text-align: center; font-style: italic;">Sample screenshot of Client Booking Online</p>';
18102        		var imgCSS = 'width: 90%; max-width: 480px; margin: 0; margin-left: -8px; padding: 2px 4px; border: 1px inset grey; border-radius: 8px;';
18103        		var img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/online-booking-appointment-search.png" style="' + imgCSS + '"/> </div>';
18104        		
18105        		var jpop = _open(h1, '<div id="pop-help-appointment-search">' + msg1 + msg2 + msg3 + '<ol>' + li1 + li2 + li3 + li4 + li5 + '</ol>' + imgMsg + img + '</div>');
18106        		_conAdvancedHelp.realign();
18107        		
18108        		setTimeout(function() {
18109        			GLO.Provider.Advanced.Help.realign();
18110        		}, 1200);
18111        	}
18112        	
18113        	_conAHelpOnline.openEnableWaitListForClients = function() {
18114        		var h1 = 'Client Access to Waiting List';
18115        		
18116        		var msg1 = '<p>You can give clients access to add and remove themselves from your waiting list</p>';
18117        		var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-waiting-list-add.jpg" style="min-height: 120px; width: 90%; max-width: 420px;"/> </div>';
18118        		
18119        		var aOnClick = 'GLO.Uri.gotoUri(\'provider/WebTemplate/ConfigureLogin?back=%2fwizard%2fwebsite&helloback=website\', this)';
18120        		var aAdjustColors = '<a onclick="' + aOnClick + '" style="border-bottom: none;">(adjust colors here)</a>';
18121        		var smallAdjustColors = '<small style="padding-left: 12px;">' + aAdjustColors + '</small>';
18122        		var b1 = '<b style="padding: 2px 8px; white-space: nowrap; color: rgb(255,232,240); background-color: #9A26FF;">Add Me to the Waiting List</b>';
18123        		var msg2 = '<p style="margin-bottom: 20px;">After clients create an account and login clients will see a bar at the top that says: ' + b1 + smallAdjustColors + '</p>';
18124        		var msg3 = '';
18125        		
18126        		var msg4 = '<p>You have the option to allow clients to be able to request a specific date/time when adding themselves to your waiting list</p>';
18127        		var img2 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-waiting-list-popup.jpg" style="min-height: 360px; width: 80%; max-width: 280px;"/> </div>';
18128        		
18129        		var msg5 = '<p>Clients can see how many people are on your waiting list</p>';
18130        		var img3 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-waiting-list2.jpg" style="min-height: 120px; width: 90%; max-width: 420px;"/> </div>';
18131        		
18132        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + img1 + msg4 + img2 + msg5 + img3 + '</div>');
18133        	}
18134        	
18135        	_conAHelpOnline.openNotifyClientWhen = function() {
18136        		var h1 = 'Notify Client When They Are Next';
18137        		
18138        		var x = '<span style="display: inline-block;" class="ui-icon ui-icon-circle-close" title="click to delete this row from the waiting list"></span>';
18139        		//var plusCSS = 'width: 36px; height: 36px; text-align: center; font-size: 32px;'
18140        		//var plus = '<span class="wait-list-create-appt" title="Create Appointment & Remove from Waiting List"> <b style="' + plusCSS + '">+</b> </span>';
18141        		var spanDotStyle = 'min-width: 40px; padding: 0 2px; line-height: 120%; text-align: center; border-radius: 20px;';
18142				var dotCreate = '<span class="wait-list-create-appt" style="' + spanDotStyle + ' margin-right: 2px;"><b style="height: inherit; width: 42px; padding: 1px 2px 3px; font-size: 16px;">new</b></span>';
18143				var dotCheckin = '<span class="wait-list-create-appt wait-list-checkin-appt" style="' + spanDotStyle + '"><b style="height: inherit; width: 36px; font-size: 16px;">pre</b></span>';
18144        		
18145        		var msg1 = '<p>When you remove a client from the waiting list, you can have ' + GLO.Info.getScheduleAnyoneHtm(
18145) + ' send a text to the next client(s)</p>';
18146        		var msg2 = '<p>There are 3 ways to remove a client from the waiting list:</p>';
18147        		var msg3b = '<ul><li><small>Also in text message sent to the next client(s), includes an estimate start time</small></li></ul>';
18148        		var msg3 = '<ul>'
18149        					+ '<li style="list-style-type: decimal;">Press the ' + x + ' to the left of the client name to remove from wait list</li>'
18150        					+ '<li style="list-style-type: decimal;">Press the ' + dotCheckin + ' to sign-in pre-booked appointment and remove from wait list</li>'
18151        					+ '<li style="list-style-type: decimal;">Press the ' + dotCreate + ' to create appointment and remove from wait list</li>'
18152        				+ '</ul>';
18153        		var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/waiting-list-staff-view2.jpg" style="min-height: 120px; width: 90%; max-width: 600px;"/> </div>';
18154        		
18155        		var codeCSS = 'display: block; margin: 4px; margin-left: 24px; white-space: pre-wrap; color: darkgreen;';
18156        		var textSample = '<code style="' + codeCSS + '">Hi Mary! You are next on the waiting list for TriBeCa Salon, estimated start time is 5:15 pm at 146 E 56th St New York, NY</code>';
18157        		var msg4 = '<p>Here is an example of the text message sent to the client: ' + textSample + '</p>'
18158        		
18159        		var msg5css = 'margin-top: 12px; margin-bottom: 0; padding-top: 6px; text-align: center; border-top: 2px solid white; font-size: 85%; opacity: .8;';
18160        		var msg5 = '<p style="' + msg5css + '">This only applies to client\'s on <b style="color: #4F81BD;">Today\'s Waiting List</b></p>';
18161        		
18162        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + img1 + msg4 + msg5 + '</div>');
18163        	}
18164        	
18165        	_conAHelpOnline.openWaitingListToday = function() {
18166        		var h1 = 'Today\'s Waiting List';
18167        		var uriSignIn = UserPortal.getProviderUri() + 'SignIn?open=help-overview';
18168        		var aSignIn = '<a href="' + uriSignIn + '" style="font-weight: bold; color: deeppink; border-color: deeppink;">Client Sign-In Screen</a>';
18169        		var today = '<b style="font-style: italic; color: #4F81BD;">Today\'s Waiting List</b>';
18170        		
18171        		var msg1 = '<p>The ' + today + ' feature allows you to have a sub-section of the waiting list dedicated to the current day</p>';
18172        		var msg2 = '<p>This feature is great on busy days to help you keep track of who is next; enable and disable ' + today + ' as desired</p>';
18173        		var msg3 = '<p>Turning on ' + today + ' also enables the ' + aSignIn + ' which allows clients to sign-in themselves at your front desk</p>';
18174        		var msg4 = '<p>If you also enable clients to have access to the waiting list, then clients can add themselves to ' + today + '</p>';
18175        		var msg5 = '<p>You can even have ' + GLO.Info.getScheduleAnyoneHtm() + ' send a text to the next client(s) on ' + today + '</p>';
18176        		
18177        		if (GLO.Info.providerPackage == 1) {
18178        			msg3 = '';
18179        		} else if (GLO.Info.providerPackage == 4) {
18180        			msg4 = msg5 = '';
18181        		}
18182        		
18183        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>');
18184        	}
18185        	
18186        	_conAHelpOnline.openCustomAppChanges = function() {
18187        		var h1 = 'Custom App Changes';
18188        		var msg1 = '<p>When your app is opened it checks with ' + GLO.Info.getScheduleAnyoneHtm() + ' to see if anything has changed</p>';
18189                var msg2 = '<p>If you change your profile and do not see the changes in the app just <i style="color: #4F81BD;">kill the app</i>, and re-open it</p>';
18190        		
18191        		var pCSS = ' style="margin-left: 2%; margin-bottom: 0;"'
18192        		
18193        		var msg3 = '<div style="margin-top: 32px;">'
18194        					+ '<h4 style="padding-left: 0; text-align: left;">How Do I Kill An App?</h4>'
18195        					+ '<p' + pCSS + '><b>On an iPhone or iPad:</b> <ol style="margin-left: 8%;"> <li>Double click the home button</li> <li>Swipe the app up</li> </ol> </p>'
18196        					+ '<p' + pCSS + '><b>On an Android:</b> <ol style="margin-left: 8%; margin-bottom: 0;"><li>Launch the recent applications menu</li> <li>Swipe the app to the right</li> </ol> </p>'
18197        				+ '</div>';
18198        		
18199        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + '</div>');
18200        	}
18201        	
18202        	_conAHelpOnline.openClientApptRestrictions = function() {
18203        		var jpage = $('#advanced-online-booking');
18204        		var isAdvancedProfile = true, footer = '';
18205        		
18206        		if (jpage.length === 0) {
18207        			isAdvancedProfile = false;
18208        			jpage = $('#aob-client-restrictions');
18209        		}
18210        		
18211        		var chr = UTIL.coalesceInt(jpage.find('#Create_Appt_Hr_nr').val(), jpage.find('#Provider_Create_Appt_Hr_sr').val());
18212        		var uhr = UTIL.coalesceInt(jpage.find('#Update_Appt_Hr_nr').val(), jpage.find('#Provider_Update_Appt_Hr_sr').val());
18213        		
18214        		if (UTIL.coalesceInt(chr, 0) === 0) {
18215        			chr = '5 minutes';
18216        		} else {
18217        			chr = chr + ' hours';
18218        		}
18219        		
18220        		if (UTIL.coalesceInt(uhr, 0) === 0) {
18221        			uhr = '5 minutes';
18222        		} else {
18223        			uhr = uhr + ' hours';
18224        		}
18225        		
18226        		var h1 = 'Client Restrictions';
18227        		var msg0 = _warnMessageOnlineBookingDisabled(jpage);
18228        		var msg = '<p style="margin-top: 8px; margin-bottom: 4px;">' + msg0 + 'You are setup to allow clients to:</p>';
18229        		
18230        		var li1 = '<li>Create appointments that start more than ' + chr + ' from right now</li>';
18231                var li2 = '<li>Update appointments that start more than ' + uhr + ' from right now</li>';
18232        		
18233        		if (GLO.Info.providerPackage != 1) {
18234	        		footer = '<div style="margin-bottom: 12px; color: #888;">';
18235	        		
18236	        		if (isAdvancedProfile) {
18237	        			footer += 'This can be set per staff member by going to <a href="/provider/profile/5?helloback=advanced&tabback=calendar&highlight=client-column">Profile ' + UI.arrow + ' Staff</a></div>';
18238	        		} else {
18239	        			footer += 'If empty, uses the values set at <a href="/provider/manage/advanced#open=tab-online-booking">Profile ' + UI.arrow + ' Advanced</a></div>';
18240	        		}
18241        		}
18242        		
18243        		return _open(h1, '<div>' + msg + '<ul>' + li1 + li2 + '</ul>' + footer + '</div>');
18244        	}
18245        	
18246        	function _warnMessageOnlineBookingDisabled(jpage) {
18247        		if (!jpage.find('#Online_Booking_fl').prop('checked')) {
18248        			return '<b style="color: green;">If you enable online booking</b> ';
18249        		} else {
18250        			return '';
18251        		}
18252        	}
18253        	
18254        	_conAHelpOnline.openSearchResults = function() {
18255        		var jpage = $('#advanced-online-booking');
18256        		var cnt = UTIL.coalesceInt(jpage.find('#Search_Result_Limit_sr').val(), 5);
18257        		var allDay = jpage.find('#Search_Result_Entire_Day_fl').prop('checked');
18258        		
18259        		var msg0 = _warnMessageOnlineBookingDisabled(jpage);
18260        		
18261        		var h1 = 'Client Search Results';
18262        		
18263        		var msg1 = '<p>When clients search for an appointment set how many appointment options do you want to show them in the search results?</p>';
18264        		var msg2 = '<div style="margin: 8px 0; padding: 12px; padding-right: 4px; background-color: pink;">'
18265        		
18266        		if (allDay) {
18267        			msg2 += 'Currently clients are shown all available appointments on the selected day (up to 20 openings) or if less than ' + cnt + ' results are available on the specified day than other days are searched until ' + cnt + ' openings are found</div>';
18268        		} else {
18269        			msg2 += 'Currently clients are shown ' + cnt + ' search results</div>';
18270        		}
18271        		
18272        		var msg3 = '<p>When clients book an appointment with you online they cannot see your schedule; they enter their desired date and time and then search for the appointment opening that best matches</p>';
18273        		
18274        		var jpop = _open(h1, '<div>' + msg0 + msg1 + msg2 + msg3 + '</div>', true);
18275        	}
18276        	
18277        	_conAHelpOnline.openSearchStaffPriority = function() {
18278        		var h1 = 'Staff Priority';
18279        		var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99);
18280        		
18281        		var urlCommissionReport = 'provider/manage/CommissionByStaffService?highlight=commission-column-is-employee&helloback=advanced&tabback=online-booking';
18282        		var aCommissionReport = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlCommissionReport + '\', this, event, true)">Payroll Setup</a>';
18283        		
18284        		var msg1 = '<p>When searching for appointments, you can prioritize commission and hourly staff before independent staff <small>(like booth renters)</small></p>';
18285        		var msg2 = '<p>This only applies if you have both commission and non-commission staff</p>';
18286        		
18287        		if (mt > 9 && mt < 20) {
18288        			var msg3 = '<p style="margin-top: 32px; letter-spacing: 0;"><i>By default</i>, staff not assigned to the <b>House Merchant Account</b> are considered <b>Independent staff</b></p>';
18289        			var msg4 = '<p style="letter-spacing: 0;">You can override this default by checking/un-checking the <b>Employee checkbox</b> next to each staff on the ' + aCommissionReport + '</p>';
18290        		} else {
18291        			var msg3 = '<p>&nbsp;</p>';
18292        			var msg4 = '<p>You can set who is an <b>Employee</b> or <b>Independent</b> staff by <i style="letter-spacing: 0;">checking/un-checking</i> the <b>Employee checkbox</b> next to each staff on the ' + aCommissionReport + '</p>';
18293        		}
18294        		
18295        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + '</div>');
18296        	}
18297        	
18298        	_conAHelpOnline.openSearchFinishTime = function() {
18299        		var h1 = 'Processing / Finish Restrictions';
18300        		var msgA = 'Do you want to allow clients to be able to book appointments when the processing or finish out time will extend beyond the';
18301        		
18302        		if (GLO.Info.providerPackage == 1) {
18303        			msgA += ' your';
18304        		} else {
18305        			msgA += ' staff or business';
18306        		}
18307        		
18308        		msgA = '<div style="margin-bottom: 12px; padding: 4px; padding-left: 20px; border-bottom: 1px solid #444; background-color: pink;">' + msgA + ' normal closing time?</div>';
18309        		
18310        		var msg1 = '<p>This setting only affects services that have a processing or finish out time</p>';
18311            	var aProfileSvc = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/4?helloback=advanced&tabback=online-booking\', this)">Profile ' + UI.arrow + ' Service</a>';
18312            	var msg2 = '<p style="margin-top: 12px; margin-bottom: 2px;">Add processing and/or finish out to any service by going to ' + aProfileSvc + '</p>';
18313            	var liCSS = ' style="text-indent: -4px;"';
18314            	var ol = '<ol style="margin-left: 60px;">'
18315            				+ '<li' + liCSS + '>Click the desired service</li>'
18316            				+ '<li' + liCSS + '>Press the more button</li>'
18317            				+ '<li' + liCSS + '>Enter the desired processing / finish out minutes</li>'
18318            			+ '</ol>';
18319        		
18320        		var jpop = _open(h1, '<div>' + msgA + msg1 + msg2 + ol + '</div>', true);
18321        	}
18322        	
18323        	_conAHelpOnline.openAllowOnlineBooking = function() {
18324        		//var book-online-url
18325        		
18326        		if (GLO.Info.providerPackage == 1) {
18327        			var page = 1, pageText = 'Profile ' + UI.arrow + ' Me', pageStep = ' and click on the "Client Setup" button';
18328        		} else {
18329        			var page = 5, pageText = 'Profile ' + UI.arrow + ' Staff', pageStep = ' and click on the <b>Clients</b> column for each staff member';
18330        		}
18331        		
18332        		var h1 = 'Enable Online Booking';
18333        		var aProfile = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/' + page + '?helloback=advanced&tabback=online-booking\', this)">' + pageText + '</a>';
18334        		var msg1 = '<p>Check the box to Allow clients to book online</p>';
18335        		
18336        		var aHow = '<a onclick="GLO.Provider.Advanced.Help.Online.openAppointmentSearch()">How Online Booking Works</a>';
18337    			var divHow = '<div style="margin-bottom: 16px; text-align: center; letter-spacing: 1px; font-weight: bold;">' + aHow + '</div>';
18338        		
18339        		var list1 = '<ol> <h4>Customize Online Booking</h4>';
18340        		var li1 = '<li>Go to ' + aProfile + pageStep + ' to restrict when and which clients can book online</li>';
18341        		
18342        		var abanner = '<a onclick="GLO.Uri.gotoUri(\'help?helloback=advanced&tabback=online-booking#tab=profile&id=web-template-add-banner\', this)">Book Appointment banner</a>';
18343        		var abutton = '<a onclick="GLO.Uri.gotoUri(\'help?helloback=advanced&tabback=online-booking#tab=profile&id=web-template-add-button\', this)">Book Appointment button</a>';
18344        		var li2 = '<li>Add a ' + abanner + ' or a ' + abutton + ' to your website</li>';
18345        		
18346        		var aChangeLink = '<a onclick="GLO.Uri.gotoUri(\'wizard/website?helloback=advanced&tabback=online-booking#step=\', this)">Change where</a>';
18347        		var li3 = '<li>' + aChangeLink + ' your customers go to book appointments with you</li>';
18348        		
18349        		var aConfigureCportal = '<a onclick="GLO.Uri.gotoUri(\'provider/WebTemplate/ConfigureLogin?back=%2fprovider%2fmanage%2fadvanced&helloback=advanced&tabback=online-booking\', this)">
18349what your clients see</a>';
18350        		var li4 = '<li>Customize ' + aConfigureCportal + ' when they create appointments with you</li>';
18351        		
18352        		//var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-portal-create-appt.png" style="max-width: 600px; min-height: 20px; width: 100%;"/> </div>';
18353        		var msg = divHow + msg1 + list1 + li1 + li2 + li3 + li4 + '</ol>'
18354        		
18355        		return _open(h1, '<div>' + msg + '</div>').attr('id', 'pop-help-allow-online-booking');
18356        	}
18357        	
18358        	_conAHelpOnline.openAllowRequestAppt = function() {
18359        		var h1 = 'Request Appointment Page';
18360        		var msg2 = '', msg1 = '<p>' + GLO.Info.getScheduleAnyoneHtm() + ' automatically creates this request appointment page allowing clients to request appointments</p>'
18361        		
18362        		var msg1b = '<p>When a client requests an appointment using this page ' + GLO.Info.getScheduleAnyoneHtm() + ':'
18363        					+ '<ul style="">'
18364        						+ '<li>Adds the appoinment request to your <a onclick="GLO.Uri.gotoUri(\'/provider/apptportal?tab=wait\', this)">Waiting List</a></li>'
18365                            	+ '<li>Send you an email that allows you to accept the appointment request</li>'
18366                            + '</ul></p>';
18367                    
18368        		if (GLO.Info.providerPackage != 1) {
18369        			var aBizEmail = '<a onclick="GLO.Uri.gotoUri(\'/provider/profile/2?helloback=advanced&tabback=online-booking\', this)">Business Email</a>';
18370        			msg2 = '<p>If a ' + aBizEmail + ' is set then the appointment request will be sent to that email, otherwise the email is sent to all the managers and admins in ' + GLO.Info.getScheduleAnyoneHtm() + '</p>';
18371        		}
18372        		
18373        		var aConfigureCportal = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/WebTemplate/ConfigureLogin?back=%2fprovider%2fmanage%2fadvanced&helloback=advanced&tabback=online-booking\', this, event, true)">Online Booking Configuration</a>';
18374        		var aRequestApptSetting = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/WebTemplate/RequestApptSetting?back=%2fprovider%2fmanage%2fadvanced&helloback=advanced&tabback=online-booking\', this, event, true)">Request Appointment Settings</a>';
18375        		var msg3 = '<p>You can customize this page by going to the ' + aConfigureCportal + ' and ' + aRequestApptSetting + '</p>';
18376        		
18377        		return _open(h1, '<div>' + msg1 + msg1b + msg2 + msg3 + '</div>');
18378        	}
18379        	
18380        	_conAHelpOnline.openAllowIndependentStatusChange = function() {
18381        		var h1 = 'Independent Staff Permissions: Client Setup';
18382        		var msg1 = '<p>Do you want to allow your independent staff (staff with <a href="/hello/StaffRole">the Independent Role</a>) to set their:</p>';
18383        		var ul = '<ul>'
18384        					+ '<li>Online booking status</li>'
18385        					+ '<li>When/If email and text reminders are sent</li>'
18386        					+ '<li>If client confirmation emails are sent when appointments are created and/or updated</li>'
18387                
18388                var imgCSS = 'max-width: 600px; min-height: 400px; width: 100%; margin-bottom: 4px; border-radius: 20px;';
18389        		var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/Independent-Staff-Permissions-Client-Setup.jpg" style="' + imgCSS + '"/> </div>';
18390        		
18391        		return _open(h1, '<div>' + msg1 + ul + img + '</div>');
18392        	}
18393
18394        	_conAHelpOnline.openProductVariantGuide = function() {
18395        		SA.Help.openReportHelp('#pop-how-to-guide-product-variations', 0, 'info/HelpGuide?name=ProductVariations');
18396				// $('.pop-modal').css('left','50px')
18397
18398        	}			
18399        	
18400        	return _conAHelpOnline;
18401    	})();
18402        
18403        
18404        _conAdvancedHelp.Client = (function() {
18405        	function _conAHelpClient() { }
18406        	
18407        	_conAHelpClient.openAddressConfig = function() {
18408        		//var msg1 = '<p>Based on your type of business the client address setting has been set automatically, but you can change it as desired</p>';
18409        		var addressFields = '<b>address fields <b class="narrow-text">(street, city, state, postal code, country)</b></b>';
18410        		var intro = '<p>When clients and staff create a new client profile do you want to display ' + addressFields + ' in the new client form?</p>'
18411        				+ '<p>Should address be required when creating a new client profile?</p>'
18412        				+ '<p>Should address be required when <a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/WebTemplate/RequestApptSetting\', this, event, true)">clients request appointment</a>?</p>'
18413        				var amerge = '';
18414        				+ '<p>Should staff see directions to client address?</p>';
18415        		
18416        		var hDisplay = '<h2>When Display + Require Client Address</h2>';
18417        		var thead = '<thead> <tr> <th></th> <th>Display on<br/>New Client Form</th> <th>Require on<br/>New Client Form</th> <th>Display on<br/>Client Profile</th> <th>Staff Can<br/>See Directions</th> </tr> </thead>';
18418        		var tblDisplay = '<table id="client-address-config-table">' + thead + '<tbody>'
18419        					+ '<tr> <th>Display Address On Profile Only</td> <td class="display-new-client"></td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions"></td> </tr>'
18420        					+ '<tr> <th>Display Directions to Staff</td> <td class="display-new-client"></td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions">x</td> </tr>'
18421        					+ '<tr> <th>Display On New Client Form, No Directions</td> <td class="display-new-client">x</td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions"></td> </tr>'
18422        					+ '<tr> <th>Display on New Client Form</td> <td class="display-new-client">x</td> <td class="require-new-client"></td> <td class="display-profile">x</td> <td class="see-directions">x</td> </tr>'
18423        					+ '<tr> <th>Require On New Client Form</td> <td class="display-new-client">x</td> <td class="require-new-client">x</td> <td class="display-profile">x</td> <td class="see-directions">x</td> </tr>'
18424        				+ '</tbody></table>';
18425        		
18426        		var hDirections = '<h2>See Directions</h2>';
18427        		var cssGetDirections = 'padding: 0 8px; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; background-color: #139ad2; color: white;';
18428        		var msgDirections = '<p style="margin-bottom: 0;">If enabled, you can easily see directions to the client\s address by:</p>';
18429        		var listDirection = '<ol style="margin-left: 48px;">'
18430        					+ '<li>Open client\'s appointment or client\'s profile</li>'
18431        					+ '<li>Press triangle to right of the client name</li>'
18432        					+ '<li>Select <b style="' + cssGetDirections + '">Get Directions</b></li>'
18433        				+ '</ol>';
18434        		var imgDirections = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/edit-appointment-get-directions.png" style="max-width: 320px; min-height: 240px; width: 100%;"/> </div>';
18435        		
18436        		var header = 'Client Address Display Information';
18437        		var htm = '<div>' + intro + hDisplay + tblDisplay + hDirections + msgDirections + listDirection + imgDirections + '</div>';
18438        		return _open(header, htm).attr('id', 'pop-client-address-config');
18439        	}
18440        	
18441        	_conAHelpClient.openHasBiz = function() {
18442        		var h1 = 'Enable Business Clients';
18443        		
18444        		var msg1 = '<p>Enabling business clients allows you to go to a client profile and select if they are male, female, or a business</p>';
18445        		var msg2 = '<p>You can go to a business client profile and set if that business is taxable or not</p>';
18446        		var msg3 = '<p>Business clients by default are not taxable - so tickets (appointments and product sales) for business clients will not include taxes</p>';
18447        		
18448        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + '</div>');
18449        	}
18450        	
18451        	_conAHelpClient.openEasyLogin = function() {
18452        		var h1 = 'Easy Login';
18453        		var pstart = '<p style="line-height: 1.4;">';
18454        		var bEasyLogin = '<b class="narrow-text">Easy Login</b>';
18455        		var htmArrow = ' <b style="display: inline-block; padding-left: 6px; padding-right: 6px;">&#10140;</b> ';
18456        		
18457        		var msg1 = pstart + 'Simplifies clients logging into ' + GLO.Info.getScheduleAnyoneHtm(
18457) + ' to book appointments with you';
18458        		var msg2 = pstart + '<span style="padding-right: 4px; color: #4F81BD;">When ' + bEasyLogin + ' Enabled</span>' 
18459        				+ 'returning clients can simply use your new client form to automatically log into their existing profile'
18460        				+ htmArrow + 'if their name and phone matches, unless the client has a</p>';
18461				var list = '<ul class="narrow-list"> <li>gift card</li> <li>card-on-file</li> <li>membership</li> </ul>';
18462				
18463        		return _open(h1, '<div>' + msg1 + msg2 + list + '</div>');
18464        	}
18465        	_conAHelpClient.openNewClientForm = function() {
18466        		var h1 = 'New Client Form';
18467        		
18468        		var pstart = '<p style="line-height: 1.4;">';
18469        		var pstartSmall = '<p style="margin-left: 40px; margin-top: 0; margin-bottom: 32px; padding-top: 0; line-height: 1.4; letter-spacing: 0; font-size: 90%;">';
18470        		var b = '<b class="narrow-text">';
18471        		var bsimple = '<b class="narrow-text" style="font-size: larger; color: blue;">Simple Client Form</b>';
18472        		var bstandard = '<b class="narrow-text" style="font-size: larger; color: blue;">Standard Form</b>';
18473        		
18474        		var fnAutoLink = 'GLO.Uri.gotoUri2(\'provider/manage/advanced?open=tab-help&popup=how-to-guide-online-booking&step=15\')';
18475    			var aAutoLink = '<a class="narrow-text" onclick="' + fnAutoLink + '">Automatic Login Link</a>';
18476        		
18477        		var msg1 = pstart+ 'The ' + bsimple + ' is the fastest way to create new clients for both your staff and online</p>'
18478        		var msg1b = pstartSmall+ 'When clients create an account'
18479        				+ ' <span class="narrow-text">(if you allow online booking)</span>'
18480        				+ ' the username/password is automatically created <span class="narrow-text">(username is usually the email)</span>'
18481        				+ ' - but with ' + aAutoLink + ' clients never need to know their <span class="narrow-text">Username</span> or <span class="narrow-text">Password</span><p>';
18482        		
18483        		var msg2 = pstart+ 'The ' + bstandard + ' contains the extra fields: ' + b + 'Username</b> + ' + b + 'Password</b></p>';
18484        		
18485        		return _open(h1, '<div id="pop-help-new-client-form-type" style="letter-spacing: 0;">' + msg1 + msg1b + msg2 + '</div>');
18486        	}
18487        	
18488        	_conAHelpClient.openReferByClient = function() {
18489        		var h1 = 'Refer by Client';
18490        		var msg1 = '<p>When enabled adds <b>Referred by Client</b> button when creating new clients and checking out new clients</p>';
18491        		var msg2 = '<p>Adds button to lookup referring client using the referring client\'s phone number</p>';
18492        		var msg3 = '<p></p>';
18493        		
18494        		var msg4 = '<p>Can automatically give new client a gift voucher + send referring client a gift voucher</p>';
18495        		var msg5 = '<p></p>';
18496        		//var msg6 = '<p></p>';
18497        		
18498        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>');
18499        	}
18500        	
18501        	_conAHelpClient.openPhoneSync = function() {
18502        		var h1 = 'Sync Client List From Phone';
18503        		var msg2 = '<p>You can disable that feature here: so no sync will occur</p>';
18504        		var msg4 = '<div style="margin-top: 12px; margin-bottom: 20px;"> <span class="btnDeleteSyncClients btnAdd" onclick="GLO.Provider.Advanced.deleteSyncedClients()"> <a>Remove Clients Synced From Phone</a> </span> </div>';
18505        		
18506        		if ($.cookies.get('pid') == 70 && (GLO.Info.isIPhone || GLO.Info.isIPad) && GLO.Info.isIosApp) {
18507        			msg4 += '<div style="margin-top: 2px; margin-bottom: 20px;"> <span class="btnSyncClientList btnAdd" onclick="SA.App.GetContacts(true)"> <a>Sync Client List from this Device</a> </span> </div>';
18508        		}
18509        		
18510        		if (GLO.Info.providerPackage == 1) {
18511        			var msg1 = '<p>When you login to the ' + GLO.Info.getScheduleAnyoneHtm() + ' App on your iPhone or iPad it asks if you want to sync the client list from your phone/iPad to ' + GLO.Info.getScheduleAnyoneHtm() + '</p>';
18512        			var msg3 = '<p style="margin-top: 20px;">Do you want to delete all clients synced from your phone, that do not have an appointment or product purchase?</p>';
18513        		} else {
18514        			var msg1 = '<p>When you or your staff login to the ' + GLO.Info.getScheduleAnyoneHtm(
18514) + ' App on your iPhone or iPad it asks if you want to sync the client list from your phone/ipad to ' + GLO.Info.getScheduleAnyoneHtm() + '</p>';
18515        			var msg3 = '<p style="margin-top: 40px;">Do you want to delete all clients synced from staff phones, that do not have an appointment or product purchase?</p>';
18516        		}
18517        		
18518        		return _open(h1, '<div>' + msg1 + msg2 + msg3 + msg4 + '</div>');
18519        	}
18520        	
18521        	_conAHelpClient.openMergeHelp = function() {
18522        		var h1 = 'Merge Clients';
18523        		var hStreamline = '<h3>' + GLO.Info.getScheduleAnyoneHtm() + ' Helps Streamline Your Client List</h3>';
18524        		
18525        		if (GLO.Info.providerPackage == 1) {
18526        			var labelYou = 'You';
18527        			var msg4b = '';
18528        		} else {
18529        			var labelYou = 'Staff';
18530        			var msg4b = '<p>Staff with the role Receptionist, Manager, or Admin can merge client profiles</p>';
18531        		}
18532        		
18533        		var btnViewDuplicates = '<span class="btnAdd"> <a onclick="GLO.Provider.Advanced.Help.Client.openProcessMerge()">Lookup Duplicate Clients</a></span>';
18534        		var btnMerge = '<span class="btnAdd"> <a onclick="GLO.Provider.Advanced.Help.Client.openProcessMerge(true)">Merge Duplicate Clients</a></span>';
18535        		
18536        		var msg0 = '<p>If attempting to create a duplicate client account, a list of similar clients are displayed to see if it is better to use an existing client account or create a new one</p>';
18537        		var msg1 = '<p>Every weekend your duplicate clients are automatically merged via a <b>Normal Merge</b>; you can also ' + btnViewDuplicates + ' and ' + btnMerge + '</p>';
18538        		var msg2 = '<p>A client is considered duplicate if another client profile has the same name and phone, email, or street address (or is empty)</p>';
18539        		var msg3 = '<p>When two client accounts are merged their profile, tickets (appointments and product purchases), waiting list requests, notes, loyalty points, and gift cards are merged into one client account</p>';
18540        		
18541        		var hSpecific = '<h3>Merge Specific Clients</h3>';
18542        		var msg4 = '<p>' + labelYou + ' can go to a client\'s profile and at the bottom of the profile press the merge button then select another client account to merge with</p>';
18543        		
18544        		return _open(h1, '<div>' + hStreamline + msg0 + msg1 + msg2 + msg3 + hSpecific + msg4 + msg4b + '</div>');
18545        	}
18546        	
18547        	_conAHelpClient.openProcessMerge = function(isMerge) {
18548        		if (GLO.Info.providerPackage != 1 && new Date().addDays(-180) > new Date(GLO.Data.provider.createDate)) {
18549        			var warnHeader = '<div style="margin-bottom: 24px; color: rgb(240,0,0);">Merging Client List only allowed before 10 am EST or after 7pm PST</div>';
18550        		} else {
18551        			var warnHeader = '';
18552        		}
18553        		
18554        		var rdoNormal = '<input type="radio" name="mergeType" id="normalMerge" value="normal" checked="checked"/>';
18555        		var labelNormal = '<label for="normalMerge"><b>Normal Merge</b> <small>Merge Clients with the same name where the phone, email, or street address match (must be empty or if exist must match)</small></label>';
18556        		
18557        		var rdoExtreme = '<input type="radio" name="mergeType" id="extremeMerge" value="extreme"/>';
18558        		var labelExtreme = '<label for="extremeMerge"><b>Extreme Merge</b> <small>Merge any client with the same phone number (warning this will merge clients with different names who might share the same phone number)</small></label>';
18559        		
18560        		var divStart = '<div class="rdo-advanced">';
18561        		var divMergeType = '<div id="process-merge-type"><h3>Merge Type</h3>' + divStart + rdoNormal + labelNormal + '</div>' + divStart + rdoExtreme + labelExtreme + '</div></div>';
18562        		
18563        		var rdoMergeView = '<input type="radio" name="MergeOrView" id="isMergeView" value="mergeview"/>';
18564        		var labelMergeView = '<label>' + rdoMergeView + 'Lookup Duplicate Clients (Do Not Merge)</label>';
18565        		
18566        		var rdoMerge = '<input type="radio" name="MergeOrView" id="isMerge" value="ismerge"/>';
18567        		var labelMerge = '<label>' + rdoMerge + 'Merge Duplicate Clients</label>';
18568        		
18569        		var divMergeOrView = '<div id="process-merge-or-view"><h3>Lookup or Merge</h3>' + divStart + labelMergeView + '</div>' + divStart + labelMerge + '</div></div>';
18570        		var btnProcessInner = '<a onclick="GLO.Provider.Advanced.Help.Client.processMerge()" style="display: inline-block;">Process Now</a>';
18571        		var btnProcess = '<span id="btnProcessMerge" class="btnSave" style="margin: 0; margin-right: 120px;">' + btnProcessInner + '</span>';
18572        		
18573        		var htm = '<div id="pop-merge-duplicates">' + warnHeader + divMergeType + divMergeOrView + '</div>';
18574        		var jpop = GLO.Popup.Custom.openSimple(htm, 'Merge Client List');
18575        		var jbtns = jpop.find('.pop-buttons');
18576        		
18577        		jbtns.find('.btnSave').remove();
18578        		jbtns.css({ "margin-top": "32px" }).prepend(btnProcess);
18579        		
18580        		if (isMerge) {
18581        			jpop.find('#isMerge').prop('checked', true);
18582        		} else {
18583        			jpop.find('#isMergeView').prop('checked', true);
18584        		}
18585        	}
18586        	
18587        	_conAHelpClient.processMerge = function() {
18588        		if (!_conAdvanced.canSaveChanges()) { _conAdvanced.initReadOnlyCheck(); return; }
18589        		
18590        		var jpop = $('#pop-merge-duplicates').closest('.glopop');
18591        		var isMerge = jpop.find('#isMerge').is(':checked');
18592        		var isExtreme = jpop.find('#extremeMerge').is(':checked');
18593        		
18594        		if (isMerge) {
18595        			var fnYes = function() {
18596        				GLO.Provider.Advanced.Help.Client.processMergeConfirmed(isMerge, isExtreme);
18597        			}
18598        			var fnNo = function() {
18599        				GLO.Popup.close($('#pop-confirm-merge-clients').closest('.glopop'));
18600        				
18601        				jpop.find('#isMergeView').prop('checked', true);
18602        				jpop.find('#btnProcessMerge > a').click();
18603        			}
18604        			
18605        			var htm = '<p>Merge Cannot be Un-Done</p><p>Would you first like to see your list of duplicates before merging?</p>';
18606        			var ojpop = GLO.Popup.Confirm.open('<div id="pop-confirm-merge-clients">' + htm + '</div>', 'Confirm Merge', fnYes, fnNo);
18607        			var jbtns = ojpop.getPopup().find('.pop-buttons').css({ "margin-bottom": "8px" });
18608        			
18609        			var btnNo = jbtns.find('.btnNo').addClass('btnAdd').removeClass('btnNo').css({ "float": "left", "display": "inline-block", "margin-top": "-6px" })
18610        			var btnYes = jbtns.find('.btnYes').addClass('btnSave').css({ "width": "240px" });
18611        			
18612        			btnNo.find('>a').css({ "padding": "8px 20px", "font-size": "larger" }).text('Lookup Duplicates');
18613        			btnYes.find(' > a').text('Merge Duplicate Clients');
18614        			
18615        			if (innerWidth < 600) {
18616        				btnNo.css({ "float": "none", "display": "block", "margin-bottom": "24px" });
18617        				btnYes.css({ "float": "none" });
18618        			} else {
18619        				jbtns.css({ "width": "600px" });
18620        			}
18621        		} else {
18622        			_conAHelpClient.processMergeConfirmed(isMerge, isExtreme);
18623        		}
18624        	}
18625        	_conAHelpClient.processMergeConfirmed = function(isMerge, isExtreme) {
18626        		if (!_conAdvanced.canSaveChanges()) { _conAdvanced.initReadOnlyCheck(); return; }
18627        		
18628        		var jpopMerge = $('#pop-merge-duplicates').closest('.glopop');
18629        		var url = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedMergeClients?ismerge=' + isMerge + '&isExtreme=' + isExtreme;
18630		    	
18631		    	GLO.Popup.closeIfExist($('#pop-confirm-merge-clients').closest('.glopop'));
18632		    	GLO.UI.Form.beginProcessing(jpopMerge.find('#btnProcessMerge'));
18633        		
18634        		_openProcessingMerge(isMerge, isExtreme);
18635        		
18636        		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: {} })
18637		            .success(function(data, textStatus, jqXHR) {
18638		                var jd = $(data);
18639		                var htm = jd.outerHTML();
18640		                
18641		                GLO.Popup.closeIfExist($('#pop-processing-merge').closest('.glopop'));
18642		                
18643		                if (UTIL.parseBool(jd.attr('warning_fl'))) {
18644		                	GLO.UI.Form.resetProcessing();
18645		                	var jpopWarn = GLO.Popup.Warning.open(htm, 'Cannot Merge Now').getPopup();
18646		                } else {
18647		                	GLO.Popup.closeIfExist(jpopMerge);
18648		                	
18649		                	if (isMerge) {
18650		                		var h1 = 'Duplicate Clients Merged';
18651		                	} else {
18652		                		var h1 = 'Duplicate Clients Found';
18653		                	}
18654		                	
18655		                	//var htm = '<div><div class="friendly-msg3">' + htm + '</div></div>';
18656		                	var jpopResults = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-merge-results');
18657		                	GLO.Popup.Custom.singleButton(jpopResults, 'Close');
18658		                }
18659		            })
18660		            .error(function(jqXHR, textStatus, errorThrown) {
18661		                var htm = '<div><p>Unable to process merge at this time</p><p>Please try again later</p></div>';
18662		                GLO.Popup.Error.open(htm, 'Merge Client List Duplicates');
18663		                GLO.UI.Form.resetProcessing();
18664		            });
18665        	}
18666        	function _openProcessingMerge(isMerge, isExtreme) {
18667        		if (isMerge) {
18668        			var label = 'Merge';
18669        		} else {
18670        			var label = 'Duplicate lookup';
18671        		}
18672        		
18673        		var msg1 = label + ' processing, please be patient it typically takes less than 60 seconds to perform, but it might take up to 5 minutes for very large client lists';
18674        		var msg2 = 'Do not attempt another merge or duplicate lookup request until this finishes processing'
18675        		
18676        		var htm = '<div id="pop-processing-merge"><p>' + msg1 + '</p><p>' + msg2 + '</p></div>';
18677        		GLO.Popup.Processing.open(htm, 'Processing ' + label);
18678        	}
18679        	
18680        	function _freeTextCount() {
18681        		if (GLO.Info.providerPackage == 1) {
18682        			return 50;
18683        		} else {
18684        			return 500;
18685        		}
18686        	}
18687        	
18688        	_conAHelpClient.openTextReminder2 = function() {
18689        		var li1 = '<li><b class="narrow-text">24 hours</b> before appointment</li>';
18690        		var li2 = '<li><b class="narrow-text">2 hours</b> before appointment</li>';
18691        		
18692        		var msg1 = '<p>Can send clients 2 text reminders for each appointment</p>';
18693        		var msg2 = '<p style="margin-bottom: 0;">
18693A common scenario is to send reminders</p>';
18694        		var ul2 = '<ul>' + li1 + li2 + '</ul>';
18695        		
18696        		var payAsUse = '<b class="narrow-text">Pay-as-Use</b> plan';
18697        		var aMsgPlan = '<a onclick=\'GLO.Uri.gotoUri2("provider/manage/message?helloback=advanced&tabback=appointment&highlight=advanced-feature-staff-alert-text")\'>Message Plan</a>';
18698        		
18699        		var msg3 = '<p>The first ' + _freeTextCount() + ' text reminders are free every month</p>';
18700        		var msg4 = '<p>Sign up for a ' + aMsgPlan + ' to send more text messages</p>';
18701        		var msg5 = '<p>With the ' + payAsUse + ' text reminders cost just 1 cent per message</p>';
18702        		
18703        		var msg6 = '<p style="margin-top: 24px; letter-spacing: 0; font-family: Arial;">The first text reminder and the second text reminder must be sent at least 8 hours apart</p>';
18704        		
18705        		return _open('Text Reminder #2', '<div id="pop-help-text-reminder2">' + msg1 + msg2 + ul2 + msg3 + msg4 + msg5 + msg6 + '</div>');
18706        	}
18707        	
18708        	_conAHelpClient.openSearchDeletedClient = function() {
18709				var label = '<label for="Deleted_Client_vc">Enter Deleted Client\'s Name, Phone, Email, or Street Address</label>';
18710				var input = '<input id="Deleted_Client_vc" placeholder="Deleted Client Search"/>';
18711				
18712				var htm = '<div id="pop-search-deleted-clients">' + label + input + '</div>';
18713        		var jpop = GLO.Popup.Custom.openSimple(htm, 'Deleted Client Search');
18714        		GLO.Popup.Custom.singleButton(jpop, 'Close');
18715        		
18716        		var jclient = jpop.find('#Deleted_Client_vc');
18717        		var urlSearch = GLO.Link.Object.Provider.Ajax + 'ClientSearchDeleted';
18718        		
18719        		var fnSelect = function(event, ui) {
18720        			var htm = '<p>Loading ' + ui.item.label + '...</p>';
18721        			var htmCreate = '<p>' + UTIL.coalesceString(ui.item.client_create_vc, 'Client created') + ' on ' + ui.item.create_dt + '</p>';
18722        			//last_login_dt
18723        			
18724        			if (!UTIL.isEmpty(ui.item.merge_client_id)) {
18725        				var mergeUrl = GLO.Link.WebsiteDomain + 'provider/clientProfile?cid=' + ui.item.merge_client_id;
18726        				var amerge = 'GLO.Uri.gotoUriWithSpinner(\'' + mergeUrl + '\', this, event, true)';
18727        				htm += '<p>Client merged into <a onclick="' + amerge + '">' + ui.item.merge_client_vc + '</a></p>';
18728        			}
18729        			
18730        			GLO.Popup.Processing.open('<div id="pop-processing-delete-client">' + htmCreate + htm + '</div>', 'Loading Deleted Client Profile');
18731			    	
18732			    	setTimeout(function() {
18733			    		document.location = GLO.Link.WebsiteDomain + 'provider/clientProfile?cid=' + ui.item.id;
18734			    	}, 7500);
18735        		}
18736        		
18737        		UI.initAutoComplete2(jclient, urlSearch, fnSelect, 5);
18738			}
18739        	
18740        	return _conAHelpClient;
18741    	})();
18742    	
18743    	
18744        _conAdvancedHelp.Location = (function() {
18745        	function _conAHelpLocation() { }
18746        	
18747        	_conAHelpLocation.openProvider = function() {
18748        		var h1 = 'Manage Locations';
18749        		var msg1 = '<p>Each business location has its own color so you can easily identify what location you are managing</p>';
18750        		var msg2 = '<p>On a computer, iPad, or tablet change the location you are managing by going to the staff filter (in the upper right corner of the screen)</p>';
18751        		var img = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/staff-filter-change-location.png" style="max-width: 280px; min-height: 120px; width: 60%;"/> </div>';
18752        		
18753        		var msg3 = '<p>On your phone open the menu and your current location is listed at the top of the menu; just press the location to change it</p>';
18754        		
18755        		return _open(h1, '<div>' + msg1 + msg2 + img + msg3 + '</div>');
18756        	}
18757        	
18758        	_conAHelpLocation.openClient = function() {
18759        		var h1 = 'Easy Client Management';
18760        		var imgOtherLocation = '<img style="float: none; display: inline-block; margin: 0;" src="' + GLO.Data.cdnDirectory + 'image/icon/location-icon-20wh.png"/>';
18761        		var div1 = '<div style="padding: 6px; padding-left: 24px; background-color: pink;">';
18762        		var msg1 = div1 + 'Client profiles are seamlessly shared accross all your bussiness locations</div>';
18763        		
18764        		var msg2 = '<p>The client profiles display appointments and product purchases at all locations, visits to other locations are displayed with the other location icon ' + imgOtherLocation + ' and the row has that location\'s background color</p>';
18765        		var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/client-profile-multi-location.png" style="max-width: 600px; min-height: 120px; width: 100%;"/> </div>';
18766        		
18767        		var msg3 = '<p>
18767When you search for clients, ' + GLO.Info.getScheduleAnyoneHtm() + ' first looks at clients in the location you are currently managing; if it does not find any clients that match your search it will look in your other locations, and the clients from your other locations will have that location\'s background color</p>';
18768        		var img2 = '<div style="display: inline-block;"> <img src="' + GLO.Data.cdnDirectory + 'image/help/link-client-search2.png" style="max-width: 180px; min-height: 80px; width: 100%;"/> </div>';
18769        		var img3 = '<div style="display: inline-block;"> <img src="' + GLO.Data.cdnDirectory + 'image/help/link-client-create-appointment.png" style="max-width: 360px; min-height: 200px; min-width: 240px; width: 60%;"/> </div>';
18770        		
18771        		var msg4 = '<p>No need to export and import client lists across multiple locations ' + GLO.Info.getScheduleAnyoneHtm() + ' takes care of all of that for you';
18772        		
18773        		return _open(h1, '<div>' + msg1 + msg2 + img1 + msg3 + img2 + img3 + msg4 + '</div>', true);
18774        	}
18775        	
18776        	_conAHelpLocation.openStaff = function() {
18777        		var h1 = 'Staff At Multiple Locations';
18778        		var msg1 = '<div style="padding: 6px; padding-left: 24px; background-color: pink;">The same staff member can work at more than one location and see appointments at all locations on one calendar</div>';
18779        		var msg2 = '<p>You regular hours at other location(s) are displayed in that location\'s color</p>';
18780        		var img1 = '<div> <img src="' + GLO.Data.cdnDirectory + 'image/help/staff-calendar-multi-location.png" style="max-width: 600px; min-height: 280px; width: 100%;"/> </div>';
18781        		
18782        		var aAddStaff = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=location#open=add-staff\', this)">Add Staff From Another Location</a>';
18783        		var aLinkStaff = '<a onclick="GLO.Uri.gotoUri(\'provider/profile/5?helloback=advanced&tabback=location#open=add-staff\', this)">Link Staff At Another Location</a>';
18784        		var msg3 = '<p>You can ' + aAddStaff + ' and ' + aLinkStaff + '</p>';
18785        		
18786        		return _open(h1, '<div>' + msg1 + msg2 + img1 + msg3 + '</div>', true);
18787        	}
18788        	
18789        	return _conAHelpLocation;
18790    	})();
18791        
18792        return _conAdvancedHelp;
18793    })();
18794    
18795    return _conAdvanced;
18796})();
18797
18798
18799GLO.Provider.Discount = (function() {
18800    function _conManageD() { }
18801    var _isAddOnFee = false, _word = 'Discount', _wordLong = 'Discount';
18802    
18803    _conManageD.init = function(isFee) {
18804        GLO.Info.init();
18805        
18806        if (isFee) {
18807        	_word = 'Fee';
18808        	_wordLong = 'Add-On Fee';
18809        	_isAddOnFee = true;
18810        }
18811        
18812        var jrpt = $('.report-container');
18813        var jcontainer = jrpt.find('#DiscountList');
18814        SA.Upgrade.initReadOnly(_word + 's', jcontainer);
18815        GLO.Report.portalName = _word;
18816        
18817        var tagOptionList = $(GLO.ClientProfile.Tag.getTagTypeDropDown()).html();
18818        $('#discount-rules').find('.tag-list').html(tagOptionList);
18819        
18820        GLO.Report.enableFullPageCheck();
18821		_conManageD.initData(jrpt);
18822        
18823        _initShortcut();
18824        _initUri(jrpt);
18825        
18826        GLO.Report.hideEmptyColumn(jrpt, 'discount-column-commission-split');
18827        GLO.Report.setupFastClick();
18828    }
18829    
18830    function _initUri(jrpt) {
18831    	var open = UTIL.cleanString(GLO.Uri.query('open')).toLowerCase();
18832    	
18833    	if (!UTIL.isEmpty(open)) {
18834			if (open === 'pay-method' || open === 'paymethod' || open === 'paymentmethod') {
18835				GLO.Provider.Discount.openHelpPayMethod();
18836			} else if (open === 'clienttag' || open === 'client-tag') {
18837				GLO.Provider.TagManager.openReportHelp();
18838			} else if (open === 'day-time' || open === 'daytime') {
18839				GLO.Provider.Discount.openHelpDayTime();
18840			} else if (open === 'client-birthday' || open === 'birthday') {
18841				GLO.Provider.Discount.openHelpBirthday();
18842			} else if (open === 'loyalty-points' || open === 'points' || open === 'loyalty') {
18843				GLO.Uri.gotoUriWithSpinner('help#tab=pos&id=faq-pos-setup-loyalty');
18844			} else if (open === 'promo-code' || open === 'promo') {
18845				GLO.Provider.Discount.openPromoHelp();
18846			} else if (open === 'rule' || open === 'rules' || open === 'more-info') {
18847				GLO.Provider.Discount.openHelpRules();
18848			
18849			} else if (open === 'commission-split') {
18850				GLO.Provider.Discount.openCommissionSplit(_isAddOnFee, true);
18851			} else if (open === 'commission-split-custom') {
18852				GLO.Provider.Discount.openCommissionSplit(_isAddOnFee, true);
18853				GLO.Provider.Discount.helpCommissionSplitCustom();
18854			} else if (open === 'commission-split-by-type') {
18855				GLO.Provider.Discount.helpCommissionSplitByType();
18856			
18857			} else if (open === 'add') {
18858				var ruleType = GLO.Uri.query('ruletype');
18859				var ruleVal = GLO.Uri.query('ruleval');
18860				
18861				GLO.Provider.Discount.openEdit(null, null, null, ruleType, ruleVal);
18862			} else if (open === 'discount' || open === 'fee') {
18863				var id = GLO.Uri.query('id');
18864				jrpt.find('#DiscountList').find('tr[provider_discount_id="' + id + '"]').find('td.discount-column-name a').click();
18865			}
18866		}
18867    }
18868	
18869	_conManageD.initData = function(jrpt) {
18870		UI.initTableSorter($('.tablesorter'));
18871		GLO.Report.CellSummary.initReport(jrpt, false, true);
18872		_initTagName(jrpt);
18873	}
18874	
18875	function _initTagName(jrpt) {
18876		var jtags = jrpt.find('tbody').find('.rule-tag');
18877		_initTagNameForTags(jtags)
18878	}
18879		
18880	function _initTagNameForTags(jtags) {
18881		for (var i=0; i < jtags.length; i++) {
18882			var jtag = jtags.eq(i);
18883			var tagTypeId = jtag.attr('discount_type_id');
18884			var tag = GLO.ClientProfile.Tag.getTagType(tagTypeId);
18885			var tagName = UTIL.maxString(tag.name, 24);
18886			jtag.find('b').text(tagName);
18887		}
18888	}
18889	
18890	function _initShortcut() {
18891    	$(document).keydown(function(event) {
18892           if (event.altKey) {
18893                if (event.which === 82) {                                //R: refresh report
18894                    GLO.Provider.Discount.search();
18895                }
18896            }
18897        });
18898        $(window).bind('keypress', function(e) {
18899            if (e.altKey) {
18900                if (e.which === 82) {               				//R: refresh report
18901                    e.preventDefault();
18902                }
18903            }
18904        });
18905    }
18906    
18907    _conManageD.openEdit = function(thisLink, highlightRuleNumber, isFee, addRuleType, addRuleValue) {
18908        if (SA.Upgrade.initReadOnly(_word + 's')) { return; }
18909        
18910        var tr, jPop = $('#manage-discount-popup');
18911        var ojpop = new GLO.Popup.Custom(jPop, GLO.Provider.Discount.save);
18912        
18913        jPop = ojpop.getPopup().addClass('pop-discount-edit');
18914        jPop.find('a.modalClose').css({ "top": "3px", "right": "3px" });
18915        jPop.find('h2').css({ "margin": 0 });
18916        jPop.find('.msg').append('<style> .ui-datepicker { z-index: 9999 !important; } </style>');
18917        jPop.find("#Start_dt, #End_dt").datepicker({ minDate: 0 });
18918        
18919        UI.timeMask('#Restrict_Start_tm');
18920        UI.timeMask('#Restrict_End_tm', '11:59 am');
18921        
18922        var jbtns = jPop.find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "480px" });
18923        jbtns.find('.btnSave').css({ "margin": "0", "text-align": "center" });
18924        
18925        if (thisLink) {
18926            tr = $(thisLink).closest('tr');
18927            var isFee = _openEditPopulate(jPop, tr);
18928            _openDiscountStatus(jPop);
18929        }
18930        
18931        _openDayTimeRestriction(jPop, tr);
18932        _openHighlightRuleNumber(jPop, highlightRuleNumber);
18933        
18934        if (isFee) {
18935        	_openEditFee(jPop);
18936        }
18937        
18938        if (GLO.Provider.isManagerCheck(_word, jPop, tr)) {
18939        	jPop.find('input, select, textarea').change( function() { 
18940	            $(this).closest('.glopop').find('.btnSave a').css({ "border": "3px solid Red" });
18941    	    });
18942    	}
18943        
18944        if (!UTIL.isEmpty(addRuleType)) {
18945        	 GLO.Provider.Discount.addRule();
18946        	 var tr = jPop.find('.discount-rule:last');
18947        	 tr.find('.select-discount-type').val(addRuleType).change();
18948        	 tr.find('.discount-rule-option select:visible').val(addRuleValue).focus();
18949        }
18950        
18951        ojpop.realign();
18952        jPop.css({ "top": "32px" });
18953        $(window).scrollTop(0);
18954    }
18955    function _openEditFee(jpop) {
18956    	jpop.find('#manage-discount-popup').addClass('is-fee');
18957    }
18958    function _openEditPopulate(jPop, tr) {
18959    	var pdid = tr.attr('provider_discount_id');
18960        var start = tr.find('.start-date').attr('dt');
18961        var end = tr.find('.end-date').attr('dt');
18962        
18963        var jamt = tr.find('.discount-column-amount');
18964        var minPurchase = tr.find('.min-purchase').text().replace('$', '');
18965        var discountType = tr.attr('discount_type1_cd'), maxAllowed = tr.attr('max_allowed_sr');
18966        var jname = tr.find('.discount-column-name');
18967        var split = tr.find('.discount-column-commission-split').attr('commission_split_cd');
18968        var splitPercent = tr.find('.discount-column-commission-split').attr('commission_split_pct');
18969        
18970        if (maxAllowed > 10) { maxAllowed = 99; }
18971        
18972        jPop.find('#Provider_Discount_id').val(pdid);
18973        jPop.find('#Discount_Name_vc').val($.trim(UTIL.coalesce(jname.attr('title'), jname.text())));
18974        jPop.find('#Max_Allowed_sr').val(maxAllowed);
18975        jPop.find('#Commission_Split_cd').val(split).change();
18976        jPop.find('#Commission_Split_pct').val(splitPercent);
18977        
18978        _openEditPopulatePromo(jPop, tr);
18979        
18980        if (UTIL.isDate(start)) {
18981        	start = new Date(start).toGloDate();
18982        	jPop.find('#Start_dt').val(start);
18983        }
18984        
18985        if (UTIL.isDate(end)) {
18986        	end = new Date(end).toGloDate();
18987        	jPop.find('#End_dt').val(end);
18988        }
18989        
18990        var dpct = UTIL.coalesceFloat(jamt.attr('discount_pct')), dmn = UTIL.coalesceMoney(jamt.attr('discount_mn'));
18991        
18992        if (UTIL.coalesceMoney(dpct, 0) + UTIL.coalesceMoney(dmn, 0) < 0) {
18993        	var isFee = true;
18994        	
18995        	if (UTIL.coalesceMoney(dpct) < 0) { dpct = -dpct; }
18996        	if (UTIL.coalesceMoney(dmn) < 0) { dmn = -UTIL.coalesceMoney(dmn); }
18997        } else {
18998        	var isFee = false;
18999        }
19000        
19001        if (dpct > 0) {
19002        	jPop.find('#Discount_pct').val(dpct);
19003        }
19004        
19005        if (dmn > 0) {
19006        	jPop.find('#Discount_mn').val(dmn);
19007        }
19008        
19009        if (!UTIL.isEmpty(minPurchase)) {
19010        	jPop.find('#require-min-purchase').prop('checked', true);
19011        	jPop.find('#Minimum_Purchase_mn').val(minPurchase);
19012        }
19013        
19014        if (!UTIL.isEmpty(discountType)) {
19015        	_openRuleRow(tr, jPop, 1, true);
19016        	_openRuleRow(tr, jPop, 2, true);
19017        	_openRuleRow(tr, jPop, 3, true);
19018        }
19019        
19020        if (tr.find('.always .check-mark').length === 1 || UTIL.isEmpty(pdid)) {
19021        	jPop.find('#Always_fl').prop('checked', true);
19022        }
19023        
19024        return isFee;
19025    }
19026    function _openEditPopulatePromo(jPop, tr) {
19027        var tdPromo = tr.find('.discount-column-promo-code');
19028        var promoCode = $.trim(tr.attr('promo_code_vc'));			// $.trim(tdPromo.find('i').text());
19029        
19030        if (!UTIL.isEmpty(promoCode)) {
19031	        jPop.find('#Promo_Code_vc').val(promoCode).change();
19032	        jPop.find('#Require_Promo_Code_fl').prop('checked', tdPromo.find('.is-require-promo').length);
19033	        jPop.find('#Promo_Message_vc').val(tdPromo.find('.discount-promo-message').text());
19034        }
19035    }
19036    
19037    function _openDiscountStatus(jpop) {
19038    	var dt1 = jpop.find('#Start_dt').val(), dt2 = jpop.find('#End_dt').val();
19039    	var msg = null;
19040    	
19041    	if (UTIL.isDate(dt2) && new Date(dt2) < new Date()) {
19042    		msg = _word + ' Expired on ' + new Date(dt2).toSADate(true);
19043    	} else if (UTIL.isDate(dt1) && new Date(dt1) > new Date()) {
19044    		msg = _word + ' Not Active Until ' + new Date(dt1).toSADate(true);
19045    	}
19046    	
19047    	if (!UTIL.isEmpty(msg)) {
19048    		var htm = '<div id="pop-discount-status">' + msg + '</div>';
19049    		jpop.find('#manage-discount-popup').prepend(htm);
19050    	}
19051    }
19052    
19053    function _openHighlightRuleNumber(jpop, highlightRuleNumber) {
19054    	jpop.find('.discount-rule').eq(highlightRuleNumber-1).find('.discount-rule-option select').focus();
19055    }
19056    
19057    function _openDayTimeRestriction(jpop, tr) {
19058    	var jrestrict = jpop.find('#discount-daytime-restriction');
19059    	
19060    	if (innerWidth < 760) {
19061    		var jlabels = jrestrict.find('#discount-restrict-day-row2').find('label');
19062    		
19063    		for (var i=0; i < jlabels.length; i++) {
19064    			jlabels.eq(i).text(jlabels.eq(i).text().substring(0,3));
19065    		}
19066    	}
19067    	
19068    	if (tr) {
19069	    	var tm1 = tr.attr('restrict_start_tm'), tm2 = tr.attr('restrict_end_tm');
19070	    	var jcheck = jrestrict.find(':checkbox');
19071			
19072	    	if (UTIL.isValidTime(tm1)) { jpop.find('#Restrict_Start_tm').val(tm1); }
19073	    	if (UTIL.isValidTime(tm2)) { jpop.find('#Restrict_End_tm').val(tm2); }
19074	    	
19075			for (var i=0; i < jcheck.length; i++) {
19076				var isChecked = UTIL.parseBool(tr.attr(jcheck.eq(i).attr('id')));
19077				jcheck.eq(i).prop('checked', isChecked);
19078			}
19079		}
19080    }
19081    
19082    function _openRuleRow(tr, jpop, ruleNumber, isLoading) {
19083    	var discountType = tr.attr('discount_type' + ruleNumber + '_cd');
19084    	
19085    	if (UTIL.isNumber(discountType)) {
19086    		discountType = parseInt(discountType);
19087    		
19088    		if (discountType > 3) {
19089	    		var ruleTR = _conManageD.addRule(isLoading);
19090	    		
19091	    		if (ruleTR) {
19092		    		var stype = null, ruleDID;
19093		    		
19094		    		if (discountType === 4 || discountType === 8 || discountType === 9 || discountType === 10) {
19095		    			stype = 'p';
19096		    			ruleDID = ruleTR.find('.product-list');
19097		    		} else if (discountType === 5 || discountType === 6 || discountType === 7) {
19098		    			stype = 's';
19099		    			ruleDID = ruleTR.find('.service-list');
19100		    		} else if (discountType === 20) {
19101		    			stype = 't';
19102		    			ruleDID = ruleTR.find('.tag-list');
19103		    		} else if (discountType === 30) {
19104		    			stype = 'r';
19105		    			jpop.find('#discount-daytime-restriction').removeClass('hide');
19106		    		} else if (discountType === 50) {
19107		    			stype = 'l';
19108		    			ruleDID = ruleTR.find('.discount-loyalty-points').removeClass('hide');
19109		    		} else if (discountType === 60) {
19110		    			stype = '$';
19111		    			ruleDID = _getPayMethodDD(ruleTR).removeClass('hide').find('.payment-method');
19112		    		} else if (discountType === 70) {
19113		    			stype = 'b';
19114		    			ruleDID = ruleTR.find('.birthday-list-container').removeClass('hide').find('.birthday-list');
19115		    		} else if (discountType === 80) {
19116		    			stype = 'm';
19117		    			ruleDID = ruleTR.find('.membership-list-container').removeClass('hide').find('.membership-list');
19118		    		}
19119		    		
19120		    		if (stype !== null) {
19121		    			ruleTR.find('.select-discount-type').val(stype).change();
19122		    			
19123		    			var discountId = tr.attr('discount_type' + ruleNumber + '_id');
19124		    			
19125		    			if (!UTIL.isEmpty(discountId)) {
19126		    				var did = null;
19127		    				
19128		    				if (discountType === 6 || discountType === 8 || discountType === 20 || discountType === 40 || discountType === 50 || discountType === 60) {
19129		    					did = discountId;
19130		    				} else if (discountType === 7) {
19131		    					did = 'sg' + discountId;
19132		    				} else if (discountType === 9) {
19133		    					did = 'pl' + discountId;
19134		    				} else if (discountType === 10) {
19135		    					did = 'v' + discountId;
19136		    				} else if (discountType === 70) {
19137		    					did = discountId;
19138		    				}  else if (discountType === 80) {
19139		    					did = discountId;
19140		    				}
19141		    				
19142		    				if (did !== null) {
19143		    					ruleDID.val(did);
19144		    				}
19145		    			}
19146		    		}
19147	    		}
19148	    	}
19149    	}
19150    }
19151    
19152    _conManageD.changeCommissionSplit = function() {
19153    	var jpop = $('#manage-discount-popup');
19154    	var split = jpop.find('#Commission_Split_cd').val();
19155    	
19156    	if (split == 4) {
19157    		jpop.addClass('is-custom-split');
19158    	} else {
19159    		jpop.removeClass('is-custom-split');
19160    	}
19161    }
19162    
19163    _conManageD.removeRule = function(thisIcon) {
19164    	var tr = $(thisIcon).closest('tr');
19165    	
19166    	if ( $('#discount-rules').find('tr.discount-rule:visible').length === 1 ) {
19167    		tr.addClass('hide');
19168    	} else {
19169    		tr.remove();
19170    	}
19171    	
19172    	_hideDayTimeRestriction();
19173    }
19174    
19175    _conManageD.addRule = function(isLoading) {
19176    	var jpop = $('#manage-discount-popup').closest('.glopop').css({ "height": "" });
19177    	var jtbl = jpop.find('#discount-rules table');
19178    	var newTR, trs = jtbl.find('tr.discount-rule');
19179    	
19180    	if (trs.length === 1 && trs.eq(0).hasClass('hide')) {
19181    		jtbl.find('#discount-always-apply').removeClass('hide');
19182    		trs.removeClass('hide');
19183    		
19184    		if (!isLoading) {
19185    			trs.find('.select-discount-type').focus();
19186    		}
19187    		
19188    		newTR = trs;
19189    	} else if (!isLoading && trs.length === 3) {
19190    		new GLO.Popup.Warning(SA.Resource.ThreeRuleLimitWarning);
19191    		return;
19192    	} else {
19193    		newTR = trs.eq(0).clone();
19194    		newTR.find('select').val('').change();
19195    		
19196    		trs.eq(trs.length - 1).after(newTR);
19197    		
19198    		if (!isLoading) {
19199    			jtbl.find('.select-discount-type:last').focus();
19200    		}
19201    	}
19202    	
19203    	return newTR;
19204    }
19205    _conManageD.displayMaxAllowed = function() {
19206    	var isDisplay = false, isProduct = false, isService = false;
19207    	var jpop = $('#manage-discount-popup');
19208    	var dmn = UTIL.coalesceMoney(jpop.find('#Discount_mn').val());
19209    	var jselect = jpop.find('select.select-discount-type');
19210    	
19211    	for (var i=0; i < jselect.length; i++) {
19212    		var rule = jselect.eq(i).val();
19213    		
19214    		if (rule == 'p' || rule == 's') {				// && dmn > 0 			// && rule > 3 && rule < 11
19215    			isDisplay = true;
19216    			
19217    			if (rule == 'p') {
19218    				isProduct = true;
19219    			} else if (rule == 's') {
19220    				isService = true
19221    			}
19222    		}
19223    	}
19224    	
19225    	isDisplay = true;
19226    	
19227    	if (isDisplay) {
19228    		var jdd = jpop.find('#max-allowed-container').removeClass('hide').find('#Max_Allowed_sr');
19229    		
19230    		if (isProduct && isService) {
19231    			jdd.addClass('has-product-and-service-option').find('option[value="99"]').text('per service / product');
19232    		} else if (isProduct) {
19233    			jdd.removeClass('has-product-and-service-option').find('option[value="99"]').text('per product');
19234    		} else if (isService) {
19235    			jdd.removeClass('has-product-and-service-option').find('option[value="99"]').text('per service');
19236    		} else {
19237    			jdd.addClass('has-product-and-service-option').find('option[value="99"]').text('per service / product');
19238    		}
19239    	} else {
19240    		jpop.find('#max-allowed-container').addClass('hide');
19241    	}
19242    }
19243    _conManageD.selectRuleType = function(thisDD) {
19244    	var jdd = $(thisDD), jPop = $('#manage-discount-popup'), newDD = null;
19245    	var tr = jdd.closest('tr');
19246    	
19247    	_hideDayTimeRestriction();
19248    	tr.find('.product-list, .service-list, .tag-list-container, .discount-loyalty-points, .payment-method-container, .birthday-list-container, .membership-list-container').addClass('hide');
19249    	
19250    	if (jdd.val() === 'p') {
19251    		newDD = tr.find('.product-list').removeClass('hide');
19252    	} else if (jdd.val() === 's') {
19253    		newDD = tr.find('.service-list').removeClass('hide');
19254    	} else if (jdd.val() === 't') {
19255    		var jtaglist = tr.find('.tag-list-container').removeClass('hide').find('.tag-list');
19256    		
19257    		if (jtaglist.find('option').length > 0) {
19258    			newDD = jtaglist.removeClass('hide');
19259    		} else {
19260    			var aClientTag = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/tag\', this, event, true)">Setup <i>Client Tags</i></a>';
19261    			var htm = '<b id="goto-client-tag-manager" class="tag-list"><span>No client tags found</span> ' + aClientTag + '</b>';
19262    			newDD = jtaglist.replaceWith(htm);
19263    		}
19264    	} else if (jdd.val() === 'r') {
19265    		jPop.find('#discount-daytime-restriction').removeClass('hide').find('#Restrict_Start_tm').focus();
19266    	} else if (jdd.val() === 'l') {
19267    		tr.find('.discount-loyalty-points').removeClass('hide').focus();
19268    	} else if (jdd.val() === '$') {
19269    		var jpm = _getPayMethodDD(tr);
19270    		
19271    		jpm.removeClass('hide').find('.payment-method').focus();
19272    	} else if (jdd.val() === 'b') {
19273    		tr.find('.birthday-list-container').removeClass('hide').find('.birthday-list').focus();
19274    	} else if (jdd.val() === 'm') {
19275    		newDD = tr.find('.membership-list-container').removeClass('hide').find('.membership-list');
19276    	}
19277    	
19278    	if (newDD !== null && !GLO.Info.isIPad) { newDD.focus(); }
19279    	_conManageD.displayMaxAllowed();
19280    }
19281    function _getPayMethodDD(tr) {
19282    	var jpm = tr.find('.payment-method-container');
19283		
19284		if (jpm.length === 0) {
19285			var htmPayMeth = UserPortal.Price.getPricePopHtm().find('#appt-price-payment-table .Payment_Method_cd').html();
19286			var dd = '<select class="payment-method" style="max-width: 210px; padding-right: 0;">' + htmPayMeth + '</select>';
19287			var helpIcon = '<b class="question-icon" onclick="GLO.Provider.Discount.openHelpPayMethod(this)" style="margin-left: 4px;">?</b>';
19288			
19289			tr.find('.discount-rule-option').append('<span class="payment-method-container">' + dd + helpIcon + '</span>');
19290			jpm = tr.find('.payment-method-container');
19291			jpm.find('.payment-method option:first').text('(any payment)');
19292		}
19293		
19294		return jpm;
19295    }
19296    function _hideDayTimeRestriction() {
19297    	var jpop = $('#manage-discount-popup').closest('.glopop');
19298    	
19299    	if (jpop.find('#discount-rules').find('.select-discount-type:visible option:selected[value="r"]').length === 0) {
19300    		jpop.find('#discount-daytime-restriction').addClass('hide');
19301    	}
19302    }
19303    
19304    _conManageD.remove = function(thisTD) {
19305        if (!GLO.Provider.isManagerCheck(_word)) { return; }
19306        
19307        var tr = $(thisTD).closest('tr');
19308        var discount = tr.find('.discount-column-name span').text();
19309        
19310        GLO.Popup.Confirm(SA.Resource.RemoveConfirmQuestion + ' ' + discount + '?', function() { GLO.Provider.Discount.removeConfirmed(tr); });
19311    }
19312
19313    _conManageD.removeConfirmed = function(tr) {
19314        if (!GLO.Provider.isManagerCheck(_word)) { return; }
19315        
19316        var url = GLO.Link.Page.Provider.Home + 'manage/RemoveDiscount';
19317        var pdId = tr.attr('provider_discount_id');
19318        
19319        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_discount_id": pdId } })
19320            .success(function(data, textStatus, jqXHR) {
19321                var tbl = $('#DiscountList tbody');
19322                tbl.find('tr[provider_discount_id="' + pdId + '"]').remove();
19323            })
19324            .error(function(jqXHR, textStatus, errorThrown) {
19325                new GLO.Popup.Error('Unable to remove this ' + _word + ' at this time.  Please try again later.');
19326            });
19327    }
19328	
19329	function _populateDiscountTypes(jpop, jsonDiscount) {
19330		var rules = jpop.find('tr.discount-rule:visible');
19331        var always = jpop.find('#Always_fl:visible');
19332        
19333        if (rules.length > 0) {
19334	        var jdd, jopt, optVal, cdColumnName, idColumnName, discountType;
19335	        
19336	        if (always.prop('checked')) { jsonDiscount.always_fl = "1" }
19337	        
19338	        for (var i=0; i < rules.length; i++) {
19339	        	discountType = null;
19340	        	jdd = rules.eq(i).find('.product-list:visible');
19341	        	
19342	        	cdColumnName = "discount_type" + (i + 1) + "_cd";
19343	        	idColumnName = "discount_type" + (i + 1) + "_id";
19344	        	
19345	        	if (jdd.length === 1) {
19346	        		jopt = jdd.find('option:selected');
19347	        		optVal = jopt.attr('value');
19348	        		
19349	        		if (UTIL.isEmpty(optVal)) {
19350	        			jsonDiscount[cdColumnName] = 4;
19351	        		} else {
19352	        			if (jopt.hasClass('v-option')) {
19353	        				jsonDiscount[cdColumnName] = 10;
19354	        				jsonDiscount[idColumnName] = optVal.replace('v', '');
19355	        			} else if (jopt.hasClass('pl-option')) {
19356	        				jsonDiscount[cdColumnName] = 9;
19357	        				jsonDiscount[idColumnName] = optVal.replace('pl', '');
19358	        			} else {
19359	        				jsonDiscount[cdColumnName] = 8;
19360	        				jsonDiscount[idColumnName] = optVal;
19361	        			}
19362	        		}
19363	        	} else {
19364	        		jdd = rules.eq(i).find('.service-list:visible');
19365	        		
19366	        		if (jdd.length === 1) {
19367		        		jopt = jdd.find('option:selected');
19368		        		optVal = jopt.attr('value');
19369		        		
19370		        		if (UTIL.isEmpty(optVal)) {
19371		        			jsonDiscount[cdColumnName] = 5;
19372		        		} else {
19373		        			if (jopt.hasClass('sg-option')) {
19374		        				jsonDiscount[cdColumnName] = 7;
19375		        				jsonDiscount[idColumnName] = optVal.replace('sg', '');
19376		        			} else {
19377		        				jsonDiscount[cdColumnName] = 6;
19378		        				jsonDiscount[idColumnName] = optVal;
19379		        			}
19380		        		}
19381		        	} else {
19382		        		var dtid = rules.eq(i).find('.select-discount-type').val();
19383		        		var tagId = rules.eq(i).find('.tag-list:visible').val();
19384		        		
19385		        		if (dtid == 't' && !UTIL.isEmpty(tagId)) {
19386		        			jsonDiscount[cdColumnName] = 20;
19387		        			jsonDiscount[idColumnName] = tagId;
19388		        		} else if (dtid === 'r') {
19389		        			if (_populateRestrictDayTime(jpop, jsonDiscount)) {
19390		        				jsonDiscount[cdColumnName] = 30;
19391		        				//jsonDiscount[idColumnName] = 1;
19392		        			}
19393		        		} else if (dtid === 'l') {
19394		        			jsonDiscount[cdColumnName] = 50;
19395		        			jsonDiscount[idColumnName] = jsonDiscount.loyalty_points_nr = rules.eq(i).find('.discount-loyalty-points').val();
19396		        		} else if (dtid === '$') {
19397		        			jsonDiscount[cdColumnName] = 60;
19398		        			jsonDiscount[idColumnName] = rules.eq(i).find('.payment-method').val();
19399		        		} else if (dtid === 'b') {
19400		        			jsonDiscount[cdColumnName] = 70;
19401		        			jsonDiscount[idColumnName] = rules.eq(i).find('.birthday-list:visible').val();
19402		        		} else if (dtid === 'm') {
19403		        			jsonDiscount[cdColumnName] = 80;
19404		        			jsonDiscount[idColumnName] = rules.eq(i).find('.membership-list').val();
19405		        		}
19406		        	}
19407	        	}
19408        	}
19409        }
19410	}
19411	
19412	function _populateRestrictDayTime(jpop, jsonDiscount) {
19413		var hasValid = false, hasDay = false;
19414		var jrestrict = jpop.find('#discount-daytime-restriction');
19415    	var tm1 = jpop.find('#Restrict_Start_tm').val(), tm2 = jpop.find('#Restrict_End_tm').val();
19416    	var jcheck = jrestrict.find(':checkbox:checked');
19417		
19418    	if (UTIL.isValidTime(tm1)) { jsonDiscount.restrict_start_tm = tm1; hasValid = true; }
19419    	if (UTIL.isValidTime(tm2)) { jsonDiscount.restrict_end_tm = tm2; hasValid = true; }
19420    	
19421		for (var i=0; i < jcheck.length; i++) {
19422			hasValid = true;
19423			hasDay = true;
19424			jsonDiscount[jcheck.eq(i).attr('id')] = 1;
19425		}
19426		
19427		if (hasValid && !hasDay) {			//= check all days (if time is set, but no day)
19428			jsonDiscount.Restrict_Sun_fl = jsonDiscount.Restrict_Mon_fl = jsonDiscount.Restrict_Tue_fl = jsonDiscount.Restrict_Wed_fl = 1;
19429			jsonDiscount.Restrict_Thu_fl = jsonDiscount.Restrict_Fri_fl = jsonDiscount.Restrict_Sat_fl = 1;
19430		}
19431		
19432		return hasValid;
19433	}
19434	
19435	function _validPromo(jpop, jsonDiscount, promo) {
19436        if (!UTIL.isEmpty(promo)) {
19437        	var firstOccurrance = UTIL.indexOfNonAlphaNumeric(promo);
19438        	
19439        	if (firstOccurrance >= 0) {
19440        		var badLetter = promo.substring(firstOccurrance, firstOccurrance + 1);
19441        		var htm = '<div>Promo code can only be letters and numbers</div> <div>The character <b style="font-size: 150%;">' + badLetter + '</b> is not allowed</div>';
19442        		GLO.Popup.Warning.open('<div class="friendly-msg2">' + htm + '</div>', 'Invalid Promo Code');
19443        		return false;
19444        	}
19445        	
19446        	jsonDiscount.promo_code_vc = promo;
19447        	jsonDiscount.require_promo_code_fl = jpop.find('#Require_Promo_Code_fl').prop('checked');
19448        	jsonDiscount.promo_message_vc = UTIL.htmlEncode(jpop.find('#Promo_Message_vc').val());
19449        }
19450        
19451        return true;
19452    }
19453	
19454    _conManageD.save = function() {
19455        if (!GLO.Provider.isManagerCheck(_word)) { return; }
19456        if (!GLO.Info.isRequireGold()) { return false; }
19457        
19458        var jpop = $('#manage-discount-popup');
19459        var discount = jpop.find('#Discount_Name_vc').val();
19460        var maxAllowed = UTIL.coalesceInt(jpop.find('#Max_Allowed_sr:visible').val(), 0);
19461        var alwaysApply = jpop.find('#Always_fl').prop('checked');
19462        var split = jpop.find('#Commission_Split_cd').val();
19463        var isFee = jpop.hasClass('is-fee');
19464        var promo = $.trim(jpop.find('#Promo_Code_vc').val());
19465        
19466        if (UTIL.isEmpty(discount)) {
19467            var fnFocus = function() { $('#manage-discount-edit').find('#Discount_Name_vc').focus(); };
19468            
19469            if (isFee) {
19470            	var msg = 'Please Enter Fee Name', word = 'Fee';
19471            } else {
19472            	var msg = SA.Resource.PleaseEnterDiscountName, word = 'Discount';
19473            }
19474            
19475            GLO.Popup.Warning.open(msg, 'Missing ' + word + ' Name', fnFocus);
19476            return;
19477        }
19478
19479        var discountNm = jpop.find('#Discount_Name_vc').val();
19480        var pdId = jpop.find('#Provider_Discount_id').val();
19481        
19482        var start = jpop.find('#Start_dt').val();
19483        var end = jpop.find('#End_dt').val();
19484        
19485        var pctDiscount = jpop.find('#Discount_pct').val();
19486        var mnDiscount = jpop.find('#Discount_mn').val();
19487        
19488        if (isFee) {
19489        	if (UTIL.coalesceInt(pctDiscount) > 0) {
19490        		if (pctDiscount.indexOf('.') !== -1) {
19491        			pctDiscount = -UTIL.coalesceFloat(pctDiscount);
19492        		} else {
19493        			pctDiscount = -UTIL.coalesceInt(pctDiscount);
19494        		}
19495        	}
19496        	
19497        	if (UTIL.coalesceMoney(mnDiscount) > 0) {
19498        		mnDiscount = -UTIL.coalesceMoney(mnDiscount);
19499        	}
19500        }
19501        
19502        if (_isEmptyAmount(pctDiscount, mnDiscount, isFee)) {
19503        	return;
19504        }
19505        
19506        var jsonDiscount = { "discount_name_vc": discountNm, "provider_discount_id": pdId, "start_dt": start, "end_dt": end, "discount_pct": pctDiscount, "discount_mn": mnDiscount
19507        					, "always_fl": alwaysApply, "fee_fl": isFee };
19508        
19509        if (maxAllowed > 0) { jsonDiscount.max_allowed_sr = maxAllowed; }
19510        
19511        if (!UTIL.isEmpty(split)) {
19512        	jsonDiscount.commission_split_cd = split;
19513        	
19514        	if (split == 4) {
19515        		jsonDiscount.commission_split_pct = jpop.find('#Commission_Split_pct').val();
19516        	}
19517        }
19518        
19519        if (!_validPromo(jpop, jsonDiscount, promo)) { return; }
19520        
19521        if (jpop.find('#require-min-purchase').prop('checked')) {
19522        	jsonDiscount.minimum_purchase_mn = jpop.find('#Minimum_Purchase_mn').val();
19523        }
19524        
19525        _populateDiscountTypes(jpop, jsonDiscount);
19526        
19527        if (!_displayInfoAndVerify(jsonDiscount)) {
19528        	return;
19529        }
19530        
19531        var url = GLO.Link.Page.Provider.Home + 'manage/discountSave';
19532        GLO.UI.Form.beginProcessing( jpop.closest('.glopop').find('.btnSave') );
19533
19534        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jsonDiscount })
19535            .success(function(data, textStatus, jqXHR) {
19536                GLO.UI.Form.resetProcessing();
19537                GLO.Popup.close( $('#manage-discount-popup').closest('.pop-custom') );
19538
19539                var tr = $(data);
19540                var tbl = $('#DiscountList tbody');
19541				var jtags = tr.find('.rule-tag');
19542				_initTagNameForTags(jtags)
19543
19544                tbl.find('tr[provider_discount_id="' + tr.attr('provider_discount_id') + '"]').remove();
19545                tbl.prepend(tr);
19546                tbl.find('#no-discount-row').remove();
19547                
19548                GLO.Provider.Discount.refresh();
19549            })
19550            .error(function(jqXHR, textStatus, errorThrown) {
19551                GLO.UI.Form.resetProcessing();
19552                new GLO.Popup.Error('Unable to edit this ' + _word + ' at this time.  Please try again later.');
19553            });
19554    }
19555    
19556    function _displayInfoAndVerify(jsonDiscount) {
19557    	if (jsonDiscount.fee_fl && jsonDiscount.discount_type1_cd == 60 && jsonDiscount.discount_type1_id == 10) {
19558    		_conManageD.displayConvenienceFeeOverview();
19559    		
19560    		if (Math.abs(jsonDiscount.discount_pct) > 3) {
19561    			var jpop = $('#pop-discount-row-amount').closest('.glopop');
19562    			jpop.find('#Discount_pct').val(3);
19563    			jpop.find('#Discount_mn').val('');
19564    			
19565    			var msg = '<p>The government restricts credit card fees to a maximum of 3%</p>';
19566    			GLO.Popup.Warning.open(msg, 'Maximum Credit Card Fee Warning');
19567    			return false;
19568    		}
19569    	}
19570    	
19571    	return true;
19572    }
19573    _conManageD.displayConvenienceFeeOverview = function() {
19574    	var uriPayOnline = 'provider/manage/ClientPayOnline';
19575		var btnIfEnabled = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uriPayOnline + '\', this, event, true)">Setup Payments When Clients Book Online</a></span>';
19576		
19577		var htm = '<p>If full payment required when booking online then this fee will be charged when client books online</p>';
19578		//htm += '<div style="text-align: center;"><small>(bonus for pre-paying online)</small></div>';
19579		htm += '<div style="margin-top: 8px; margin-bottom: 32px; text-align: center;">' + btnIfEnabled + '</div>';
19580		
19581		var urlMoreInfo = 'https://merchants.fiserv.com/content/dam/firstdata/us/en/documents/pdf/Understanding_Surcharging_Convenience_Service_Fees.pdf';
19582		var aMoreInfo = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlMoreInfo + '\', this, event, true, \'ccfeeinfo\')">Understanding Card Fees</a>';
19583		var css = 'margin-top: 8px; line-height: 1.4; text-align: left; font-size: 14px;';
19584		
19585		htm += '<div style="' + css + '">The credit card convenience fee must be clearly displayed at the point of sale</div>';
19586		htm += '<div style="' + css + '">As of March 2023, credit card surchage fees are not allowed in: Connecticut, Massachusetts, and Puerto Rico</div>';
19587		htm += '<div style="' + css + ' margin-bottom: 36px;">To verify you are following all state and federal laws as well as best practices visit ' + aMoreInfo + '</div>';
19588		
19589		return GLO.Popup.Info.open(htm, 'Credit Card Add-On Fee');
19590    }
19591    
19592    function _isEmptyAmount(pctDiscount, mnDiscount, isFee) {
19593    	if (UTIL.coalesceMoney(pctDiscount, 0) === 0 && UTIL.coalesceMoney(mnDiscount, 0) === 0) {
19594        	var fnFocus = function() { $('#manage-discount-popup').find('#Discount_pct').focus(); };
19595        	
19596        	if (isFee) {
19597            	var msg = 'Please Enter Fee Amount <small style="white-space: nowrap;">(percent or dollar amount)</small>', word = SA.Resource.Fee;
19598            } else {
19599            	var msg = SA.Resource.DiscountHelp, word = SA.Resource.Discount;
19600            }
19601            
19602            GLO.Popup.Warning.open(msg, 'Missing ' + word + ' Amount', fnFocus);
19603        	return true;
19604        }
19605    }
19606    
19607    _conManageD.openDateFilter = function(start, end) {
19608    	var htmStart = '<input type="text" id="Start_d" name="Start_d" class="filter-date" pattern="[0-9]*" placeholder="Start" onclick="GLO.UI.displayDatePicker(this)"/>';
19609    	var htmEnd = '<input type="text" id="End_d" name="End_d" class="filter-date" pattern="[0-9]*" placeholder="End" onclick="GLO.UI.displayDatePicker(this)"/>';
19610    	
19611    	var css = '<style> #ui-datepicker-div { z-index: 6000 !important; } </style>';
19612    	var msg = '<p style="padding: 0 8px; text-align: center;">Filter by date the ' + _wordLong + ' was added to the ticket</p>';
19613    	var htm = '<div id="pop-report-filter-date-range">' + css + msg + '<div id="pop-report-filter-date-range-input">' + htmStart + htmEnd  + '</div>';
19614    	
19615    	var jpop = GLO.Popup.Custom.openSimple(htm, _wordLong + ' Report', GLO.Provider.Discount.filterByDate);
19616    	jpop.find('.btnSave').addClass('btnAdd').removeClass('btnSave').css({ "position": "absolute", "right": "8px" }).find('>a').text('Search');
19617    	
19618    	//jWaitEdit.find("#Wait_Request_d").datepicker({ showWeek: true, beforeShowDay: UserPortal.setDatePickerDays, calculateWeek: UTIL.datePickerCalculateWeek });
19619    	var jstart = jpop.find('#Start_d').datepicker({ showButtonPanel: true, maxDate: 0, changeYear: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(1480) });
19620        var jend = jpop.find('#End_d').datepicker({ showButtonPanel: true, maxDate: 0, changeYear: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(1080) });
19621        
19622        if (UTIL.isDate(start)) {
19623        	jstart.val(start);
19624        }
19625        
19626        if (UTIL.isDate(end)) {
19627        	jend.val(end);
19628        }
19629    }
19630    _conManageD.filterByDate = function() {
19631    	var jpop = $('#pop-report-filter-date-range').closest('.glopop');
19632    	var start = jpop.find('#Start_d').val();
19633    	var end = jpop.find('#End_d').val();
19634    	
19635    	_conManageD.search(start, end);
19636    	
19637    	var word = 'Discount';
19638    	
19639    	if (UTIL.parseBool($('#manage-discount-container').attr('is_fee'))) {
19640    		word = 'Add-On Fee';
19641    	}
19642    	
19643    	var htm = '<span>Displaying ' + word + ' used</span>';
19644    	var dayStart = new Date(start).toGloDate();
19645    	var dayEnd = new Date(end).toGloDate();
19646    	
19647    	if (UTIL.isDate(start) && UTIL.isDate(end)) {
19648    		document.title = word + ' Report ' + dayStart + ' - ' + dayEnd;
19649    		var fn = 'GLO.Provider.Discount.openDateFilter(\'' + dayStart + '\', \'' + dayEnd + '\')';
19650    		
19651    		htm += '<span>between</span>'
19652                + '<a class="filter-start-date" onclick="' + fn + '">' + dayStart + '</a>'
19653                + '<i> - </i>'
19654                + '<a class="filter-end-date" onclick="' + fn + '">' + dayEnd + '</a>';
19655    	} else if (UTIL.isDate(start)) {
19656    		document.title = word + ' Report After' + dayStart
19657    		var fn = 'GLO.Provider.Discount.openDateFilter(\'' + dayStart + '\')';
19658    		htm += '<span>after</span>' + '<a class="filter-start-date" onclick="' + fn + '">' + dayStart + '</a>';
19659    	} else if (UTIL.isDate(end)) {
19660    		document.title = word + ' Report Before' + dayEnd;
19661    		var fn = 'GLO.Provider.Discount.openDateFilter(null, \'' + dayEnd + '\')';
19662    		htm += '<span>before</span>' + '<a class="filter-end-date" onclick="' + fn + '">' + dayEnd + '</a>';
19663    	} else {
19664    		document.title = word + ' Report';
19665    		htm = '<div><span class="btnAdd"><a onclick="GLO.Provider.Discount.openDateFilter()">Filter ' + word + ' used by date</a></span></div>';
19666    	}
19667    	
19668    	$('#manage-discount-container-top-filter, #manage-discount-container-top-help').replaceWith('<div id="manage-discount-container-top-filter">' + htm + '</div>');
19669    }
19670    _conManageD.refresh = function() {
19671    	/*
19672    	var j = $('#manage-discount-container-top-filter');
19673    	var start = j.find('.filter-start-date').text();
19674    	var end = j.find('.filter-end-date').text();
19675    	
19676    	_conManageD.search(start, end);
19677    	*/
19678    	
19679    	var word = 'Discount';
19680    	
19681    	if (UTIL.parseBool($('#manage-discount-container').attr('is_fee'))) {
19682    		word = 'Add-On Fee';
19683    	}
19684    	
19685    	var htm = '<div><span class="btnAdd">
19685<a onclick="GLO.Provider.Discount.openDateFilter()">Filter ' + word + ' used by date</a></span></div>';
19686    	$('#manage-discount-container-top-filter, #manage-discount-container-top-help').replaceWith('<div id="manage-discount-container-top-filter">' + htm + '</div>');
19687    	_conManageD.search();
19688    }
19689    
19690    _conManageD.search = function(start, end) {
19691    	var jbutton = $('#manage-discount-header .fa-refresh');
19692    	var jd = {};
19693    	
19694    	if (jbutton.hasClass('fa-spin')) {
19695    		return;
19696    	} else if (!GLO.Report.hasReportPassword(jd)) {
19697	    	return;
19698	    }
19699    	
19700    	jbutton.addClass('fa-spin');			//GLO.UI.Form.beginProcessing(jbutton);
19701    	
19702    	var jrpt = $('.report-container');
19703    	var isExpired = $('#manage-discount-container #Include_Inactive_fl').prop('checked');
19704    	var page = 'discount', word = 'Discount', hasDateRange = false;
19705    	
19706    	if (UTIL.parseBool($('#manage-discount-container').attr('is_fee'))) {
19707    		page = 'addon';
19708    		word = 'Add-On Fee';
19709    	}
19710    	
19711    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/' + page + '?display-expired=' + isExpired;
19712    	
19713    	if (UTIL.isDate(start)) {
19714    		uri += '&start=' + new Date(start).toGloDate();
19715    		hasDateRange = true;
19716    	}
19717    	if (UTIL.isDate(end)) {
19718    		uri += '&end=' + new Date(end).toGloDate();
19719    		hasDateRange = true;
19720    	}
19721    	
19722    	if (hasDateRange) {
19723        	GLO.Popup.closeIfExist($('#pop-report-filter-date-range').closest('.glopop'));
19724        }
19725    	
19726    	var jqxhr = $.ajax({ "type": "POST", "url": (uri + '&ispartial=1'), "cache": false, "data": jd })
19727            .success(function(data, textStatus, jqXHR) {
19728                jbutton.removeClass('fa-spin');				//GLO.UI.Form.resetProcessing();
19729                
19730                jrpt.html($(data).html());
19731                _conManageD.initData(jrpt);
19732                
19733                if (!hasDateRange) {
19734                	document.title = word + ' Report';
19735                }
19736                
19737                window.history.pushState('', '', uri);
19738            })
19739            .error(function(jqXHR, textStatus, errorThrown) {
19740            	jbutton.removeClass('fa-spin');
19741            	//jrpt.html('<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>');
19742            });
19743    }
19744    
19745    _conManageD.changePromoCode = function() {
19746    	var jpop = $('#manage-discount-popup').closest('.glopop').css({ "height": "" });
19747    	var promo = jpop.find('#Promo_Code_vc').val();
19748    	
19749    	if (!UTIL.isEmpty(promo)) {
19750    		var promoUrl = GLO.Data.provider.websiteuri + 'client#promo=' + promo;
19751    		var promoLink = '<a href="' + promoUrl.replace('http://', '').replace('https://', '') + '">' + promoUrl + '</a>';
19752    		
19753    		//jpop.find('#Require_Promo_Code_fl').prop('checked', true);
19754    		//jpop.find('#Always_fl').prop('checked', true);
19755    		
19756    		jpop.find('#pop-discount-promo-message').removeClass('hide');
19757    		jpop.find('#pop-discount-promo-link').removeClass('hide').find('a').replaceWith(promoLink);
19758    	} else {
19759    		jpop.find('#pop-discount-promo-message').addClass('hide');
19760    		jpop.find('#pop-discount-promo-link').addClass('hide').find('a').replaceWith('<a/>');
19761    	}
19762    }
19763    
19764    _conManageD.openCommissionSplitHelp = function() {
19765    	var jpop = $('#manage-discount-popup');
19766        var isFee = jpop.hasClass('is-fee');
19767        
19768    	_conManageD.openCommissionSplit(isFee, false);
19769    }
19770    _conManageD.openCommissionSplit = function(isFee, isAllowEdit) {
19771    	GLO.Popup.closeIfExist($('#pop-provider-commission-split').closest('.glopop'));
19772    	
19773    	var split = $('#btnCommissionSplit').attr('commission_split_cd');
19774    	var msg = 'How Service Commission is affected by '
19775        var btnLabel = 'Save';
19776        var word = 'Discount', btnOther = null;
19777        
19778    	if (isFee) {
19779    		msg += 'Fees';
19780    		word = 'Add-On Fee';
19781    		var pct = GLO.Data.provider.commission_split_fee_pct;
19782    		
19783    		var text1 = 'staff gets 100% of fee';
19784    		var text2 = 'default; fee added to price, <small>
19784then commission calculated normally</small>';
19785    		var text3 = 'entire fee goes to business\'s profit <small>(staff does not get fee)</small>';
19786    		var text4 = 'percent of fee added to staff\'s commission';
19787    	} else {
19788    		msg += 'Discounts';
19789    		var pct = GLO.Data.provider.commission_split_discount_pct;
19790    		
19791    		var text1 = 'discount subtracted from staff\'s commission <small>(entire discount taken out of staff commision)</small>';
19792    		var text2 = 'default; price discounted, <small>then commission calculated normally</small>';
19793    		var text3 = 'discount subtracted from business\'s profit <small>(staff commission same as if there was no discount)</small>';
19794    		var text4 = 'percent of discount added to staff\'s commission';
19795    	}
19796    	
19797    	var rdo1 = '<input type="radio" name="Commission_Split_cd" id="Split_Staff_cd" value="1"/>';
19798    	var label1 = '<label for="Split_Staff_cd"><b>Staff</b></label>';
19799    	
19800    	var rdo2 = '<input type="radio" name="Commission_Split_cd" id="Split_Proportional_cd" value="0"/>';
19801    	var label2 = '<label for="Split_Proportional_cd"><b>Split</b></label>';
19802    	
19803    	var rdo3 = '<input type="radio" name="Commission_Split_cd" id="Split_Business_cd" value="2"/>';
19804    	var label3 = '<label for="Split_Business_cd"><b>Business</b></label>';
19805    	
19806    	if (isAllowEdit) {
19807    		var rdo0 = '';
19808    	} else {
19809    		var htmArrow = ' <b style="display: inline-block; padding-left: 6px; padding-right: 6px;">&#10140;</b> ';
19810    		var btnSeeDefault = '<span class="btnAdd btnAction2"><a onclick="GLO.Provider.Discount.helpCommissionSplitSeeDefault(' + isFee + ')">See Default</a></span>';
19811    		var text0 = 'default commission split set on <b>' + word + ' Report</b> ' + htmArrow + btnSeeDefault;
19812    		var label0 = '<label for="Use_Default_cd"><b>Use Default</b></label>';
19813    		var rdo0 = '<li> <span class="commission-split-type">' + label0 + '</span> <span class="commission-split-text">' + text0 + '</span> </li>';
19814    		
19815    		rdo1 = ''; rdo2 = ''; rdo3 = '';
19816    		btnLabel = 'Close';
19817    		var btnPage = GLO.Report.portalName.toLowerCase();
19818    		
19819    		if (btnPage != 'discount' && btnPage != 'fee') {
19820    			if (isFee) {
19821    				btnOther = '<span id="btnViewSplitOther" class="btnAdd" onclick="GLO.Provider.Discount.openCommissionSplit(0, false)"><a>How Works for Discounts</a></span>';
19822    			} else {
19823    				btnOther = '<span id="btnViewSplitOther" class="btnAdd" onclick="GLO.Provider.Discount.openCommissionSplit(1, false)"><a>How Works for Add-On Fees</a></span>';
19824    			}
19825    		}
19826    	}
19827    	
19828    	if (GLO.Info.isGold()) {
19829    		var helpIcon = '<b class="question-icon" onclick="GLO.Provider.Discount.helpCommissionSplitCustom()" style="margin: 0 8px; border-width: 2px;">&#63;</b>';
19830    		
19831    		if (pct == 0) {
19832    			pct = '';
19833    		}
19834    		
19835    		if (isAllowEdit) {
19836    			var rdo4 = '<input type="radio" name="Commission_Split_cd" id="Split_Custom_cd" value="4" onclick="UI.changeFocus(this, \'Commission_Split_pct\')" style="margin: 0 4px;"/>';
19837    			var htmPercent = '<input id="Commission_Split_pct" type="number" value="' + pct + '" min="5" max="95" onchange="UI.markCheckbox(this, \'Split_Custom_cd\')"/>';
19838    		} else {
19839    			var rdo4 = '', htmPercent = '';
19840    		}
19841    		
19842    		var percentSign = '<b class="percent-sign">%</b>';
19843    		var label4 = '<label for="Split_Custom_cd"><b>Custom</b>' + htmPercent + percentSign + helpIcon + '</label>';
19844    		rdo4 = '<li> <span class="commission-split-type">' + rdo4 + label4 + '</span> <span class="commission-split-text">' + text4 + '</span> </li>';
19845    	} else {
19846    		var rdo4 = '';
19847    	}
19848    	
19849    	rdo1 = '<li> <span class="commission-split-type">' + rdo1 + label1 + '</span> <span class="commission-split-text">' + text1 + '</li>';
19850    	rdo2 = '<li> <span class="commission-split-type">' + rdo2 + label2 + '</span> <span class="commission-split-text">' + text2 + '</li>';
19851    	rdo3 = '<li> <span class="commission-split-type">' + rdo3 + label3 + '</span> <span class="commission-split-text">' + text3 + '</li>';
19852    	
19853    	var htm = '<div id="pop-provider-commission-split"> <p>' + msg + '</p><ul>' + rdo0 + rdo1 + rdo2 + rdo3 + rdo4 + '</ul></div>';
19854    	var ojpop = GLO.Popup.Custom.openSimple(htm, 'Service Discount Commission', null, null, true);
19855    	var jpop = ojpop.getPopup().addClass('no-persist').addClass('pop-commission-split').attr('is_fee_fl', isFee);
19856    	
19857        GLO.Popup.Custom.singleButtonNew(jpop, btnLabel).find('> a').css({ "background-color": "rgb(0, 240, 0)", "color": "blue" });
19858        
19859        if (btnOther) {
19860        	jpop.append(btnOther);
19861        }
19862        
19863        ojpop.realign();
19864        
19865        if (isAllowEdit) {
19866	        if (split == 1) {
19867	        	jpop.find('#Split_Staff_cd').prop('checked', true);
19868	        } else if (split == 2) {
19869	        	jpop.find('#Split_Business_cd').prop('checked', true);
19870	        } else if (split == 4) {
19871	        	jpop.find('#Split_Custom_cd').prop('checked', true);
19872	        } else {
19873	        	jpop.find('#Split_Proportional_cd').prop('checked', true);
19874	        }
19875        }
19876        
19877        if (isAllowEdit && GLO.Provider.isManagerCheck('Commission Split')) {
19878        	//jpop.find('input[type="radio"]').change(GLO.Provider.Discount.saveCommissionSplit);
19879        	jpop.find('.btn').click(GLO.Provider.Discount.saveCommissionSplit);
19880    	} else {
19881    		jpop.find('input[type="radio"]').prop('disabled', true);
19882    	}
19883    }
19884    
19885    _conManageD.helpCommissionSplitSeeDefault = function(isFee) {
19886    	GLO.Popup.closeIfExist( $('#pop-provider-commission-split').closest('.glopop') );
19887    	GLO.Popup.closeIfExist( $('#manage-discount-popup').closest('.glopop') );
19888    	
19889    	var jbtn = $('#btnCommissionSplit');
19890    	
19891    	if (jbtn.length) {
19892	    	UI.highlight(jbtn, null, null, true);
19893	    	
19894	    	setTimeout(function() {
19895	    		$('#btnCommissionSplit > a').click();
19896	    	}, 2500);
19897	    	
19898	    	return;
19899    	} else if (isFee) {
19900    		var label = 'Add-On Fee';
19901    		var url = GLO.Link.WebsiteDomain + 'provider/manage/addon?open=commission-split';
19902    	} else {
19903    		var label = 'Discount';
19904    		var url = GLO.Link.WebsiteDomain + 'provider/manage/discount?open=commission-split';
19905    	}
19906    	
19907    	GLO.Popup.Processing.open('Loading ' + label + ' Report so you can set the default commission split for ' + label + '...', 'Loading ' + label + ' Report');
19908    	
19909    	setTimeout(function() {
19910    		document.location = url;
19911    	}, 200);
19912    }
19913    
19914    _conManageD.helpCommissionSplitByType = function() {
19915    	_conManageD.helpCommissionSplitCustom(true);
19916    }
19917    _conManageD.helpCommissionSplitCustom = function(isViewOnly) {
19918    	var htm = _helpCommissionSplitCustomHtm(isViewOnly);
19919    	
19920    	var h1b = '<b style="display: block; padding: 4px;">';
19921    	var h1 = h1b + 'Custom Commission Example</b>' + h1b + 'Service ' + _word + '</b>';
19922    	var ojpop = GLO.Popup.Info.openSimple(htm, h1, null, true);
19923    	
19924    	ojpop.getPopup().css({ "max-width": "900px" });
19925    	ojpop.realign();
19926    }
19927	function _helpCommissionSplitCustomHtm() {
19928		if (_isAddOnFee) {
19929    		var action = 'increased by an add-on fee';
19930    		var verb = 'added to';
19931    	} else {
19932    		var action = 'discounted';
19933    		var verb = 'taken from';
19934    	}
19935    	
19936    	var htmArrow = ' &#10140; ';
19937    	/*
19938    	var bstart = '<b style="letter-spacing: 0;">';
19939    	var bsplit = bstart + 'Commission Split = "Split"</b>';
19940    	var pSplit = '<p style="margin-bottom: 48px;">By default, when a service price is ' + action + ' the price after ' + _word + ' will receive the staff\'s normal commission percent, this is ' + bsplit + '</p>';
19941    	
19942    	var pPay = '<p>You can also pay a custom commission on the actual ' + _wordLong + ' amount</p>';
19943    	var pCustom = '<p>To pay a different commission on the action ' + _wordLong + ' amount, select ' + bstart + 'Commission Split = "Custom"</b></p>';
19944    	*/
19945    	
19946    	if (_isAddOnFee) {
19947    		var htmExample = _helpCommissionSplitCustomFeeHtm(htmArrow);
19948    	} else {
19949    		var htmExample = _helpCommissionSplitCustomDiscountHtm(htmArrow);
19950    	}
19951    	
19952    	//return '<div id="pop-help-custom-discount-split">' + pSplit + pPay + pCustom + htmExample + '</div>';
19953    	return '<div id="pop-help-custom-discount-split">' + htmExample + '</div>';
19954	}
19955    function _helpCommissionSplitCustomDiscountHtm(htmArrow) {
19956    	var h5 = '<h5 style="margin: 2px;">Example Scenario</h5>';
19957    	
19958    	var ex1 = '<li>Staff Commission = <b>60%</b></li>';
19959    	var ex2 = '<li>Service Price = <b>$110</b></li>';
19960    	var ex3 = '<li>Service Discount = <b>$10</b></li>';
19961    	var ex4 = '<li>Service Discount Commission = <b>Custom 40%</b></li>';
19962    	
19963    	var svcPrice = '<i style="letter-spacing: 0;">So the service price for the client is <b>$100</b></i>';
19964    	var htmFinalPrice = '<p style="margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid black; color: black;">' + htmArrow + svcPrice + '</p>';
19965    	var htmExample = h5 + '<ul style="margin-bottom: 0;">' + ex1 + ex2 + ex3 + ex4 + '</ul>' + htmFinalPrice;
19966    	
19967    	var smallCustom = '<small style="padding-left: 6px; letter-spacing: 0;">($10 * 40%)</small>';
19968    	var btotal = '<b style="display: inline-block; padding: 4px 8px; line-height: 1; font-size: larger; border-radius: 8px; background-color: rgb(0,240,0);">$64</b>';
19969    	
19970    	var li1 = '<li><b>Service Commission = $60</b> <small style="padding-left: 6px; letter-spacing: 0;">($100 * 60%)</small></li>';
19971    	var li2 = '<li><b>Discount Commission = $4</b> ' + smallCustom + '</li>';
19972    	var li3 = '<li>So total commission on the service ' + htmArrow + btotal + '</li>';
19973    	
19974    	return htmExample + '<ol>' + li1 + li2 + li3 + '</ol>';
19975    }
19976    function _helpCommissionSplitCustomFeeHtm(htmArrow) {
19977    	var h5 = '<h5 style="margin: 2px;">Example Scenario</h5>';
19978    	
19979    	var ex1 = '<li>Staff Commission = <b>60%</b></li>';
19980    	var ex2 = '<li>Service price = <b>$100</b></li>';
19981    	var ex3 = '<li>Service Add-On Fee = <b>$10</b></li>';
19982    	var ex4 = '<li>Service Discount Commission = <b>Custom 40%</b></li>';
19983    	
19984    	var svcPrice = '<i style="letter-spacing: 0;">So the service price for the client is <b>$110</b></i>';
19985    	var htmFinalPrice = '<p style="margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid black; color: black;">' + htmArrow + svcPrice + '</p>';
19986    	var htmExample = h5 + '<ul style="margin-bottom: 0;">' + ex1 + ex2 + ex3 + ex4 + '</ul>' + htmFinalPrice;
19987    	
19988    	var smallCustom = '<small style="padding-left: 6px; letter-spacing: 0;">($10 * 40%)</small>';
19989    	var btotal = '<b style="display: inline-block; padding: 4px 8px; line-height: 1; font-size: larger; border-radius: 8px; background-color: rgb(0,240,0);">$64</b>';
19990    	
19991    	var li1 = '<li><b>Service Commission = $60</b> <small style="padding-left: 6px; letter-spacing: 0;">($100 * 60%)</small></li>';
19992    	var li2 = '<li><b>Add-On Fee Commission = $4</b> ' + smallCustom + '</li>';
19993    	var li3 = '<li>So total commission on the service is ' + btotal + '</li>';
19994    	
19995    	return htmExample + '<ol>' + li1 + li2 + li3 + '</ol>';
19996    }
19997    
19998    function _isAllowSaveSplit() {
19999    	var jpop = $('.pop-commission-split').closest('.glopop');
20000        var split = jpop.find('input[name="Commission_Split_cd"]:checked').val();
20001        var pct = UTIL.coalesceInt(jpop.find('#Commission_Split_pct').val(), 0);
20002        
20003        if (split == 4 && (pct < 5 || pct > 95)) {
20004        	var msg = '<p>Custom Split percent must be between 5% - 95%</p>';
20005        	var isFee = UTIL.parseBool($('.pop-commission-split').attr('is_fee_fl'));
20006        	var htmArrow = '<b class="arrow-right">&#10140;</b>';
20007    		
20008        	if (pct < 5) {
20009        		if (isFee) {
20010        			msg += '<p>To have all the add-on fee go to the staff ' + htmArrow + ' select <b>Staff</b> as the <i>Service Discount Commission</i></p>';
20011        		} else {
20012        			msg += '<p>To have all the discount taken out of the staff commission ' + htmArrow + ' select <b>Staff</b> as the <i>Service Discount Commission</i></p>';
20013        		}
20014        	} else if (pct > 95) {
20015        		if (isFee) {
20016        			msg += '<p>To have all the add-on fee go to the business ' + htmArrow + ' select <b>Business</b> as the <i>Service Discount Commission</i></p>';
20017        		} else {
20018        			msg += '<p>To have all the discount taken out of the business ' + htmArrow + ' select <b>Business</b> as the <i>Service Discount Commission</i></p>';
20019        		}
20020        	}
20021        	
20022        	GLO.Popup.Warning.open(msg, 'Invalid Custom Split %');
20023        	return false;
20024        }
20025        
20026        return true;
20027    }
20028    
20029    _conManageD.saveCommissionSplit = function() {
20030    	if (!_isAllowSaveSplit()) {
20031    		return;
20032    	}
20033    	
20034    	var msg = '<p>Would you like to back date this change and re-calculate commissions?</p>';
20035    	var htm = $('<div id="pop-commission-split-start"> <h1 class="friendly-msg4">Commission Split Effective Date</h1>'
20036			+ '<div class="friendly-msg4" style="padding: 20px;">'
20037				+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
20038				+ msg
20039				+ '<label for="Commission_Start_dt">Start Date</label>'
20040				+ '<input id="Commission_Start_dt" type="text" style="width: 120px; padding-bottom: 1px; letter-spacing: 2px; text-align: center; font-weight: bold; color: #4F81BD;"/>'
20041			+ '</div> </div>');
20042    	
20043    	var fnSave = function () {
20044    		var dt = $('#pop-commission-split-start #Commission_Start_dt').val()
20045    		GLO.Provider.Discount.saveCommissionSplitConfirmed(dt);
20046    	}
20047    	
20048    	var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist');
20049    	
20050    	var dtToday = new Date().toGloDate();
20051    	jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-1M", maxDate: 0 });
20052    	jpop.find('#Commission_Start_dt').val(dtToday);
20053    	
20054    	jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" });
20055    	jpop.find('#Commission_Start_dt').blur();
20056    }
20057    _conManageD.saveCommissionSplitConfirmed = function(startDate) {
20058        if (!GLO.Provider.isManagerCheck('Commission Split')) {
20059        	return;
20060        }
20061        
20062        var jpop = $('.pop-commission-split');
20063        var isFee = jpop.attr('is_fee_fl');
20064        var split = jpop.find('input[name="Commission_Split_cd"]:checked').val();
20065        var pct = jpop.find('#Commission_Split_pct').val();
20066        
20067        var jpopConfirm = $('#pop-commission-split-start').closest('.glopop');
20068        var url = GLO.Link.Page.Provider.Home + 'manage/CommissionSplit';
20069        
20070        GLO.UI.Form.beginProcessing( jpop.closest('.glopop').find('.btn') );
20071        GLO.UI.Form.beginProcessing(jpopConfirm.find('.btnSave'));
20072
20073        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "startDate": startDate, "split": split, "percent": pct, "isfee": isFee } })
20074            .success(function(data, textStatus, jqXHR) {
20075                //GLO.UI.Form.resetProcessing();
20076                GLO.Popup.closeIfExist(jpop);
20077                GLO.Popup.closeIfExist(jpopConfirm);
20078                
20079                var btn = $('#btnCommissionSplit');
20080                btn.attr('commission_split_cd', split);
20081                
20082                if (split == 1) {
20083                	label = 'Staff';
20084                } else if (split == 2) {
20085                	label = 'Business';
20086                } else if (split == 4) {
20087                	label = 'Custom';
20088                } else {
20089                	label = 'Split';
20090                }
20091                
20092                btn.find('b').text(label);
20093                
20094                if (UTIL.parseBool(isFee)) {
20095                	GLO.Data.provider.commission_split_fee_cd = split;
20096                	GLO.Data.provider.commission_split_fee_pct = pct;
20097                } else {
20098                	GLO.Data.provider.commission_split_discount_cd = split;
20099                	GLO.Data.provider.commission_split_discount_pct = pct;
20100                }
20101            })
20102            .error(function(jqXHR, textStatus, errorThrown) {
20103                GLO.UI.Form.resetProcessing();
20104                GLO.Popup.Error.open('<p>Unable to change commission split at this time</p><p>Please try again later</p>', 'Update Commission Split');
20105            });
20106    }
20107    
20108    _conManageD.openHelpRules = function() {
20109    	var p1 = '<p>You can apply a ' + _word + ' to only tickets that have a specific combination of products and/or services by adding rules</p>';
20110    	var p2 = '<p>You can also require the ticket to match other rules like time of day, day of the week, payment method used, client tag, etc...</p>';
20111    	var p3 = '<p>For the ' + _word + ' to apply <b>all rules must match the ticket</b> <small style="letter-spacing: 0;">(for example, if a ' + _word + ' has 2 rules and only 1 rule matches a ticket then the ' + _word + ' cannot be used)</small></p>';
20112    	
20113    	var p4 = '<p>If any ' + _word + ' matches a ticket <i style="letter-spacing: 0;">(and the ' + _word + ' does not automatically apply)</i> then the ticket will include the option <b>(select discount or fee)</b></p>';
20114    	var img1 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit-appt-select-discount.png" style="max-width: 640px;"/>';
20115    	var p5 = '<p>When a ' + _word + ' is selected it will be displayed on the ticket</p>';
20116    	
20117    	if (_isAddOnFee) {
20118    		var img2 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit-appt-fee-selected.png" style="max-width: 640px;"/>';
20119    	} else {
20120    		var img2 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit-appt-discount-selected.png" style="max-width: 640px;"/>';
20121    	}
20122    	
20123    	var small6 = '<small style="letter-spacing: 0;">(and do not <b>Require</b> a promo code and leave the <b>Require Minimum Purchase</b> empty)</small>';
20124    	var p6 = '<p style="margin-bottom: 16px;">If you want to be able to apply a ' + _word + ' to any ticket, when creating the ' + _word + ' &#10140; leave the rule section empty ' + small6 + '</p>';
20125    	//var p7 = '<p></p>';
20126    	
20127    	if (_isAddOnFee) {
20128    		var img3 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/edit-discount-type.png" style="max-width: 640px;"/>';
20129    	} else {
20130    		var img3 = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/edit-add-on-fee-type.png" style="max-width: 640px;"/>';
20131    	}
20132    	
20133    	var htm = '<div id="pop-help-discount-rules">' + p1 + p2 + p3 + p4 + img1 + p5 + img2 + p6 + img3 + '</div>';
20134    	var ojpop = GLO.Popup.Info.openSimple(htm, _wordLong + ' Rules', null, true);
20135    	GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, false);
20136    }
20137    
20138    _conManageD.openPromoHelp = function() {
20139    	var imgOnlineBookingPromo = GLO.Data.cdnDirectory + 'image/faq/appointment/create/online-booking-create-appointment-with-note.png'; 	//image/faq/website/online-booking-create-appointment.png
20140    	var imgOnlineBooking = '<div style="text-align: center;"><img src="' + imgOnlineBookingPromo + '" style="max-width: 480px;"/></div>';
20141    	var imgApptNotePopup = '<div style="text-align: center;"><img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/edit/appointment-notes-popup.png" style="max-width: 420px;"/></div>';
20142    	
20143    	var chkRequired = '<input type="checkbox" id="example-require-promo" checked="checked" readonly="readonly" style="height: 18px; width: 18px; margin-top: -3px; margin-right: 2px; margin-left: 8px;">';
20144    	var lblRequired = '<b style="margin-right: 6px; font-size: 16px; color: #4F81BD;">Require</b></span>';
20145    	var htmRequired = 'if you check ' + chkRequired + lblRequired + ' <i style="letter-spacing: 0;">(next to the promo code field)</i>';
20146    	
20147    	var smallRequired = '<small style="display: block; margin-left: 24px; letter-spacing: 0;">(even staff must enter promo code to use discount on client ticket)</small>';
20148    	var htmArrow = '<b class="arrow-right">&#10140;</b>';
20149    	
20150    	var p1 = '<p>You can create a discount with a promo code for coupons and other specials</p>';
20151    	var p2 = '<p style="margin-top: 0;">Clients can enter the promo code in the special requests note field when they book online</p>';
20152    	var p3 = '<p style="margin-top: 32px;">Staff can also enter the promo code in the special requests note field or in the <b style="color: #4F81BD;">Appointment Notes</b> popup</p>';
20153    	var p4 = '';		// '<p style="margin-top: 32px;">When creating a discount, ' + htmRequired + ' then ' + htmArrow + ' promo code is <b>Required</b> to use the discount' + smallRequired + '</p>';
20154    	
20155    	var htm = '<div id="pop-help-discount-promo-code">' + p1 + p2 + imgOnlineBooking + p3 + imgApptNotePopup + p4 + '</div>';
20156    	var ojpop = GLO.Popup.Info.openSimple(htm, 'Discount Promo Code', null, true);
20157    	
20158    	GLO.Popup.Custom.singleButton(ojpop, 'Close');
20159    	GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, false);					//ojpop.getPopup().css({ "max-width": "900px" });
20160    }
20161    
20162    _conManageD.openHelpDayTime = function() {
20163    	var p1 = '<p>Can setup the ' + _wordLong + ' to only occur on specific day(s) of the week and/or time of day <i class="narrow-text">(based on the appointment start time)</i></p>';
20164    	
20165    	if (_isAddOnFee) {
20166    		var p2 = '<p>For example, if you want to charge more on the weekends</p>';
20167    		var p3 = '<p>You could also stay open an hour later - then just charge an extra fee for those late appointments</p>';
20168    	} else {
20169    		var p2 = '<p>For example, you could setup a <b>Happy Hour</b> where appointments are cheaper during slower times of the day</p>';
20170    		var p3 = '<p></p>';
20171    	}
20172    	
20173    	var htm = '<div id="pop-help-discount-daytime">' + p1 + p2 + p3 + '</div>';
20174    	var ojpop = GLO.Popup.Info.openSimple(htm, _word + ' by Day / Time', null, true);
20175    	GLO.Popup.Custom.singleButton(ojpop, 'Close');
20176    	//GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, false);
20177    }
20178    
20179    _conManageD.openHelpPayMethod = function(element) {
20180    	var p1 = '<p>Setup a ' + _wordLong + ' when a client pays with a specific payment method</p>';
20181    	
20182    	if (_isAddOnFee) {
20183    		var aMoreInfo = ' <b>&#10140;</b> <a onclick="GLO.Provider.Discount.displayConvenienceFeeOverview()">More Information</a>';
20184    		var p2 = '<p>For example, you can charge a <i>Convenience Fee</i> <small>(to re-imburse your credit card merchant fees)</small> when a client pays with a credit card' + aMoreInfo + '</p>';
20185    	} else {
20186    		var p2 = '<p>For example, you can offer a ' + _wordLong + ' when a client pays with cash</p>';
20187    	}
20188    	
20189    	var htm = '<div id="pop-help-discount-paymethod">' + p1 + p2 + '</div>';
20190    	var ojpop = GLO.Popup.Info.openSimple(htm, 'Payment Method ' + _word, null, true);
20191    	GLO.Popup.Custom.singleButton(ojpop, 'Close');
20192    }
20193    
20194    _conManageD.openHelpBirthday = function() {
20195    	var imgBdayHelloBar = '<div style="text-align: center;"><img src="' + GLO.Data.cdnDirectory + 'image/faq/appointment/hello-bar/hello-bar-birthday2.png" style="max-width: 480px;"/></div>';
20196    	var htmArrow = ' <b>&#10140;</b> ';
20197    	var aBdayEmail = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'message/Birthday?helloback=discount\'' + ', this, event, true)">Birthday Email Setup</a>';
20198    	
20199    	var p1 = '<p>When a client has a birthday <i>within a month of the current day</i>, then a bar is displayed at the top of the <b>Create Appointment</b> and <b>Edit Appointment</b>
20199 popup indicating that the client just recently had a birthday or has an upcoming birthday</p>';
20200    	var p2 = '<p>You can have a birthday discount automatically be given to a client on their birthday, within days of their birthday, or within weeks of their birthday</p>';
20201    	var p3 = '<p>You can also have <b>Happy Birhday Emails</b> automatically be sent to clients' + htmArrow + aBdayEmail + '</p>';
20202    	//var p4 = '<p></p>';
20203    	
20204    	var htm = '<div id="pop-help-discount-birthday">' + p1 + imgBdayHelloBar + p2 + p3 + '</div>';
20205    	var ojpop = GLO.Popup.Info.openSimple(htm, 'Birthday ' + _word, null, true);
20206    	GLO.Popup.Custom.singleButton(ojpop, 'Close');
20207    	//GLO.Popup.Custom.fixTallPopup(ojpop, 760, true, true);					//ojpop.getPopup().css({ "max-width": "900px" });
20208    }
20209    
20210    return _conManageD;
20211})();
20212
20213
20214GLO.Provider.Commission = (function() {
20215    function _conCommission() { }
20216    var _serviceCommissionTypeTimeout = null, _dtCommissionStart = null;
20217    var _minCommissionPopupHtm = null;
20218    
20219    _conCommission.initStaffService = function(minCommissionStart, maxCommissionStart) {
20220    	var jtbl = $('#commission-by-staff-service').find('.tablesorter');
20221    	UI.initTableSorter(jtbl);
20222    	
20223    	GLO.Staff.Filter.isReportFilterEasyQuery = true;
20224    	
20225    	jStaffFilter = $('#staff-filter');
20226    	jStaffFilter.find('#staff-filter-custom-group #staff-filter-custom').remove();
20227    	jStaffFilter.find('#staff-filter-sg').remove();
20228    	
20229    	var sfilter = GLO.Uri.query('sfilter');
20230    	
20231    	if (!UTIL.isEmpty(sfilter)) {
20232			jStaffFilter.val(sfilter);
20233		}
20234		
20235		jtbl.find('input').on('keyup', GLO.Provider.Commission.onChangeCommission);
20236		WIZ.page = 5;
20237		GLO.Info.helloBarCheck();
20238		
20239		if (UTIL.isDate(minCommissionStart) && UTIL.isDate(maxCommissionStart)) {
20240			if (new Date(minCommissionStart).toGloDate() == new Date(maxCommissionStart).toGloDate()) {
20241				_dtCommissionStart = new Date(maxCommissionStart).toGloDate();
20242			}
20243		}
20244    }
20245    
20246    _conCommission.initStaffServiceReport = function() {
20247    	GLO.Info.init();
20248    	_conCommission.initStaffService();
20249    	GLO.Report.enableFullPageCheck();
20250    	GLO.Report.initReportPassword();
20251    	
20252    	$('#commission-by-staff-service-more').find('#Overtime_Type_cd').change();
20253    	$('#commission-by-staff-service-more').find('.btnSave').addClass('hide');
20254    	
20255    	_conCommission.initPayrollSchedule();
20256    	_initEarly();
20257    	_initUrlActions();
20258    }
20259    function _initEarly() {
20260    	var jCommissionType = $('#service-commission-type-setup');
20261    	var earlyPercent = UTIL.coalesceMoney(jCommissionType.find('#Service_Commission_Type1_pct').val());
20262    	var hasStaffEarly = false;
20263    	var tdEarly = $('#report-commission-staff-list').find('tbody td.commission-column-staff-early-percent');
20264    	
20265    	for (var i=0; i < tdEarly.length; i++) {
20266    		var pct = UTIL.coalesceMoney(tdEarly.eq(i).text().replace('%', ''));
20267    		
20268    		if (pct > 0) {
20269    			hasStaffEarly = true;
20270    		}
20271    	}
20272    	
20273    	if (hasStaffEarly || earlyPercent > 0) {
20274    		jCommissionType.find('#early-commission-container2').removeClass('hide');
20275    	}
20276    }
20277    _conCommission.initPayrollSchedule = function() {
20278    	var jrange = $('#report-payroll-date-range');
20279		var dateRange = UTIL.coalesceInt(jrange.attr('value'));
20280		
20281		if (dateRange > 0) {
20282			if (dateRange == 10) {
20283				var label = 'Twice Monthly';
20284			} else if (dateRange == 20) {
20285				var label = 'Monthly';
20286			} else if (dateRange >= 30 && dateRange <= 39) {
20287				var label = 'Every 2 weeks';
20288				
20289				if (dateRange > 30) {
20290					var day = dateRange % 10;
20291					label += ' <span class="narrow-text">(starts ' + GLO.Provider.Advanced.Help.Calendar.getStartDayOfWeek(day, true) + ')</span>';
20292				}
20293			} else if (dateRange >= 40 && dateRange <= 49) {
20294				var label = 'Every week';
20295				
20296				if (dateRange > 40) {
20297					var day = dateRange % 10;
20298					label += ' <span class="narrow-text">(starts ' + GLO.Provider.Advanced.Help.Calendar.getStartDayOfWeek(day, true) + ')</span>';
20299				}
20300			}
20301			
20302			jrange.find('label').html(label);
20303		}
20304    }
20305    _conCommission.loadCommissionReport = function() {
20306    	var frm = $('#commission-report-password').attr('action', window.location.href).attr('method', 'post');
20307    	var pass = frm.find('#Report_Password_vc').val();
20308		
20309		if (UTIL.isEmpty(pass)) {
20310			var fnFocus = function() { frm.find('#Report_Password_vc').focus(); }
20311			GLO.Popup.Warning.open('Please Enter Password', 'Report Password Empty', fnFocus);
20312			return false;
20313        }
20314		
20315		GLO.Popup.Processing.open('Looking up password...', 'Processing...');
20316		
20317		setTimeout(function() {
20318			frm.submit();
20319		}, 100);
20320    }
20321    
20322    function _initUrlActions() {
20323    	var open = UTIL.cleanString(GLO.Uri.query('open')).toLowerCase();
20324    	var highlight = UTIL.cleanString(GLO.Uri.query('highlight'));
20325    	
20326    	if (open === 'help') {
20327			var page = UTIL.coalesceInt(GLO.Uri.hash('page'), 0);
20328			GLO.Provider.Commission.openReportHelp(page);
20329		} else if (open === 'wage') {
20330			var sid = UTIL.cleanString(GLO.Uri.hash('staff')).toLowerCase();
20331			
20332			if (sid > 1) {
20333				$('#report-commission-staff-list').find('tr[staff_id=' + sid + ']').find('.commission-column-hourly-wage a').click();
20334			} else {
20335				$('#report-commission-staff-list').find('tbody tr:first').find('.commission-column-hourly-wage a').click();
20336			}
20337		} else if (open === 'range' || open === 'date-range' || open === 'schedule') {
20338			$('#report-payroll-date-range #btnPayrollDateRange > a').click();
20339		}
20340		
20341		if (highlight.toLowerCase() === 'early') {
20342			var jelement = $('#service-commission-type-setup #Service_Commission_Type1_pct');
20343			UI.highlight(jelement, null, null, true);
20344			jelement.focus();
20345		} else if (highlight.toLowerCase() === 'normal') {
20346			var jelement = $('#service-commission-type-setup #Service_Commission_Type2_pct');
20347			UI.highlight(jelement, null, null, true);
20348			jelement.focus();
20349		} else if (!UTIL.isEmpty(highlight)) {
20350			var jhigh = $('#commission-by-staff-service .' + highlight);
20351			
20352			if (jhigh.length && !jhigh.is(':visible') && !$('body').hasClass('report-full-page')) {
20353				GLO.Report.enableFullPage(true);
20354			} else if (jhigh.length === 0) {
20355				jhigh = $('#' + highlight);
20356			}
20357			
20358			UI.highlight(jhigh, null, null, true);
20359		}
20360		
20361    	GLO.Info.displayHelloBarBackToAdvanced();
20362    }
20363    
20364    _conCommission.changeOvertimeType = function(element) {
20365    	if (!GLO.Report.allowReportChange()) { return false; }
20366    	
20367		var overtimeType = element.value;
20368		var jcontainer = $(element).closest('fieldset, div');
20369		
20370		$('#commission-setup-container-max-hr-per-week-label1').removeClass('hide');
20371		
20372		if (overtimeType == 10) {
20373			jcontainer.find('#commission-setup-container-max-hr-per-day').removeClass('hide');
20374			jcontainer.find('#commission-setup-container-max-hr-per-week').addClass('hide');
20375		} else if (overtimeType == 20) {
20376			jcontainer.find('#commission-setup-container-max-hr-per-day').addClass('hide');
20377			jcontainer.find('#commission-setup-container-max-hr-per-week').removeClass('hide');
20378		} else if (overtimeType == 30) {
20379			jcontainer.find('#commission-setup-container-max-hr-per-day').removeClass('hide');
20380			jcontainer.find('#commission-setup-container-max-hr-per-week').removeClass('hide').find('#commission-setup-container-max-hr-per-week-label1').addClass('hide');
20381		} else {
20382			jcontainer.find('#commission-setup-container-max-hr-per-day').addClass('hide');
20383			jcontainer.find('#commission-setup-container-max-hr-per-week').addClass('hide');
20384		}
20385    	
20386    	jcontainer.find('.btnSave').removeClass('hide');
20387    }
20388    _conCommission.changeCommissionSetup = function(element) {
20389    	if (!GLO.Report.allowReportChange()) { return false; }
20390    	
20391    	var jcontainer = $(element).closest('fieldset, div');
20392    	
20393    	if (jcontainer.hasClass('sub-container')) {
20394    		jcontainer = jcontainer.closest('fieldset, div');
20395    	}
20396    	
20397    	jcontainer.find('.btnSave').removeClass('hide');
20398    	return true;
20399    }
20400    _conCommission.changeServiceCommissionType = function(element, event) {
20401    	UI.verifyNumberInput(element);
20402    	clearTimeout(_serviceCommissionTypeTimeout);
20403    	
20404    	_serviceCommissionTypeTimeout = setTimeout(function() {
20405    		GLO.Provider.Commission.changeServiceCommissionType2(element);
20406    	}, 100);
20407    }
20408    _conCommission.changeMinHourly = function() {
20409    	if (!GLO.Report.allowReportChange()) { return; }
20410    	
20411    	var j = $('#min-hourly-rate');
20412    	j.find('.btnSave').removeClass('hide');
20413    }
20414    _conCommission.changeServiceCommissionType2 = function(element) {
20415    	var j = $('#service-commission-type-setup');
20416    	var jt1 = j.find('#Service_Commission_Type1_pct');
20417    	var jt2 = j.find('#Service_Commission_Type2_pct');
20418    	
20419    	j.find('.btnSave').removeClass('hide');
20420    	
20421    	if ($(element).attr('id') === 'Service_Commission_Type1_pct') {
20422    		var amt = 100 - UTIL.coalesceInt(jt1.val(), 0);
20423    		jt2.val(amt);
20424    	} else {
20425    		var amt = 100 - UTIL.coalesceInt(jt2.val(), 0);
20426    		jt1.val(amt);
20427    	}
20428    }
20429    _conCommission.onChangeCommission = function() {
20430    	$('.ss-commission-buttons .btnSave > a').addClass('unsaved');
20431    }
20432    _conCommission.saveServiceCommissionType = function() {
20433    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveCommissionType';
20434    	var j = $('#service-commission-type-setup');
20435    	var btnSave = j.find('.btnSave');
20436        
20437    	var t1 = j.find('#Service_Commission_Type1_pct').val();
20438    	var t2 = j.find('#Service_Commission_Type2_pct').val();
20439    	var up = j.find('#Early_Commission_Roundup_fl').prop('checked');
20440    	
20441        GLO.UI.Form.beginProcessing(btnSave);
20442        
20443        $.ajax({ type: "POST", url: uri, "cache": false, data: { "type1": t1, "type2": t2, "up": up } })
20444            .success(function(data, textStatus, jqXHR) {
20445                var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Service Commission Type Changed!</div></div>';
20446                new GLO.Popup.Success(htm);
20447                
20448                GLO.UI.Form.resetProcessing();
20449                btnSave.addClass('hide');
20450                
20451                if (t2 != 100) {
20452                	$('#service-commission-type-setup #early-commission-container2').removeClass('hide');
20453                }
20454		    })
20455            .error(function(jqXHR, textStatus, errorThrown) {
20456                GLO.Popup.Error('Unable to save.  Please try again');
20457                GLO.UI.Form.resetProcessing();
20458            });
20459    }
20460    _conCommission.saveMinHourly = function() {
20461    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveMinHourly';
20462    	var j = $('#min-hourly-rate');
20463    	var m1 = j.find('#Min_Hourly_Wage_mn').val();
20464    	var m2 = j.find('#Min_Hourly_Overtime_mn').val();
20465    	var btnSave = j.find('.btnSave');
20466        
20467        GLO.UI.Form.beginProcessing(btnSave);
20468        
20469        $.ajax({ type: "POST", url: uri, "cache": false, data: { "minHourly": m1, "minOvertime": m2 } })
20470            .success(function(data, textStatus, jqXHR) {
20471                var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Minimum Hourly Rates Changed!</div></div>';
20472                new GLO.Popup.Success(htm);
20473                
20474                GLO.UI.Form.resetProcessing();
20475                btnSave.addClass('hide');
20476		    })
20477            .error(function(jqXHR, textStatus, errorThrown) {
20478                GLO.Popup.Error('Unable to save.  Please try again');
20479                GLO.UI.Form.resetProcessing();
20480            });
20481    }
20482    _conCommission.saveOvertimeDefault = function() {
20483    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveOvertimeDefault';
20484    	var j = $('#commission-overtime-default');
20485    	var btnSave = j.find('.btnSave');
20486    	var day = '', week = '', ot = j.find('#Overtime_Type_cd').val();
20487    	var perHr = j.find('#Hourly_Overtime_mn').val();
20488    	
20489    	if (ot == 10 || ot == 30) {
20490    		day = j.find('#Overtime_Day_Max_sr').val();
20491    	}
20492    	
20493    	if (ot == 20 || ot == 30) {
20494    		var week = j.find('#Overtime_Week_Max_sr').val();
20495    	}
20496    	
20497        GLO.UI.Form.beginProcessing(btnSave);
20498        
20499        $.ajax({ type: "POST", url: uri, "cache": false, data: { "otype": ot, "day": day, "week": week, "hourly": perHr } })
20500            .success(function(data, textStatus, jqXHR) {
20501                var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Overtime Defaults Updated!</div></div>';
20502                new GLO.Popup.Success(htm);
20503                
20504                setTimeout(function() {
20505                	location.reload();
20506                }, 250);
20507                
20508                //GLO.UI.Form.resetProcessing();
20509                //btnSave.addClass('hide');
20510		    })
20511            .error(function(jqXHR, textStatus, errorThrown) {
20512                GLO.Popup.Error('Unable to save.  Please try again');
20513                GLO.UI.Form.resetProcessing();
20514            });
20515    }
20516    
20517    _conCommission.changePayrollLastPeriodEnd = function() {
20518    	var jpop = $('#pop-payroll-date-rate').closest('.glopop');
20519    	var dtLastEnd = jpop.find('#Last_Payroll_Period_End_dt').val();
20520    	
20521    	if (UTIL.isDate(dtLastEnd)) {
20522    		var dayOfWeek = new Date(dtLastEnd).getDay() + 1 + 1;				//getDay() is zero indexed, so add 1 to get day of the week for dtLastEnd; then add 1 for next day
20523    		
20524    		if (dayOfWeek == 8) {
20525    			dayOfWeek = 1;
20526    		}
20527    		
20528    		jpop.find('#payroll-date-range-days').find(':radio[value=' + dayOfWeek + ']').prop('checked', true);
20529    	}
20530    }
20531    _conCommission.openPayrollDateRange = function() {
20532    	GLO.Popup.closeIfExist($('#pop-save-payroll-history').closest('.glopop'));
20533    	
20534    	var aPayroll = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'report/payroll\', this, event, true)">Payroll report</a>';
20535    	var aTimesheet = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'report/timesheet\', this, event, true)">Timesheet report</a>';
20536    	//var aStaffGoals = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'report/StaffGoal\', this, event, true)">Staff Goals</a>';
20537    	var msg = '<p style="text-align: center; font-size: larger; font-weight: bold;">When do you pay payroll?</p>'
20538    			+ '<p>Conveniently sets the default date range on the ' + aTimesheet + ' and ' + aPayroll + '</p>';
20539    	
20540    	var dd = '<select id="Payroll_Date_Range_cd" name="Payroll_Date_Range_cd" onchange="GLO.Provider.Commission.changePayrollDateRange(this)">'
20541    			+ '<option value=""></option>'
20542    			+ '<option value="20">Once per month</option>'
20543    			+ '<option value="10">Twice per month</option>'
20544    			+ '<option value="30">Every 2 weeks</option>'
20545    			+ '<option value="40">Every week</option>'
20546    		+ '</select>';
20547    	
20548    	if (innerWidth > 900) {
20549    		var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
20550    	} else {
20551    		var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
20552    	}
20553    	
20554    	var htmDays = '<fieldset id="payroll-date-range-days" class="hide">'
20555    			 + '<legend>Payroll starts on</legend>'
20556    			 + '<label for="payroll-day-sun"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-sun" value="1"/>' + days[0] + '</label>'
20557    			 + '<label for="payroll-day-mon"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-mon" value="2"/>' + days[1] + '</label>'
20558    			 + '<label for="payroll-day-tue"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-tue" value="3"/>' + days[2] + '</label>'
20559    			 + '<label for="payroll-day-wed"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-wed" value="4"/>' + days[3] + '</label>'
20560    			 + '<label for="payroll-day-thu"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-thu" value="5"/>' + days[4] + '</label>'
20561    			 + '<label for="payroll-day-fri"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-fri" value="6"/>' + days[5] + '</label>'
20562    			 + '<label for="payroll-day-sat"> <input type="radio" name="Payroll_Date_Range_Days_sr" id="payroll-day-sat" value="7"/>' + days[6] + '</label>'
20563    		+ '</fieldset>';
20564    	
20565    	var htmTwicePerMonth = '<div id="payroll-date-range-twice-month">'
20566    			//+ '<p style="margin-bottom: 0;">Default Payroll Schedule</p>'
20567    			+ '<ul>'
20568    				+ '<li>1st - 15th</li>'
20569    				+ '<li>16th - end of month</li>'
20570    			+ '</ul>'
20571    		+ '</div>';
20572    	
20573    	var htmEveryOtherWeek = '<div id="payroll-date-range-every2weeks">'
20574    			+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
20575    			+ '<label for="Last_Payroll_Period_End_dt">Last Payroll Period End</label>'
20576    			+ '<input id="Last_Payroll_Period_End_dt" type="text" onchange="GLO.Provider.Commission.changePayrollLastPerio
20576dEnd()"/>'
20577    		+ '</div>';
20578    	
20579    	var htm = '<div id="pop-payroll-date-rate">' + msg + dd + htmDays + htmTwicePerMonth + htmEveryOtherWeek + '</div>';
20580		var jpop = GLO.Popup.Custom.openSimple(htm, 'Payroll Date Range', GLO.Provider.Commission.savePayrollDateRange);
20581		
20582		var jrange = $('#report-payroll-date-range');
20583		var startDay = 0, dateRange = jrange.attr('value'), lastPeriodEnd = jrange.attr('last_period_end_dt');
20584		
20585		if (dateRange > 0) {
20586			if ((dateRange > 30 && dateRange < 38) || (dateRange > 40 && dateRange < 48)) {
20587				startDay = UTIL.coalesceInt(dateRange % 10);
20588				dateRange = parseInt(dateRange/10) * 10;
20589			}
20590			
20591			jpop.find('#Payroll_Date_Range_cd').val(dateRange).change();
20592			
20593			if (startDay > 0) {
20594				jpop.find('input[name="Payroll_Date_Range_Days_sr"][value="' + startDay + '"]').prop('checked', true);
20595			}
20596		} else {
20597			jpop.find('#Payroll_Date_Range_cd').change();
20598		}
20599		
20600		jpop.find('#Last_Payroll_Period_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
20601																, numberOfMonths: UI.getDatepickerMonths(), minDate: "-1M", maxDate: 0 });
20602		
20603		if (UTIL.isDate(lastPeriodEnd)) {
20604			jpop.find('#Last_Payroll_Period_End_dt').val(lastPeriodEnd);
20605		}
20606    }
20607    _conCommission.changePayrollDateRange = function(dd) {
20608    	var jdays = $('#pop-payroll-date-rate #payroll-date-range-days').addClass('hide');
20609    	var jtwiceMonth  = $('#pop-payroll-date-rate #payroll-date-range-twice-month').addClass('hide');
20610    	var jEvery2Weeks = $('#pop-payroll-date-rate #payroll-date-range-every2weeks').addClass('hide');
20611    	
20612    	if (dd.value == 30 || dd.value == 40) {
20613    		jdays.removeClass('hide');
20614    		
20615    		if (dd.value == 30) {
20616    			jEvery2Weeks.removeClass('hide');
20617    		}
20618    	} else if (dd.value == 10) {
20619    		jtwiceMonth.removeClass('hide');
20620    	}
20621    }
20622    _conCommission.savePayrollDateRange = function() {
20623    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SavePayrollDateRange?range=';
20624    	var jpop = $('#pop-payroll-date-rate').closest('.glopop');
20625    	var range = UTIL.coalesceInt(jpop.find('#Payroll_Date_Range_cd').val());
20626    	var jdays = jpop.find('#payroll-date-range-days');
20627    	var lastPeriod = '', jLastPeriod = jpop.find('#Last_Payroll_Period_End_dt');
20628    	
20629    	if (jdays.is(':visible')) {
20630    		var day = UTIL.coalesceInt(jdays.find('input[name="Payroll_Date_Range_Days_sr"]:checked').val(), GLO.Data.firstWeekDay, 2);
20631    		range = UTIL.coalesceInt(range + day);
20632    	}
20633    	
20634    	if (jLastPeriod.is(':visible') && UTIL.isDate(jLastPeriod.val())) {
20635    		//dtLastPeriodEnd = new Date(lastPeriod);
20636    		lastPeriod = jLastPeriod.val();
20637    	}
20638    	
20639    	var btnSave = jpop.find('.btnSave');
20640        GLO.UI.Form.beginProcessing(btnSave);
20641        
20642        $.ajax({ type: "POST", url: uri, "cache": false, data: { "range": range, "lastPayrollEnd": lastPeriod } })
20643            .success(function(data, textStatus, jqXHR) {
20644                var htm = '<div><h1 class="friendly-msg2">Save Completed</h1><div class="friendly-msg2">Payroll Date Rate Changed!</div></div>';
20645                new GLO.Popup.Success(htm);
20646                
20647                $('#report-payroll-date-range').attr('value', range).attr('last_period_end_dt', lastPeriod);
20648                _conCommission.initPayrollSchedule();
20649                
20650                GLO.UI.Form.resetProcessing();
20651                GLO.Popup.close(jpop);
20652                
20653                if (GLO.Report.portalName == 'payroll') {
20654                	GLO.Popup.Processing.open('Loading Payroll Schedule Setting...', 'Re-Loading Payroll Report');
20655					
20656					setTimeout(function() {
20657                		location.reload();
20658                	}, 250)
20659                }
20660		    })
20661            .error(function(jqXHR, textStatus, errorThrown) {
20662                GLO.Popup.Error('Unable to save.  Please try again');
20663                GLO.UI.Form.resetProcessing();
20664            });
20665    }
20666    
20667    _conCommission.openSetAllServices = function() {
20668    	var numberInputType = "text";
20669        if (GLO.Info.isAndroid) { numberInputType = "number"; }
20670    	
20671    	var htm = $('<div id="pop-commission-set-all-services"> <h1 class="friendly-msg2">
20671Set Commission For All Services</h1>'
20672    				+ '<div class="friendly-msg2" style="min-width: 300px; margin-top: 12px;">'
20673						+ '<label for="All_Commission_mn">Commission</label>'
20674						+ '<input id="All_Commission_mn" type="' + numberInputType + '" style="width: 50px; letter-spacing: 1px;"/> %'
20675				+ '</div> </div>');
20676		
20677    	var ojpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.setAllServices);
20678    	var jpop = ojpop.getPopup().addClass('no-persist');
20679    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px" });
20680    }
20681    
20682    _conCommission.setAllServices = function(element) {
20683    	var jpop = $('#pop-commission-set-all-services').closest('.glopop');
20684    	var commission = jpop.find('#All_Commission_mn').val();
20685    	var jtr = $('#commission-by-staff-service').find('.tablesorter tbody').find('tr');
20686    	
20687    	for (var i=0; i < jtr.length; i++) {
20688    		jtr.eq(i).find('.svc-commission input').val(commission);
20689    	}
20690    	
20691    	GLO.Popup.close(jpop);
20692    	$('.ss-commission-buttons:first').find('.btnSave > a ').click();
20693    }
20694    
20695    function _upgradeToGoldPopup(msg) {
20696    	var msg = '<p>Upgrade to the Gold Package ' + msg + '</p>';
20697    	var btnLearn = '<span class="btnAdd" href="/provider/profile/6"><a>Learn More</a></span>';
20698    	var htm = '<div>' + msg + btnLearn + '</div>';
20699    	
20700    	GLO.Popup.Info.open(htm, 'Gold Package');
20701    }
20702    
20703    _conCommission.openEditMinAndFeeFromReport = function() {
20704    	if (!GLO.Report.allowReportChange()) { return; }
20705    	
20706    	var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr');
20707		var sid = tr.attr('staff_id');
20708		var sname = tr.find('.staff-column').text();
20709		var feeSupply = tr.attr('day_supply_fee_mn'), feeClean = tr.attr('day_clean_fee_mn');
20710		
20711		//var minWeekly = tr.find('.min-weekly-column').text().replace('$', '');
20712		//var minDays = tr.find('.required-days-column').text();
20713		var minWeek = UTIL.coalesceMoney(tr.attr('minWeek'));
20714		var minWeekDays = UTIL.coalesceInt(tr.attr('minWeekDays'));
20715		
20716		var minDay = UTIL.coalesceMoney(tr.attr('minDay'));
20717		var minDayHours = UTIL.coalesceInt(tr.attr('minDayHours'));
20718		var minDayHalfHours = UTIL.coalesceInt(tr.attr('minDayHalfHours'));
20719		
20720		var minHour = UTIL.coalesceMoney(tr.attr('minHour'));
20721		var minIncludeTip = UTIL.parseBool(tr.attr('minIncludeTip'));
20722    	var minOvertimePerHour = UTIL.coalesceMoney(tr.attr('minOvertimePerHour'));
20723		
20724		GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
20725		_conCommission.openEditMinAndFee2(sid, sname, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour);
20726    }
20727    _conCommission.openEditMinAndFee = function(element) {
20728    	if (!GLO.Report.allowReportChange()) { return; }
20729    	
20730    	var tr = $(element).closest('tr');
20731    	var sid = tr.attr('staff_id');
20732    	var sname = tr.find('td.commission-column-staff').text();
20733    	
20734    	var feeSupply = UTIL.coalesceMoney(tr.find('td.commission-column-daily-fee-supply').text().replace('$', ''));
20735    	var feeClean = UTIL.coalesceMoney(tr.find('td.commission-column-daily-fee-clean').text().replace('$', ''));
20736    	
20737    	var minWeek = UTIL.coalesceMoney(tr.attr('minWeek'));
20738		var minWeekDays = UTIL.coalesceInt(tr.attr('minWeekDays'));
20739		
20740		var minDay = UTIL.coalesceMoney(tr.attr('minDay'));
20741		var minDayHours = UTIL.coalesceInt(tr.attr('minDayHours'));
20742		var minDayHalfHours = UTIL.coalesceInt(tr.attr('minDayHalfHours'));
20743		
20744		var minHour = UTIL.coalesceMoney(tr.attr('minHour'));
20745		var minIncludeTip = UTIL.parseBool(tr.attr('minIncludeTip'));
20746    	var minOvertimePerHour = UTIL.coalesceMoney(tr.attr('minOvertimePerHour'));
20747		
20748    	_conCommission.openEditMinAndFee2(sid, sname, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour);
20749    }
20750    _conCommission.openEditMinAndFee2 = function(sid, sname, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour) {
20751    	if (_minCommissionPopupHtm === null) {
20752    		if (UTIL.coalesceMoney($('#service-commission-type-setup #Service_Commission_Type1_pct').val()) == 0) {
20753    			$('#pop-edit-min-and-fee').find('#pop-fee-early-normal').remove();
20754    		}
20755    		
20756    		_minCommissionPopupHtm = $('#pop-edit-min-and-fee').outerHTML();
20757    		$('#pop-edit-min-and-fee').remove();
20758    	}
20759    	
20760    	var jpop = GLO.Popup.Custom.openSimple(_minCommissionPopupHtm, sname, GLO.Provider.Commission.saveMinAn
20760dFees);
20761    	var jtabs = jpop.find('#min-period-tabs');
20762    	var jmin = null, jtab = jtabs.find('#min-period-tab-hourly');
20763    	
20764    	jpop.find('#Day_Supply_Fee_mn').val(UTIL.displayMoney(feeSupply, true));
20765    	jpop.find('#Day_Clean_Fee_mn').val(UTIL.displayMoney(feeClean, true));
20766    	jpop.find('#Edit_Staff_id').val(sid);
20767    	
20768    	if (minWeek > 0) {
20769    		jmin = jpop.find('#Min_Week_mn').val(UTIL.displayMoney(minWeek, true, false, true));
20770    		jtab = jtabs.find('#min-period-tab-weekly');
20771    	}
20772    	if (minDay > 0) {
20773    		jmin = jpop.find('#Min_Day_mn').val(UTIL.displayMoney(minDay, true, false, true));
20774    		jtab = jtabs.find('#min-period-tab-daily');
20775    	}
20776    	if (minHour > 0) {
20777    		jmin = jpop.find('#Min_Hour_mn').val(UTIL.displayMoney(minHour, true, false, true));
20778    		jtab = jtabs.find('#min-period-tab-hourly');
20779    	}
20780    	
20781    	if (minWeekDays) {
20782    		jpop.find('#Min_Days_Week_sr').val(minWeekDays);
20783    	}
20784    	if (minDayHours) {
20785    		jpop.find('#Min_Hours_Day_sr').val(minDayHours);
20786    	}
20787    	if (minDayHalfHours) {
20788    		jpop.find('#Min_Hours_Half_Day_sr').val(minDayHalfHours);
20789    	}
20790    	if (UTIL.parseBool(minIncludeTip)) {
20791    		jpop.find('#Min_Includes_Tip_fl').prop('checked', true);
20792		}
20793		
20794		if (minOvertimePerHour > 0) {
20795    		jpop.find('#Min_Overtime_mn').val(UTIL.displayMoney(minOvertimePerHour, true, false, true));
20796    	}
20797		
20798		jtab.find('>a').click();
20799    }
20800    _conCommission.displayMinPeriod = function(tabElement, periodName) {
20801    	var jmin = $('#pop-edit-min-data');
20802    	var jpop = jmin.closest('.glopop');
20803    	jpop.find(':focus').blur();
20804    	
20805    	jmin.removeClass('min-period-hour').removeClass('min-period-day').removeClass('min-period-week').addClass(periodName);
20806    	jpop.find('.min-period-tab.active-tab').removeClass('active-tab');
20807    	$(tabElement).closest('.min-period-tab').addClass('active-tab');
20808    	
20809    	if (!GLO.Info.isMobile(true)) {
20810    		jmin.find('.min-per-period-value:visible').focus();
20811    	}
20812    }
20813    
20814    function _getPayrollGuideLink(page, label) {
20815    	return '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="GLO.Provider.Commission.openReportHelp(' + page + ')">' + label + '</a>';
20816    }
20817    
20818    _conCommission.helpMinPeriod = function() {
20819    	var aMinHr = _getPayrollGuideLink(18, 'Hourly Minimum');
20820    	var aMinDay = _getPayrollGuideLink(19, 'Daily Minimum');
20821    	var aMinWk = _getPayrollGuideLink(20, 'Weekly Minimum');
20822    	
20823    	var arrow = '<b class="arrow-right">&#10140;</b>';
20824    	var plusMin = '<b class="narrow-text">+ Min column</b>';
20825    	//var aPayrollRpt = '<a onclick="SA.Menu.gotoReport(event, this, \'reports/payroll?highlight=plus-min-column&helloback=commission&openback=help&pageback=20\', true)">Payroll report</a>';
20826    	var aPayrollRpt = '<a onclick="GLO.Provider.Commission.openReportHelp(24)">Payroll report</a>';
20827    	
20828    	var msgHr = '<p>' + aMinHr + ': setup to guarantee staff make at least a minimum amount per hour</p>';
20829		var msgDay = '<p>' + aMinDay + ': can now set how many hours/day count as a full day or a half day</p>';
20830		var msgWk = '<p>' + aMinWk + ': gurantee staff make a minimum amount per week.  Require a minimum days worked per work to receive weekly minimum?  Can set how many hours/day count as a full day or a half day.</p>';
20831    	
20832    	var msg1 = '<p style="margin-top: 40px;">If the ' + aMinHr + ', ' + aMinDay + ', or ' + aMinWk + ' is used on a staff\'s payroll period then the ' + plusMin + ' is populated on the ' 
20833    			+ aPayrollRpt + ' with the amount that is added to the <b>Service Commission</b></p>';
20834		
20835		var msg2 = '<p style="margin-top: 24px;">If ' + aMinHr + ', ' + aMinDay + ', or ' + aMinWk + ' are all setup ' + arrow + ' then will use the highest minimum for each staff during the payroll period</p>';
20836		
20837		var htm = '<div id="pop-help-min-commission">' + msgHr + msgDay + msgWk + msg1 + msg2 + '</div>';
20838		GLO.Popup.Info.openSimple(htm, 'Staff Minimums').css({ "max-width": "900px" });
20839    }
20840    _conCommission.changeMinPeriod = function(radio) {
20841    	var jmin = $('#pop-edit-min-data').removeClass('min-period-hour').removeClass('min-period-day').removeClass('min-period-week');
20842    	//jmin.find('.pop-edit-field').addClass('hide');
20843    	
20844    	if (radio.value == 'hour') {
20845    		jmin.addClass('min-period-hour'); 	//jmin.find('.pop-min-period-hour').removeClass('hide');
20846    	} else if (radio.value == 'day') {
20847    		jmin.addClass('min-period-day');
20848    	} else if (radio.value == 'week') {
20849    		jmin.addClass('min-period-week');
20850    	}
20851    	
20852    	if (!GLO.Info.isMobile(true)) {
20853    		jmin.find('.min-per-period-value:visible').focus();
20854    	}
20855    }
20856    function _isValidMin(jpop, minWeek, minDay, minDayHours, minWeekDays) {
20857    	if ((minDay > 0 || minWeek > 0) && UTIL.coalesceInt(minDayHours, 0) == 0) {
20858    		var fn = function() { 
20859    			var jday = jpop.find('#Min_Hours_Day_sr').focus();
20860    			UI.highlight(jday);
20861    		};
20862    		
20863    		GLO.Popup.Warning.open('Please set how many hours are required in a day (minimum must be 1 or more)', 'Min Hours for a Full Day', fn);
20864    		return false;
20865    	} else if (minWeek > 0 && UTIL.coalesceInt(minWeekDays, 0) == 0) {
20866    		var fn = function() { 
20867    			var jweek = jpop.find('#Min_Days_Week_sr').focus();
20868    			UI.highlight(jweek);
20869    		};
20870    		
20871    		GLO.Popup.Warning.open('Please set how many days are required in a week (minimum must be 1 or more)', 'Min Days for a Full Week', fn);
20872    		return false;
20873    	}
20874    	
20875    	return true;
20876    }
20877    _conCommission.saveMinAndFees = function() {
20878    	var jpop = $('#pop-edit-min-and-fee').closest('.glopop');
20879    	var sid = jpop.find('#Edit_Staff_id').val();
20880    	
20881    	var feeSupply = jpop.find('#Day_Supply_Fee_mn').val().replace(',', '');
20882    	var feeClean = jpop.find('#Day_Clean_Fee_mn').val().replace(',', '');
20883    	//var minOption = jpop.find('input[name="Min_Period_cd"]:checked').val();
20884    	
20885    	var minWeek = jpop.find('#Min_Week_mn').val().replace(',', '');
20886    	var minWeekDays = jpop.find('#Min_Days_Week_sr').val();
20887    	//var minDayHours = jpop.find('#Min_Hours_Day_sr').val();
20888    	
20889    	var minDay = jpop.find('#Min_Day_mn').val().replace(',', '');
20890    	var minDayHours = jpop.find('#Min_Hours_Day_sr').val();
20891    	var minDayHalfHours = jpop.find('#Min_Hours_Half_Day_sr').val();
20892    	
20893    	var minHour = jpop.find('#Min_Hour_mn').val().replace(',', '');
20894    	var minOvertimePerHour = jpop.find('#Min_Overtime_mn').val();
20895    	var minIncludeTip = jpop.find('#Min_Includes_Tip_fl').val();
20896    	
20897    	var htm = $('<div id="pop-edit-start"> <h1 class="friendly-msg4">Effective Start Date</h1>'
20898    			+ '<div class="friendly-msg4" style="padding: 20px;">'
20899    				+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
20900    				+ '<label for="Min_Fee_Start_dt">Start Date</label>'
20901    				+ '<input id="Min_Fee_Start_dt" type="text" style="width: 110px; letter-spacing: 1px; text-align: center;"/>'
20902    			+ '</div> </div>');
20903    	
20904    	if (!_isValidMin(jpop, minWeek, minDay, minDayHours, minWeekDays)) {
20905    		return;
20906    	}
20907    	
20908    	var fnSave = function () {
20909    		var dt = $('#pop-edit-start #Min_Fee_Start_dt').val()
20910    		GLO.Provider.Commission.saveMinAndFeesConfirmed(sid, dt, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour);
20911    	};
20912    	
20913    	var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist');
20914    	
20915    	var dtToday = new Date().toGloDate();
20916    	jpop.find('#Min_Fee_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 });
20917    	jpop.find('#Min_Fee_Start_dt').val(dtToday);
20918    	
20919    	jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" });
20920    	jpop.find('#Min_Fee_Start_dt').blur();
20921	}
20922    _conCommission.saveMinAndFeesConfirmed = function(sid, confirmDate, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour) {
20923    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveMinAndFees?sid=' + sid;
20924    	
20925        var jdata = { "startDate": confirmDate, "feeSupply": feeSupply, "feeClean": feeClean
20926        				, "minWeek": minWeek, "minWeekDays": minWeekDays
20927        				, "minDay": minDay, "minDayHours": minDayHours, "minDayHalfHours": minDayHalfHours
20928        				, "minHour": minHour, "minIncludeTip": minIncludeTip, "minOvertime": minOvertimePerHour };
20929        
20930        var jpop1 = $('#pop-edit-start').closest('.glopop');
20931        var jpop2 = $('#pop-edit-min-and-fee').closest('.glopop');
20932        
20933        GLO.UI.Form.beginProcessing( jpop1.find('.btnSave') );
20934        GLO.UI.Form.beginProcessing( jpop2.find('.btnSave') );
20935        
20936        $.ajax({ type: "POST", url: uri, "cache": false, data: jdata })
20937            .success(function(data, textStatus, jqXHR) {
20938                GLO.Popup.close(jpop1);
20939                GLO.Popup.close(jpop2);
20940                GLO.Popup.Success.open('Weekly Minimum and Fees Updated', 'Save Successful');
20941                
20942                if ($('#bd #report-payroll').length) {
20943                	GLO.Report.Payroll.search();
20944                } else {
20945                	_setMinAndFees(sid, confirmDate, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour);
20946                }
20947		    })
20948            .error(function(jqXHR, textStatus, errorThrown) {
20949                GLO.Popup.Error.open('Unable to save<br/><br/>Please try again', 'Save Un-Successful');
20950                GLO.UI.Form.resetProcessing();
20951            });
20952    }
20953    function _setMinAndFees(sid, confirmDate, feeSupply, feeClean, minWeek, minWeekDays, minDay, minDayHours, minDayHalfHours, minHour, minIncludeTip, minOvertimePerHour) {
20954    	var tr = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]');
20955    	tr.attr('minWeek', minWeek).attr('minWeekDays', minWeekDays);
20956    	tr.attr('minDay', minDay).attr('minDayHours', minDayHours).attr('minDayHalfHours', minDayHalfHours);
20957    	tr.attr('minHour', minHour).attr('minIncludeTip', minIncludeTip).attr('minOvertimePerHour', minOvertimePerHour);
20958    	
20959    	feeSupply = UTIL.displayMoney(feeSupply);
20960    	feeClean = UTIL.displayMoney(feeClean);
20961    	
20962    	if (minWeek > 0) {
20963	    	var minText = UTIL.displayMoney(minWeek, false, false, true) + '/week';
20964	    	
20965	    	if (minWeekDays > 0) {
20966	    		minText += '<small>' + minWeekDays + ' days</small>';
20967	    	}
20968    	} else if (minDay > 0) {
20969    		var minText = UTIL.displayMoney(minDay, false, false, true) + '/day';
20970    		
20971    		if (minDayHalfHours > 0 && minDayHours > 0) {
20972    			minText += '<small>' + minDayHours + ' hrs / ' + minDayHalfHours + ' hrs</small>';
20973	    	} else if (minDayHours > 0) {
20974	    		minText += '<small>' + minDayHours + ' hours</small>';
20975	    	}
20976    	} else if (minHour > 0) {
20977    		var minText = UTIL.displayMoney(minHour, false, false, true) + '/hour';
20978    		
20979    		if (UTIL.parseBool(minIncludeTip)) {
20980    			minText += '<small class="narrow-text">include Tips</small>';
20981    		}
20982    		
20983    		if (minOvertimePerHour > 0) {
20984    			minText += '<small class="narrow-text">Min Overtime = ' + UTIL.displayMoney(minOvertimePerHour) + '/hr</small>';
20985    		}
20986    	} else {
20987    		var minText = 'none';
20988    	}
20989    	
20990    	tr.find('td.commission-column-min').css({ "color": "rgb(0, 200, 80)" }).html(minText);
20991    	//tr.find('td.commission-column-min-days').css({ "color": "rgb(0, 200, 80)" }).text(minDays);
20992    	tr.find('td.commission-column-daily-fee-supply').css({ "color": "rgb(0, 200, 80)" }).text(feeSupply);
20993    	tr.find('td.commission-column-daily-fee-clean').css({ "color": "rgb(0, 200, 80)" }).text(feeClean);
20994    }
20995    
20996    _conCommission.openEditStaffEarlyPercent = function(element) {
20997    	if (!GLO.Report.allowReportChange()) { return; }
20998    	
20999    	var tr = $(element).closest('tr');
21000    	var sid = tr.attr('staff_id');
21001    	var sname = tr.find('.commission-column-staff').text();
21002    	var earlyPercent = UTIL.coalesceInt($.trim(tr.find('td.commission-column-staff-early-percent').text()).replace('%', ''), 0);
21003    	
21004    	if (earlyPercent == 0) { earlyPercent = ''; }
21005    	
21006    	_openEditStaffEarlyPercent2(sid, sname, earlyPercent);
21007    }
21008    function _openEditStaffEarlyPercent2(sid, sname, earlyPercent) {
21009    	var inputStyle = 'width: 50px; letter-spacing: 1px; text-align: center; font-size: 18px; font-weight: bold;';
21010    	
21011    	var ex1 = '<i class="narrow-text" style="display: inline;">(and then the remaining amount normally)</i>';
21012    	var p1 = '<p style="padding-bottom: 16px; line-height: 1.4; font-size: 16px; opacity: .8;">';
21013    	var p2 = '<p style="margin-top: 40px; padding-bottom: 8px; line-height: 1.4; font-size: 16px; opacity: .8;">';
21014    	var msg1 = p1 + 'You can pay this staff a percent of the service commission + adjusted amount early ' + ex1 + '</p>';
21015    	
21016    	//var iBottom = '<i class="narrow-text" style="display: inline;">(if early or normal amount is less than $10, then rounded to the nearest dollar)</i>';
21017    	var msgBottom = ''; //var msgBottom = p2 + 'Starting July 1, 2025 early commission rounded up to the nearest $10 ' + iBottom + '</p>';
21018    	
21019    	var inputHide = '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>';
21020    	var label = '<label for="Service_Commission_Early_pct">Staff Early Commission</label>';
21021    	var inputPct = '<input id="Service_Commission_Early_pct" type="text" value="' + earlyPercent + '" onkeypress="UI.numberOnly(event, false, true)" pattern="[0-9]*" maxlength="3" style="' + inputStyle + '"/>';
21022    	var pctSymbol = '<b class="display-percent" style="padding-left: 1px;">%</b>';
21023    	var htmInput = '<div>' + inputHide + label + inputPct + pctSymbol + '</div>';
21024    	
21025    	var htm = '<div id="pop-edit-staff-early-percent" style="max-width: 640px; padding-top: 0; padding-left: 12px; padding-right 6px; padding-bottom: 16px;">'
21026					+ msg1 + htmInput + msgBottom
21027				+ '</div>';
21028		
21029		var ojpop = GLO.Popup.Custom.openSimple(htm, sname, GLO.Provider.Commission.saveStaffEarlyPercent);
21030    }
21031    _conCommission.saveStaffEarlyPercent = function() {
21032    	var jpop = $('#pop-edit-staff-early-percent').closest('.glopop');
21033    	var sid = jpop.find('#Edit_Staff_id').val();
21034    	var earlyPercent = jpop.find('#Service_Commission_Early_pct').val();
21035    	
21036    	//var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>';
21037    	var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveStaffServiceCommissionEarly?staff=' + sid + '&earlyPercent=' + earlyPercent;
21038    	
21039    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
21040    	
21041    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
21042            .success(function(data, textStatus, jqXHR) {
21043                GLO.Popup.close(jpop);
21044                
21045                if (earlyPercent > 0) {
21046                	earlyPercent = UTIL.roundNumber(UTIL.coalesceMoney(earlyPercent, 0), 2) + '%';
21047                } else {
21048                	earlyPercent = '<small>use default</small>';
21049                }
21050                
21051                $('#report-commission-staff-list tbody tr[staff_id="' + sid + '"]').find('td.commission-column-staff-early-percent').html(earlyPercent);
21052            })
21053            .error(function(jqXHR, textStatus, errorThrown) {
21054                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
21055            });
21056    }
21057    
21058    _conCommission.openEditStaffTipPercent = function(element) {
21059    	if (!GLO.Report.allowReportChange()) { return; }
21060    	
21061    	var tr = $(element).closest('tr');
21062    	var sid = tr.attr('staff_id');
21063    	var sname = tr.find('.commission-column-staff').text();
21064    	
21065    	var td = tr.find('td.commission-column-staff-tip-percent');
21066    	var tipCommission = UTIL.coalesceInt(td.attr('tip_pct'), 0);
21067    	var tipCommissionCredit = UTIL.coalesceInt(td.attr('tip_credit_pct'), 0);
21068    	
21069    	if (tipCommission == 0) { tipCommission = ''; }
21070    	if (tipCommissionCredit == 0) { tipCommissionCredit = ''; }
21071    	
21072    	_openEditStaffTipPercent2(sid, sname, tipCommission, tipCommissionCredit);
21073    }
21074    function _openEditStaffTipPercent2(sid, sname, tipCommission, tipCommissionCredit) {
21075    	var ex1 = '<i class="narrow-text" style="display: inline;">(like more commission paid early, higher commission percent, or a daily/weekly minimum)</i>';
21076    	var ex2 = '<i class="narrow-text" style="display: inline;">(for example paying 97% or 98% of tips paid with a card)</i>';
21077    	
21078    	var p1 = '<p style="line-height: 1.4; font-size: 14px; opacity: .8;">';
21079    	var msg1 = p1 + 'Sometimes staff have special negotiated commission ' + ex1 + ' so to offset this, you can pay staff a percent of tips</p>';
21080    	var msg2 = p1 + 'To offset credit card charges you can pay staff a percent of tips paid with a card ' + ex2 + '</p>';
21081    	var msg3 = '<p></p>';
21082    	
21083    	var htm = '<div id="pop-edit-staff-tip-percent" style="max-width: 720px; padding: 8px; padding-top: 0; padding-left: 16px;">'
21084					+ '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>'
21085					+ msg1 + msg2 + msg3
21086					
21087					+ '<div id="pop-edit-staff-tip-percent-all">'
21088					+ '<label for="Tip_Commission_pct" style="margin-right: 69px;">Tip Commission</label>'
21089    				+ '<input id="Tip_Commission_pct" type="text" value="' + tipCommission + '" onkeypress="UI.numberOnly(event, false, true)" pattern="[0-9]*" maxlength="3"/>'
21090    				+ '<b class="display-percent" style="padding-left: 1px;">%</b>'
21091    				+ '</div>'
21092    				
21093    				+ '<div id="pop-edit-staff-tip-percent-credit" title="Tip commission percentage when client pays with credit or debit card">'
21094    				+ '<label for="Tip_Commission_Credit_pct">Tip Commission Credit</label>'
21095    				+ '<input id="Tip_Commission_Credit_pct" type="text" value="' + tipCommissionCredit + '" onkeypress="UI.numberOnly(event, false, true)" pattern="[0-9]*" maxlength="3"/>'
21096    				+ '<b class="display-percent" style="padding-left: 1px;">%</b>'
21097    				+ '</div>'
21098				+ '</div>';
21099		
21100		var ojpop = GLO.Popup.Custom.openSimple(htm, sname, GLO.Provider.Commission.saveStaffTipPercent);
21101    }
21102    _conCommission.saveStaffTipPercent = function() {
21103    	var jpop = $('#pop-edit-staff-tip-percent').closest('.glopop');
21104    	var sid = jpop.find('#Edit_Staff_id').val();
21105    	var tipCommission = jpop.find('#Tip_Commission_pct').val();
21106    	var tipCommissionCredit = jpop.find('#Tip_Commission_Credit_pct').val();
21107    	
21108    	//var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>';
21109    	var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveStaffTipCommission?staff=' + sid + '&commission=' + tipCommission + '&commissionCredit=' + tipCommissionCredit;
21110    	
21111    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
21112    	
21113    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
21114            .success(function(data, textStatus, jqXHR) {
21115                GLO.Popup.close(jpop);
21116                
21117                
21118                var td = $('#report-commission-staff-list tbody tr[staff_id="' + sid + '"]').find('td.commission-column-staff-tip-percent');
21119                td.attr('tip_pct', tipCommission).attr('tip_credit_pct', tipCommissionCredit);
21120                td.html(data);
21121            })
21122            .error(function(jqXHR, textStatus, errorThrown) {
21123                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
21124            });
21125    }
21126    
21127    _conCommission.openEditTaxWithheld = function(element) {
21128    	if (!GLO.Report.allowReportChange()) { return; }
21129    	
21130    	var tr = $(element).closest('tr');
21131    	var sid = tr.attr('staff_id');
21132    	var sname = tr.find('.commission-column-staff').text();
21133    	var withheld = $.trim(tr.find('td.commission-column-tax-withheld').text()).replace('%', '');
21134    	
21135    	if (withheld == 0) { withheld = ''; }
21136    	
21137    	_conCommission.openEditTaxWithheld2(sid, sname, withheld);
21138    }
21139    _conCommission.openEditTaxWithheld2 = function(sid, sname, withheld) {
21140    	var htm = '<div id="pop-edit-tax-withheld">'
21141					+ '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>'
21142					+ '<label for="Tax_Withheld_pct">Tax Withheld</label>'
21143    				+ '<input id="Tax_Withheld_pct" type="text" value="' + withheld + '" onkeypress="UI.numberOnly(event)" pattern="[0-9]*" maxlength="5"/>'
21144    				+ '<b class="display-percent" style="padding-left: 1px;">%</b>'
21145				+ '</div>';
21146		
21147		var ojpop = GLO.Popup.Custom.openSimple(htm, sname, GLO.Provider.Commission.saveTaxWithheld);
21148    }
21149    _conCommission.saveTaxWithheld = function() {
21150    	var jpop = $('#pop-edit-tax-withheld').closest('.glopop');
21151    	var sid = jpop.find('#Edit_Staff_id').val();
21152    	var withheld = jpop.find('#Tax_Withheld_pct').val();
21153    	
21154    	//var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>';
21155    	var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveTaxWithheld?sid=' + sid + '&withheld=' + withheld;
21156    	
21157    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
21158    	
21159    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
21160            .success(function(data, textStatus, jqXHR) {
21161                GLO.Popup.close(jpop);
21162                withheld = UTIL.roundNumber(UTIL.coalesceMoney(withheld, 0), 2) + '%';
21163                $('#report-commission-staff-list tbody tr[staff_id="' + sid + '"]').find('td.commission-column-tax-withheld').text(withheld);
21164            })
21165            .error(function(jqXHR, textStatus, errorThrown) {
21166                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
21167            });
21168    }
21169    
21170    _conCommission.openEditWage = function(element) {
21171    	if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10) {
21172    		return _upgradeToGoldPopup('to Enable Clock/In Out, Timesheet Management, and track wages for hourly staff');
21173    	} else if (!GLO.Report.allowReportChange()) {
21174    		return;
21175    	}
21176    	
21177    	var jwage = $('#ss-commission-hourly-wage').find('#Hourly_Wage_mn');
21178    	
21179    	if (jwage.length > 0) {
21180    		var wage = jwage.text();
21181    		var sid = $('#commission-by-staff-service').attr('staff_id');
21182    		var sname = $('#commission-by-staff-service h2').attr('staff_name_vc');
21183    	} else {
21184    		var jelement = $(element);
21185    		var tr = jelement.closest('tr');
21186    		
21187    		var wage = jelement.text();
21188    		var sid = tr.attr('staff_id');
21189    		var sname = tr.find('.commission-column-staff').text();
21190    	}
21191    	
21192    	_conCommission.openEditWage2(sid, sname, wage);
21193    }
21194    _conCommission.openEditWageOnPayroll = function() {
21195    	var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr');
21196    	var sid = tr.attr('staff_id');
21197		var sname = tr.find('.staff-column').text();
21198		var wage = tr.find('.hourly-rate-column').text().replace('$', '');
21199		
21200		GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
21201		_conCommission.openEditWage2(sid, sname, wage);
21202    }
21203    _conCommission.openEditWage2 = function(sid, sname, wage, password) {
21204    	if (!GLO.Report.allowReportChange()) { return; }
21205    	
21206    	if (UTIL.isEmpty(sid)) {
21207    		sid = $('#simplemodal-container').find('#Staff_id').val();
21208    	}
21209    	
21210    	if (innerWidth > 600) {
21211    		var minWidth = '400px';
21212    	} else {
21213    		var minWidth = '300px';
21214    	}
21215    	
21216    	var throbber = '<div id="pop-wage-throbber" style="margin-top: 16px;"> <div id="edit-wage-display">' + wage + '</div> <div>' + GLO.Report.Template2.getBlueThrobber() + '</div></div>';
21217    	var htm = '<div id="pop-edit-wage" style="min-width: ' + minWidth + '; margin-bottom: 16px;">'
21218					+ '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>'
21219					+ '<div style="margin-bottom: 12px;"><label for="Edit_Hourly_Wage_mn" style="font-weight: bold; font-size: larger; color: #4F81BD;">' + sname + '</label></div>'
21220					+ throbber
21221				+ '</div>';
21222		
21223		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Edit Hourly Wage', GLO.Provider.Commission.saveEditWage, null, true);
21224		var jpop = ojpop.getPopup();
21225    	var url = GLO.Link.WebsiteDomain + 'provider/manage/GetWage?sid=' + sid;
21226    	
21227    	var jqxhr = $.ajax({ "type": "POST", "url": url, "cache": false, "data": { "report_password_vc": password } })
21228            .success(function(data, textStatus, jqXHR) {
21229                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
21230                	jpop.find('.btnSave').remove();
21231                	jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "font-weight": "bold" });
21232                }
21233                
21234                jpop.find('#pop-wage-throbber').replaceWith(data);
21235                jpop.find('#Staff_Overtime_Start_dt').datepicker({ minDate: "-3M", maxDate: "+1M", calculateWeek: UTIL.datePickerCalculateWeek });
21236                jpop.find('#Report_Password_vc').focus();
21237	            ojpop.realign();
21238            })
21239            .error(function(jqXHR, textStatus, errorThrown) {
21240                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
21241            });
21242    }
21243    
21244    _conCommission.openEditCommissionOnPayroll = function() {				//= called by Payroll Report
21245    	var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr');
21246    	
21247		var sid = tr.attr('staff_id');
21248		var sname = tr.find('.staff-column').text();
21249		
21250		var commission = tr.find('.commission-percent-column').text().replace('%', '');
21251		var hasDiffCommissionPerService = (commission.indexOf('-') !== -1);
21252		
21253		GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
21254		
21255		_conCommission.openEditCommission2(sid, sname, commission, null, event, hasDiffCommissionPerService);
21256	}
21257    _conCommission.openEditCommission = function(element, event, hasDiffCommissionPerService) {				//= called by Commission Report
21258    	if (!GLO.Report.allowReportChange()) { return; }
21259    	
21260    	var jelement = $(element);
21261		var tr = jelement.closest('tr');
21262		
21263		var commission = jelement.text().replace('%', '').replace('none', '');
21264		var sid = tr.attr('staff_id');
21265		var sname = tr.find('.commission-column-staff').text();
21266		var currentCommissionStartDescription = tr.find('td.svc-price').attr('title');
21267		
21268		_conCommission.openEditCommission2(sid, sname, commission, jelement, event, hasDiffCommissionPerService, currentCommissionStartDescription);
21269	}
21270	
21271	_conCommission.openEditCommission2 = function(sid, sname, commission, jelement, event, hasDiffCommissionPerService, currentCommissionStartDescription) {
21272    	var uri = '', setByService = '', numberInputType = "text";
21273    	
21274        if (GLO.Info.isAndroid) { numberInputType = "number"; }
21275    	
21276    	if (GLO.Info.isGold()) {
21277    		uri = GLO.Link.WebsiteDomain + 'provider/manage/CommissionByStaffService?sfilter=' + sid;
21278    		setByService = '<div style="margin: 20px; margin-bottom: 32px; text-align: center;"> <a href="' + uri + '">Set By Service</a> </div>';
21279    		
21280    		if (hasDiffCommissionPerService) {
21281	    		UI.openLink(uri, event, jelement)
21282	    		return;
21283	    	}
21284    	}
21285    	
21286    	if (!UTIL.isEmpty(currentCommissionStartDescription)) {
21287    		var css = 'margin: 0 6px 24px; text-align: center; letter-spacing: 0; font-family: arial; font-stretch: condensed;';
21288    		currentCommissionStartDescription = '<div style="' + css + '">' + currentCommissionStartDescription + '</div>';
21289    	} else {
21290    		currentCommissionStartDescription = '';
21291    	}
21292    	
21293    	var htm = $('<div id="pop-edit-commission"> <h1 class="friendly-msg2">Edit Commission</h1> <div class="friendly-msg2" style="min-width: 300px;">'
21294					+ '<label for="Edit_Commission_pct" style="display: block; margin: 8px; margin-bottom: 2px; text-align: center;">' + sname + ' Commission</label>'
21295					+ '<input id="Edit_Commission_pct" original_commission_pct="' + commission + '" type="' + numberInputType + '" value="' + commission + '" pattern="[0-9+\.]+" maxlength="5" onkeypress="UI.numberOnly(event, true)" style="width: 60px; letter-spacing: 1px;"/> %'
21296					+ '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>'
21297					+ setByService + currentCommissionStartDescription
21298				+ '</div> </div>');
21299		
21300    	var ojpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.saveEditCommission);
21301    	var jpop = ojpop.getPopup().addClass('no-persist');
21302    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "8px" });
21303    }
21304    
21305    _conCommission.saveEditCommission = function() {
21306    	var jpop = $('#pop-edit-commission').closest('.glopop');
21307    	var sid = jpop.find('#Edit_Staff_id').val();
21308    	
21309    	var jcommission = jpop.find('#Edit_Commission_pct');
21310    	var commission = jcommission.val();
21311    	
21312    	if (false && jcommission.attr('original_commission_pct') == commission) {
21313    		_conCommission.saveEditCommissionConfirmed(sid, commission);
21314    	} else {
21315    		var htm = $('<div id="pop-commission-start"> <h1 class="friendly-msg4">Commission Effective Date</h1>'
21316    			+ '<div class="friendly-msg4" style="padding: 20px;">'
21317    				+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
21318    				+ '<label for="Commission_Start_dt">Commission Start Date</label>'
21319    				+ '<input id="Commission_Start_dt" type="text" style="width: 120px; padding-bottom: 1px; letter-spacing: 2px; text-align: center; font-weight: bold; color: #4F81BD;"/>'
21320    				+ _getCurrentCommissionStart()
21321    			+ '</div> </div>');
21322	    	
21323	    	var fnSave = function () {
21324	    		var dt = $('#pop-commission-start #Commission_Start_dt').val()
21325	    		GLO.Provider.Commission.saveEditCommissionConfirmed(sid, commission, dt);
21326	    	}
21327	    	
21328	    	var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist');
21329	    	
21330	    	var dtToday = new Date().toGloDate();
21331	    	jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 });
21332	    	jpop.find('#Commission_Start_dt').val(dtToday);
21333	    	
21334	    	jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" });
21335	    	jpop.find('#Commission_Start_dt').blur();
21336    	}
21337    }
21338    
21339    _conCommission.saveEditCommissionConfirmed = function(sid, commission, confirmDate) {
21340    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveCommission?sid=' + sid;
21341        
21342        var jpop1 = $('#pop-commission-start').closest('.glopop');
21343        var jpop2 = $('#pop-edit-commission').closest('.glopop');
21344        
21345        GLO.UI.Form.beginProcessing( jpop1.find('.btnSave') );
21346        GLO.UI.Form.beginProcessing( jpop2.find('.btnSave') );
21347        
21348        $.ajax({ type: "POST", url: uri, "cache": false, data: { "commission": commission, "commissionStartDate": confirmDate } })
21349            .success(function(data, textStatus, jqXHR) {
21350                GLO.Popup.close(jpop1);
21351                GLO.Popup.close(jpop2);
21352                GLO.Popup.Success.open('Service Commission Updated', 'Commission Saved');
21353                
21354                if ($('#bd #report-payroll').length) {
21355                	GLO.Report.Payroll.search();
21356                } else {
21357                	_setCommission(sid, commission);
21358                }
21359		    })
21360            .error(function(jqXHR, textStatus, errorThrown) {
21361                GLO.Popup.Error('Unable to save.  Please try again');
21362                GLO.UI.Form.resetProcessing();
21363            });
21364    }
21365    
21366    _conCommission.gotoCommissionReport_IsEmployee = function() {
21367    	_conCommission.gotoCommissionReport('commission-column-is-employee', 'Set which staff are employees');
21368    }
21369    _conCommission.gotoCommissionReport_StaffFee = function(highlight, msg) {
21370    	_conCommission.gotoCommissionReport('staff-svc-fee', 'Set which staff are charged staff service fees');
21371    }
21372    _conCommission.gotoEditEarlyPercent = function() {
21373    	_conCommission.gotoCommissionReport('early', 'Change Early Commission Percent', '% Early Commission');
21374    }
21375    _conCommission.gotoEditNormalPercent = function() {
21376    	_conCommission.gotoCommissionReport('normal', 'Change Normal Commission Percent', '% Normal Commission');
21377    }
21378    _conCommission.gotoEditMinHourly = function() {
21379    	_conCommission.gotoCommissionReport('min-hourly-rate', 'Change Minimum Hourly Rate', 'Hourly Rate');
21380    }
21381    _conCommission.gotoCommissionReport = function(highlight, msg, title) {
21382    	var url = 'provider/manage/CommissionByStaffService?highlight=' + highlight;
21383    	
21384    	title = UTIL.coalesce(title, 'Payroll Setup');
21385    	
21386    	GLO.Popup.Processing.open(msg + '<br/><br/>Loading Payroll Setup...', title);
21387    	GLO.Report.CellSummary.gotoReport(url, null, event);
21388    }
21389    _conCommission.gotoServiceFee = function() {
21390    	var url = 'provider/profile/4?goto=fee';
21391    	
21392    	GLO.Popup.Processing.open('Loading Manage Staff Service Fees...', 'Staff Service Fees');
21393    	GLO.Report.CellSummary.gotoReport(url, null, event);
21394    }
21395    _conCommission.gotoCreditFee = function() {
21396    	var url = 'provider/profile/4?goto=fee&highlight=creditfee';
21397    	
21398    	GLO.Popup.Processing.open('Loading Manage Staff Credit Card Fee...', 'Staff Credit Card Fee');
21399    	GLO.Report.CellSummary.gotoReport(url, null, event);
21400    }
21401    _conCommission.gotoEditDefaultProductCommission = function(element, event) {
21402    	var url = 'provider/inventory#action=inventory-options';
21403    	
21404    	GLO.Popup.Processing.open('Loading Manage Inventory to allow you to change the default product commission %...', 'Edit Product Commission');
21405    	GLO.Report.CellSummary.gotoReport(url, null, event);
21406    }
21407    _conCommission.openEditProductCommissionOnReport = function() {
21408    	var tr = $('#report-payroll').find('td.cell-summary-selected').closest('tr');
21409    	var sid = tr.attr('staff_id');
21410		var sname = tr.find('.staff-column').text();
21411		var commission = tr.find('.commission-percent-column').text().replace('%', '');
21412		
21413		GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
21414		
21415		_conCommission.openEditProductCommission2(sid, sname, commission);
21416    }
21417    _conCommission.openEditProductCommission = function(element, event) {
21418    	if (!GLO.Report.allowReportChange()) { return; }
21419    	
21420    	var commission = '', jelement = $(element);
21421		var tr = jelement.closest('tr');
21422		
21423		if (jelement.find('b').length > 0) {
21424			commission = jelement.find('b').text().replace('%', '');
21425		}
21426		
21427		var sid = tr.attr('staff_id');
21428		var sname = tr.find('.commission-column-staff').text();
21429		
21430		_conCommission.openEditProductCommission2(sid, sname, commission);
21431    }
21432    _conCommission.openEditProductCommission2 = function(sid, sname, commission) {
21433    	var numberInputType = "text";
21434        if (GLO.Info.isAndroid) { numberInputType = "number"; }
21435    	
21436    	var htm = $('<div id="pop-edit-product-commission"> <h1 class="friendly-msg2">Product Commission</h1> <div class="friendly-msg2" style="min-width: 300px;">'
21437					+ '<label for="Product_Commission_pct" style="display: block; margin: 8px; margin-bottom: 2px; text-align: center;">' + sname + ' Product Commission</label>'
21438					+ '<input id="Product_Commission_pct" original_commission_pct="' + commission + '" type="' + numberInputType + '" value="' + commission + '" pattern="[0-9+\.]+" maxlength="5" onkeypress="UI.numberOnly(event, true)" style="width: 50px; letter-spacing: 1px;"/> %'
21439					+ '<input id="Edit_Staff_id" type="hidden" value="' + sid + '"/>'
21440				+ '</div> </div>');
21441		
21442    	var ojpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.saveProductCommission);
21443    	var jpop = ojpop.getPopup().addClass('no-persist');
21444    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "8px" });
21445    }
21446    
21447    _conCommission.printPayroll = function() {
21448    	var tbl = $('#report-payroll-summary');
21449    	var dateRange = tbl.attr('start_d') + ' - ' + tbl.attr('end_d');
21450    	
21451    	var tr = tbl.find('td.cell-summary-selected').closest('tr');
21452    	var sid = tr.attr('staff_id');
21453		var sname = tr.find('.staff-column').text();
21454		var h2 = '<h2>' + sname + ': ' + dateRange + '</h2>';
21455		//var commission = tr.find('.commission-percent-column').text().replace('%', '');
21456		
21457		var productCommission = UTIL.coalesceMoney(tr.find('.product-dollar-column').text().replace('$', ''));
21458		var serviceCommission = UTIL.coalesceMoney(tr.find('.service-dollar-column').text().replace('$', '')) + UTIL.coalesceMoney(tr.find('.plus-min-column').text().replace('$', ''));
21459		
21460		var feeSupply = UTIL.coalesceMoney(tr.find('.supply-fee-column').text().replace('$', ''));
21461		var feeClean = UTIL.coalesceMoney(tr.find('.clean-fee-column').text().replace('$', ''));
21462		
21463		var adjust = UTIL.coalesceMoney(tr.find('.adjust-input').val());
21464		var tips = UTIL.coalesceMoney(tr.find('.tip-column').text().replace('$', ''));
21465		var preTaxTotal = UTIL.coalesceMoney(tr.find('.total-column').text().replace('$', ''));
21466		
21467		var social = UTIL.coalesceMoney(tr.attr('social_security_mn'));
21468		var medicare = UTIL.coalesceMoney(tr.attr('medicare_mn'));
21469		var employmentInsurance = UTIL.coalesceMoney(tr.attr('employment_insurance_mn'));
21470		
21471		var fedWithheld = UTIL.coalesceMoney(tr.attr('federal_tax_mn'));
21472		//var totalWithheld = UTIL.coalesceMoney(tr.attr('total_withheld_mn'));
21473		var totalAfterTax = UTIL.coalesceMoney(tr.attr('wage_after_tax_mn'));
21474		
21475		GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
21476		
21477		var tbl = _printPayrollHtm(productCommission, serviceCommission, feeSupply, feeClean, adjust, tips, preTaxTotal, -social, -medicare, -employmentInsurance, -fedWithheld, totalAfterTax);
21478		var htm = '<div id="payroll-print-staff">' + h2 + tbl + '</div>';
21479		var css = '#doc3 { visibility: hidden; display: none; } #payroll-print-staff-table { margin: auto; margin-top: 8px; }';
21480		
21481		UI.Print.print(htm, css, true);
21482		//var jpop = GLO.Popup.Info.open(htm, h2).addClass('pop-print-payroll');
21483		//GLO.Popup.Custom.singleButton(jpop, 'Close');
21484    }
21485    function _printPayrollHtm(productCommission, serviceCommission, feeSupply, feeClean, adju
21485st, tips, preTaxTotal, social, medicare, employmentInsurance, fedWithheld, totalAfterTax) {
21486    	var tbl = _printPayrollHtmRow('Product Commission', productCommission);
21487    	tbl += _printPayrollHtmRow('Service Commission', serviceCommission);
21488    	tbl += _printPayrollHtmRow('Supply Fees', feeSupply);
21489    	tbl += _printPayrollHtmRow('Cleaning Fees', feeClean);
21490		
21491		tbl += _printPayrollHtmRow('Ajdustment', adjust);
21492		tbl += _printPayrollHtmRow('Tips', tips);
21493		tbl += _printPayrollHtmRow('Pre-Tax Total', preTaxTotal);
21494		
21495		if (GLO.Data.provider.country == "US") {
21496			tbl += _printPayrollHtmRow('Social Security', social);
21497			tbl += _printPayrollHtmRow('Medicare', medicare);
21498		} else if (GLO.Data.provider.country == "CA") {
21499			if (GLO.Data.provider.state == "QC") {
21500				tbl += _printPayrollHtmRow('Quebec Pension Plan (QPP)', social);
21501			} else {
21502				tbl += _printPayrollHtmRow('Canada Pension Plan (CPP)', social);
21503			}
21504			
21505			tbl += _printPayrollHtmRow('Employment Insurance (EU)', employmentInsurance);
21506		}
21507		
21508		tbl += _printPayrollHtmRow('Federal Tax Withheld', fedWithheld);
21509		tbl += _printPayrollHtmRow('Total After Tax', totalAfterTax);
21510		
21511		return '<table id="payroll-print-staff-table">' + tbl + '</table>';
21512    }
21513    function _printPayrollHtmRow(label, amount) {
21514    	if (amount != 0) {
21515    		var id = 'print-payroll-' + UTIL.replaceAll($.trim(label).toLowerCase(), ' ', '');
21516    		return '<tr id="' + id + '"><th>' + label + '</th><td>' + UTIL.displayMoney(amount, false, true, true) + '</td></tr>';
21517    	} else {
21518    		return '';
21519    	}
21520    }
21521    
21522    _conCommission.saveProductCommission = function() {
21523    	var jpop = $('#pop-edit-product-commission').closest('.glopop');
21524    	var sid = jpop.find('#Edit_Staff_id').val();
21525    	var commission = jpop.find('#Product_Commission_pct').val();
21526    	
21527    	var htm = $('<div id="pop-commission-start"> <h1 class="friendly-msg4">Commission Effective Date</h1>'
21528			+ '<div class="friendly-msg4" style="padding: 20px;">'
21529				+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
21530				+ '<label for="Commission_Start_dt">Commission Start Date</label>'
21531				+ '<input id="Commission_Start_dt" type="text" style="width: 100px; letter-spacing: 1px;"/>'
21532			+ '</div> </div>');
21533    	
21534    	var fnSave = function () {
21535    		var dt = $('#pop-commission-start #Commission_Start_dt').val()
21536    		GLO.Provider.Commission.saveProductCommissionConfirmed(sid, commission, dt);
21537    	}
21538    	
21539    	var jpop = new GLO.Popup.Custom(htm, fnSave).getPopup().addClass('no-persist');
21540    	
21541    	var dtToday = new Date().toGloDate();
21542    	jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 });
21543    	jpop.find('#Commission_Start_dt').val(dtToday);
21544    	
21545    	jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" });
21546    	jpop.find('#Commission_Start_dt').blur();
21547    }
21548    _conCommission.saveProductCommissionConfirmed = function(sid, commission, dt) {
21549    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/ProductCommissionByStaff?sid=' + sid;
21550        var jpop1 = $('#pop-commission-start').closest('.glopop');
21551        var jpop2 = $('#pop-edit-product-commission').closest('.glopop');
21552        
21553        GLO.UI.Form.beginProcessing( jpop1.find('.btnSave') );
21554        GLO.UI.Form.beginProcessing( jpop2.find('.btnSave') );
21555        
21556        $.ajax({ type: "POST", url: uri, "cache": false, data: { "commission": commission, "commissionStartDate": dt } })
21557            .success(function(data, textStatus, jqXHR) {
21558                GLO.Popup.close(jpop1);
21559                GLO.Popup.close(jpop2);
21560                GLO.Popup.Success.open('Product Commission Updated', 'Save Product Commission');
21561                
21562                _setProductCommission(sid, commission);
21563		    })
21564            .error(function(jqXHR, textStatus, errorThrown) {
21565                GLO.Popup.Error('Unable to save.  Please try again');
21566                GLO.UI.Form.resetProcessing();
21567            });
21568    }
21569    _conCommission.saveEnableStaffFee = function(element, event) {
21570    	var jcheckbox = $(element);
21571    	var tr = jcheckbox.closest('tr');
21572    	var sid = tr.attr('staff_id');
21573    	var sname = tr.find('.commission-column-staff').text();
21574    	var isEnable = jcheckbox.prop('checked');
21575    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/EnableStaffFee?sid=' + sid + '&enable=' + isEnable;
21576        
21577        $.ajax({ type: "POST", url: uri, "cache": false })
21578            .success(function(data, textStatus, jqXHR) {
21579                var word = 'Disabled', uri = 'provider/profile/4?goto=fee';
21580                
21581                if (isEnable) { word = 'Enabled'; }
21582                
21583                var msg = '<p>Staff Service Fee ' + word + ' for ' + sname + '</p>';
21584                var btn = '<span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uri + '\', this, event, true)">Setup Staff Service Fees</a></span>';
21585                var htm = '<div id="pop-success-enable-staff-service-fee">' + msg + '<div>' + btn + '</div></div>';
21586                
21587                GLO.Popup.Success.open(htm, 'Staff Service Fees');
21588		    })
21589            .error(function(jqXHR, textStatus, errorThrown) {
21590                GLO.Popup.Error('Unable to save.  Please try again');
21591                GLO.UI.Form.resetProcessing();
21592            });
21593    }
21594    _conCommission.saveEnableEmployee = function(element, event) {
21595    	var jcheckbox = $(element);
21596    	var tr = jcheckbox.closest('tr');
21597    	var sid = tr.attr('staff_id');
21598    	var sname = tr.find('.commission-column-staff').text();
21599    	var isEnable = jcheckbox.prop('checked');
21600    	var dstype = $('#report-commission-staff-list').attr('default_staff_type_cd')
21601    	
21602    	if (isEnable) {
21603    		if (tr.find('td.commission-column-merchant .merchant-personal').length > 0) {
21604    			var aemail = '<a href="mailto:[email protected]">[email protected]</a>';
21605    			var msg1 = sname + ' has personal merchant account';
21606    			var msg2 = 'To remove this merchant account and change ' + sname + ' to an employee please send an email to: ' + aemail;
21607    			var htm = '<div id="pop-warn-employee-no-merchant"><p>' + msg1 + '</p><p>' + msg2 + '</p></div>';
21608    			
21609    			GLO.Popup.Warning.open(htm, 'Employee Cannot Have Personal Merchant Account');
21610    			jcheckbox.prop('checked', false);
21611    			return false;
21612    		}
21613    		
21614    		var svcCommission = tr.find('.svc-price').text().replace('none', '').replace('-', '');
21615    		var productCommission = tr.find('.commission-column-product').text().replace('none', '').replace('-', '');
21616    		var hourlyWage = tr.find('.commission-column-hourly-wage').text().replace('none', '').replace('-', '');
21617    		
21618    		if (!UTIL.isEmpty(svcCommission)) {
21619    			var stype = 20;
21620    		} else if (!UTIL.isEmpty(hourlyWage)) {
21621    			var stype = 10;
21622    		} else if (!UTIL.isEmpty(dstype)) {
21623    			var stype = dstype;
21624    		} else {						//if (!UTIL.isEmpty(productCommission)) 
21625    			var stype = 20;
21626    		}
21627    	} else {
21628    		var stype = 30;
21629    	}
21630    	
21631    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SetStaffType?sid=' + sid + '&stype=' + stype;
21632        
21633        $.ajax({ type: "POST", url: uri, "cache": false })
21634            .success(function(data, textStatus, jqXHR) {
21635                var msg = sname + ' changed to ';
21636                
21637                if (isEnable) { msg += 'an employee'; } else { msg += ' an independent staff'; }
21638                
21639                var htm = '<div id="pop-success-staff-staff-type">' + msg + '</div>';
21640                
21641                GLO.Popup.Success.open(htm, 'Staff Type');
21642		    })
21643            .error(function(jqXHR, textStatus, errorThrown) {
21644                GLO.Popup.Error('Unable to save.  Please try again');
21645                GLO.UI.Form.resetProcessing();
21646            });
21647    }
21648    _conCommission.saveEditWage = function() {
21649    	var jpop = $('#pop-edit-wage').closest('.glopop');
21650    	var sid = jpop.find('#Edit_Staff_id').val();
21651    	var jwage = jpop.find('#Edit_Hourly_Wage_mn');
21652    	var password = $.trim(jpop.find('#Report_Password_vc').val());
21653    	
21654    	var jReportRow = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]');
21655    	var jd = { "hourly_wage_mn": $.trim(jwage.val()), "report_password_vc": password };
21656    	var xml = '', trs = jpop.find('.employee-service-row')
21657    	
21658		if (trs.length) {
21659			for (var i=0; i < trs.length; i++) {
21660				var tr = trs.eq(i), accessType = 0;
21661				var svcid = tr.attr('service_id'), ssid = UTIL.cleanString(tr.attr('staff_service_id')), wage = tr.find('.custom-wage input').val();
21662				var dsvc = tr.attr('default_service_id');
21663				
21664				if (tr.find('.wiz5-svc-enable').prop('checked')) {
21665					accessType = 4;
21666				} else if (!UTIL.isEmpty(ssid)) {
21667					accessType = 5;
21668				}
21669				
21670				if (accessType > 0) {
21671					xml += '<li service_id="' + svcid + '" staff_service_id="' + ssid + '" hourly_mn="' + wage + '" access_type_cd="' + accessType + '"/>';
21672					
21673					if (accessType == 5) {
21674						var swage = '$0';
21675					} else {
21676						var swage = UTIL.coalesce(UTIL.displayMoney(wage), tr.find('.default-wage').text(), '$0');
21677					}
21678					
21679					if (dsvc == 2330) {
21680						$('#Paid_Vacation_Amount').text(swage);
21681						jReportRow.find('.commission-column-vacation > a').text(swage);
21682					} else if (dsvc == 2331) {
21683						$('#Paid_Sick_Amount').text(swage);
21684						jReportRow.find('.commission-column-sick > a').text(swage);
21685					}
21686				}
21687			}
21688    		
21689    		jd.employee_service_xml = UTIL.htmlEncode('<ol>' + xml + '</ol>');
21690    	}
21691    	
21692    	var jovertime = jpop.find('#Staff_Overtime_mn');
21693    	var newOvertime = UTIL.coalesceMoney(jovertime.val()), currentOvertime = UTIL.coalesceMoney(jovertime.attr('original_value'));
21694    	var overtimeStart = jpop.find('#Staff_Overtime_Start_dt').val();
21695    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/SaveWage?sid=' + sid + '&overtime=' + newOvertime + '&overtimeStart=' + overtimeStart;
21696        
21697    	if (currentOvertime != newOvertime) {
21698    		uri += '&overtimeChange=1';
21699    	}
21700    	
21701    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
21702        
21703        $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
21704            .success(function(data, textStatus, jqXHR) {
21705                if ($(data).find('#report-password-container').length) {
21706                	jpop.find('.no-results-report-role').remove();
21707                	jpop.find('#edit-employee-service').before(data);
21708                	jpop.find('.btnSearchWithReportPassword').remove();
21709                	
21710                	jpop.css({ "top": "24px", "height": "inherit" }).find('#Report_Password_vc').focus();
21711                	
21712                	GLO.UI.Form.resetProcessing();
21713                	return;
21714                }
21715                
21716                GLO.Popup.close(jpop);
21717                GLO.Popup.Success.open('Hourly Wage Updated', 'Wage Saved');
21718                
21719                if ($('#bd #report-payroll').length) {
21720                	//GLO.Popup.Success.open('Refreshing Wage...', 'Wage Updated');
21721                	GLO.Report.Payroll.search();
21722                } else {
21723                	var summary = $('<div>' + data + '</div>').find('#save-wage-summary').html();
21724                	_setWage(sid, summary, newOvertime);
21725                }
21726		    })
21727            .error(function(jqXHR, textStatus, errorThrown) {
21728                GLO.Popup.Error('Unable to save.  Please try again');
21729                GLO.UI.Form.resetProcessing();
21730            });
21731    }
21732    
21733    function _setProductCommission(sid, productCommission) {
21734    	if (!UTIL.isEmpty(productCommission)) {
21735        	var pc = productCommission + '%';
21736        } else {
21737        	var pc = 'use default';
21738        }
21739        
21740        var j = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]').find('.commission-column-product > a');
21741        
21742        if (j.length > 0) {
21743	        j.css({ "border-color": "rgb(0, 200, 80)" });
21744	        
21745	        if (pc !== 'use default') {
21746	            if (j.find('>b').length > 0) {
21747	            	j = j.find('>b');
21748	            } else {
21749	            	j = j.html('<b></b>').find('>b');
21750	            }
21751	        }
21752	        
21753	        j.text(pc);
21754	        j.css({ "color": "rgb(0, 200, 80)" });
21755	    }
21756    }
21757    
21758    function _setWage(sid, summary, newOvertime) {
21759    	summary = UTIL.coalesceString(summary, 'none');
21760        var jwage = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]').find('.commission-column-hourly-wage > a');
21761        
21762        if (jwage.length > 0) {
21763	        jwage.css({ "border-color": "rgb(0, 200, 80)" });
21764	        
21765	        if (summary !== 'none') {
21766	            if (jwage.find('>b').length > 0) {
21767	            	jwage = jwage.find('>b');
21768	            } else {
21769	            	jwage = jwage.html('<b></b>').find('>b');
21770	            }
21771	        }
21772	        
21773	        jwage.text(summary);
21774	        jwage.css({ "color": "rgb(0, 200, 80)" });
21775	        
21776	        var bUpdated = '<b style="display: inline-block; padding: 2px 8px 0px; border-radius: 12px; font-family: arial; background-color: rgb(0,255,0);">Updated</b>';
21777	        var tr = jwage.closest('tr');
21778	        
21779	        tr.attr('overtimePerHour', newOvertime);
21780	        tr.find('.commission-column-hourly-service').find('span').html(bUpdated);
21781	    } else {
21782	    	var j = $('#ss-commission-hourly-wage');
21783	    	
21784	    	if (j.length) {
21785		    	j.find('#Hourly_Wage_mn').text(summary).css({ "color": "rgb(0, 200, 80)" });
21786		    	j.find('#ss-commission-edit-hourly-wage').text('(edit)').css({ "border-color": "rgb(0, 200, 80)", "color": "rgb(0, 200, 80)" });
21787		    } else {
21788		    	$('#wiz5-popupStaffConfig #wiz5-hourly-row > a').text(summary);
21789		    }
21790	    }
21791    }
21792    
21793    function _setCommission(sid, commission) {
21794    	var jcommission = $('#commission-by-staff-service tbody tr[staff_id="' + sid + '"]').find('.svc-price > a').css({ "color": "rgb(0, 200, 80)" });
21795    	
21796    	if (commission > 0) {
21797        	var strCommission = commission + '%';
21798        } else {
21799        	var strCommission = 'none';
21800        }
21801        
21802        if (jcommission.find('>b').length > 0) {
21803        	jcommission = jcommission.find('>b');
21804        } else {
21805        	jcommission = jcommission.html('<b></b>').find('>b');
21806        }
21807        
21808        if (commission > 0 && UTIL.coalesceInt(jcommission.text().replace('none', '').replace('%', ''), 0) === 0) {
21809        	jcommission.closest('tr').find('td.staff-svc-fee input').prop('checked', true).change();
21810        }
21811        
21812        jcommission.css({ "border-color": "rgb(0, 200, 80)" })
21813        jcommission.text(strCommission);
21814    }
21815    
21816    _conCommission.canEditStaffCommission = function() {
21817    	if (GLO.Info.roleType < 220) {
21818    		var msg = '<div> <h1 class="friendly-msg4">Permission Warning</h1> <div class="friendly-msg4">Please login as a manager or admin to update the service commission</div></div>';
21819    		new GLO.Popup.Warning(msg);
21820    		return false;
21821    	} else {
21822    		return true;
21823    	}
21824    }
21825    
21826    _conCommission.gotoStaffService = function(event) {
21827    	if (!_conCommission.canEditStaffCommission()) { return; }
21828    	
21829    	var sid = $('#wiz5-popupStaffConfig #Staff_id').val();
21830    	var uri = GLO.Link.Page.Provider.Home + 'manage/CommissionByStaffService?sfilter=' + sid;
21831    	
21832    	if (event.ctrlKey) {
21833    		var childWindow = UI.openChildWindow(uri, '', true);
21834    	} else {
21835    		document.location = uri;
21836    	}
21837    }
21838    
21839    function _getCurrentCommissionStart() {
21840    	if (UTIL.isDate(_dtCommissionStart)) {
21841			var day = new Date(_dtCommissionStart).toGloDateString(true, false, true, true) + ', ' + new Date(_dtCommissionStart).getFullYear();
21842			
21843			var label = '<label style="padding-right: 8px; letter-spacing: 0;">Current Commission Start</label>';
21844			var value = '<b style="font-size: large; color: #4F81BD;">' + day + '</b>';
21845			
21846			return '<div style="margin-top: 24px; text-align: center;">' + label + value + '</div>';
21847		} else {
21848			return '';
21849		}
21850    }
21851    
21852    _conCommission.saveStaffService = function() {
21853    	if (false && $('.ss-commission-buttons .btnSave a.unsaved').length === 0) {
21854    		_conCommission.saveStaffServiceConfirmed();
21855    		return;
21856    	}
21857    	
21858    	var htm = $('<div id="pop-commission-start"> <h1 class="friendly-msg4">Commission Effective Date</h1>'
21859    			+ '<div class="friendly-msg4" style="padding: 20px;">'
21860    				+ '<style> .ui-datepicker { z-index: 9999 !important; } </style>'
21861    				+ '<label for="Commission_Start_dt">Commission Start Date</label>'
21862    				+ '<input id="Commission_Start_dt" type="text" style="width: 120px; padding-bottom: 1px; letter-spacing: 2px; text-align: center; font-weight: bold; color: #4F81BD;"/>'
21863    				+ _getCurrentCommissionStart()
21864    			+ '</div> </div>');
21865    	
21866    	var jpop = new GLO.Popup.Custom(htm, GLO.Provider.Commission.saveStaffServiceConfirmed).getPopup().addClass('no-persist');
21867    	
21868    	var dtToday = new Date().toGloDate();
21869    	jpop.find('#Commission_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), minDate: "-6M", maxDate: 0 });
21870    	jpop.find('#Commission_Start_dt').val(dtToday);
21871    	
21872    	jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px", "letter-spacing": "1px" })
21873    	jpop.find('#Commission_Start_dt').blur();
21874    }
21875    
21876    _conCommission.saveStaffServiceConfirmed = function() {
21877    	var j = $('#commission-by-staff-service');
21878    	var sid = j.attr('staff_id');
21879    	var commission, dcommission = j.attr('default_commission_pct');
21880    	
21881    	var jpop = $('#pop-commission-start').closest('.glopop');
21882    	var start = UTIL.cleanString(jpop.find('#Commission_Start_dt').val());
21883    	
21884    	var tr = j.find('.tablesorter > tbody > tr');
21885    	var xml = '<table>';
21886    	
21887    	for (var i=0; i < tr.length; i++) {
21888    		commission = tr.eq(i).find('.svc-commission input').val();
21889    		//if (dcommission == commission) { commission = '0'; }
21890    		
21891    		xml += '<tr staff_service_id="' + tr.eq(i).attr('staff_service_id') + '" commission_pct="' + commission + '"/>';
21892    	}
21893    	
21894    	xml = UTIL.htmlEncode(xml + '</table>');
21895    	
21896    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/CommissionByStaffServiceUpdate?sfilter=' + sid;
21897        GLO.UI.Form.beginProcessing( j.find('.btnSave') );
21898        GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
21899        
21900        $.ajax({ type: "POST", url: uri, "cache": false, data: { "input_xml": xml, "commission_start_dt": start } })
21901            .success(function(data, textStatus, jqXHR) {
21902                new GLO.Popup.Success('Commission Saved');
21903                
21904                setTimeout(function() {
21905                	document.location = GLO.Link.Page.Provider.Home + $('#commission-by-staff-service h2').attr('back_url_vc');
21906                });
21907		    })
21908            .error(function(jqXHR, textStatus, errorThrown) {
21909                GLO.Popup.Error('Unable to save.  Please try again');
21910                GLO.UI.Form.resetProcessing();
21911            });
21912    }
21913    
21914    _conCommission.openReportHelp = function(stepNumber) {
21915    	if (UTIL.coalesceInt(GLO.Info.roleType, 201) > 200) {
21916    		SA.Help.openReportHelp('#help-commission', stepNumber, 'info/CommissionHelp');
21917    	} else {
21918    		GLO.Popup.Warning.open('Please login as a receptionist, manager, or admin to access the Payroll Guide', 'Access Issue');
21919    	}
21920    }
21921
21922    return _conCommission;
21923})();
21924
21925
21926GLO.Provider.Resource = (function() {
21927    function _conResourceAdmin() { }
21928    var _jsonResource, _jsonIndustry, _rgNameAutoSave = null;
21929    
21930    _conResourceAdmin.init = function(jsonResource, jsonIndustry) {
21931        _jsonResource = jsonResource;
21932        _jsonIndustry = jsonIndustry;
21933        
21934        var j = $('#manage-resource-group-container');
21935        var tblSvc = j.find('#manage-resource-type-service');
21936        var tblResource = j.find('#manage-resource-list');
21937        
21938        var jmsg = $('#resource-type-message');
21939		GLO.Provider.Advanced.initClientOptions(jmsg);
21940        
21941        if (UTIL.coalesceInt(GLO.Data.provider.resource_per_cd, 20) == 20) {
21942        	$('#resource-type-message, #manage-resource-type-service').addClass('hideX');
21943        }
21944        
21945        _initUrl();
21946        _initSortResourceGroup();
21947        _displayAutoAssign();
21948        $('#throbber-still-loading').remove();
21949    }
21950    
21951    function _initUrl() {
21952    	var open = UTIL.coalesceString(UTIL.cleanString(GLO.Uri.url('open')).toLowerCase(), 'help');
21953    	
21954    	if (!UTIL.isEmpty(open) && open != 'no') {
21955    		//var highlight = UTIL.cleanString(GLO.Uri.hash('highlight'));
21956	    	var id = UTIL.cleanString(GLO.Uri.hash('id')).toLowerCase();
21957	    	//var help = UTIL.cleanString(GLO.Uri.hash('help')).toLowerCase();
21958    		
21959    		if (open === 'add-resource' || open === 'addresource') {
21960    			setTimeout(function() {
21961	    			$('#btnAddResource > a').click()
21962	    		}, 100);
21963    		} else if (open === 'resource') {
21964    			setTimeout(function() {
21965	    			$('#resource-group-list').find('tr[resource_group_id="' + id + '"]').click()
21966	    		}, 100);
21967    		} else if (open === 'help') {
21968    			setTimeout(function() {
21969	    			$('#manage-resource-add-button').find('.helpIcon2').click();
21970	    		}, 100);
21971    		} else if (open === 'help-per') {
21972    			setTimeout(function() {
21973	    			GLO.Provider.Resource.openHelpResourcePer();
21974	    		}, 100);
21975    		}
21976    	}
21977    }
21978    
21979    function _initSortResourceGroup() {
21980    	var rglist = $('#resource-group-list');
21981    	
21982    	rglist.find('tbody').sortable({
21983			handle: '.drag-handle'
21984			, update: function(event, ui) {
21985				//toDo: save to DB
21986				_updateResourceGroupOrder();
21987			}
21988		});
21989    }
21990    
21991    function _initSortResource() {
21992    	var rlist = $('#manage-resource-list #resource-list')
21993    	UI.initTableSorter(rlist, null, true);
21994    	
21995    	rlist.find('tbody').sortable({
21996			handle: '.drag-handle'
21997			, update: function(event, ui) {
21998				//var trs = $('#manage-resource-list #resource-list').find('tbody > tr');
21999				//for (var i=0; i < trs.length; i++) { trs.eq(i).attr('order_sr', i+1); }
22000				
22001				_updateResourceOrder();
22002			}
22003		});
22004    }
22005    
22006    function _displayAutoAssign() {
22007    	var jAutoAssign = $('#manage-resource-auto-assign');
22008    	var tdBookOnline = $('#manage-resource-container').find('.book_resource_online_fl, .resource-book-online');
22009    	
22010    	if ($('#manage-resource-per #Resource_Per_cd').val() == 10) {
22011    		jAutoAssign.removeClass('hide');
22012    		
22013    		if (jAutoAssign.find('#Auto_Assign_Resource_fl').prop('checked')) {
22014    			tdBookOnline.removeClass('hide');
22015    		} else {
22016    			tdBookOnline.addClass('hide');
22017    		}
22018    	} else {
22019    		jAutoAssign.addClass('hide');
22020    		tdBookOnline.removeClass('hide');
22021    	}
22022    }
22023    function _updateResourceOrder() {
22024    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22025    	var trs = $('#manage-resource-list #resource-list').find('tbody > tr');
22026    	var xml = '<ol>';
22027		
22028		for (var i=0; i < trs.length; i++) {
22029			trs.eq(i).attr('order_sr', i+1);
22030			xml += '<li resource_id="' + trs.eq(i).attr('resource_id') + '" order_sr="' + (i+1) + '"/>';
22031		}
22032		
22033		xml = UTIL.htmlEncode(xml + '</ol>');
22034		var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceOrder?rgid=' + rgid;
22035		
22036        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": xml } });
22037            //.success(function(data, textStatus, jqXHR) { })
22038            //.error(function(jqXHR, textStatus, errorThrown) { });
22039    }
22040    
22041    function _updateResourceGroupOrder() {
22042    	var trs = $('#resource-group-list').find('tbody > tr');
22043    	var xml = '<ol>';
22044		
22045		for (var i=0; i < trs.length; i++) {
22046			trs.eq(i).attr('order_sr', i+1);
22047			xml += '<li resource_group_id="' + trs.eq(i).attr('resource_group_id') + '" order_sr="' + (i+1) + '"/>';
22048		}
22049		
22050		xml = UTIL.htmlEncode(xml + '</ol>');
22051		var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceGroupOrder';
22052		
22053        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": xml } })
22054            .success(function(data, textStatus, jqXHR) {
22055                //GLO.Popup.Success.open(htm, 'Order Updated');
22056            })
22057            .error(function(jqXHR, textStatus, errorThrown) {
22058                //GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
22059                //new GLO.Popup.Error('Unable to order the calendars staff');
22060            });
22061    }
22062    
22063    _conResourceAdmin.changeAutoAssignResource = function(element) {
22064    	_displayAutoAssign();
22065    	
22066    	var isAutoAssign = $('#manage-resource-auto-assign #Auto_Assign_Resource_fl').prop('checked');
22067    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceAutoAssign?isauto=' + isAutoAssign;
22068    	var msg = 'Auto-Assign Resource Setting ';
22069    	
22070    	if (isAutoAssign) {
22071    		msg += 'Enabled';
22072    	} else {
22073    		msg += 'Disabled';
22074    	}
22075    	
22076        $.ajax({ type: "POST", url: uri, "cache": false })
22077            .success(function(data, textStatus, jqXHR) {
22078                GLO.Popup.Success(msg);
22079		    })
22080		    .error(function(jqXHR, textStatus, errorThrown) {
22081                GLO.Popup.Error('Unable to change auto-assign resource setting.  Please try again later.');
22082                GLO.UI.Form.resetProcessing();
22083            });
22084    }
22085    _conResourceAdmin.openHelpResourcePer = function(event, element) {
22086    	GLO.Popup.closeIfExist($('#pop-setup-service-resource-help').closest('.glopop'));
22087    	
22088    	var arrow = '<b class="arrow-right">&#10140;</b>';
22089    	var perService = '<b class="narrow-text">Per Service</b>';
22090    	var perTicket = '<b class="narrow-text">Per Ticket</b>';
22091    	var aSchedule = '<a onclick="GLO.Uri.gotoUri(\'provider/ResourceView\', this, event, true)">Resource Calendar</a>';
22092    	
22093    	var msg = '<p style="margin-left: -20px; margin-top: 12px; font-weight: bold;">Can assign resource per service or per ticket, both populate your ' + aSchedule + '</p>';
22094    	
22095    	var listPerService = '<li>Need to assign different types of resources to different types of services <small>(like massage rooms for massages, pedicure chairs for pedicures, tanning beds for tanning)</small></li>'
22096	    	+ '<li>Need to ensure that a resource does not get double booked (like if have more nail technicians than pedicure chairs)</li>'
22097	    	+ '<li>Need to allow booking resource without a staff (like a tanning bed)</li>'
22098	    	+ '<li>Want to assign resources for limited number of the services you offer</li>';
22099    	
22100    	var msgPerService = '<h3>Set Resource Per Service</h3>'
22101	    	+ '<p>For services setup with a resource, online booking will only allow booking services if a resource is available</p>'
22102	    	+ '<p>Can allow the client to book the resource or have the resource automatically assigned <span class="narrow-text">(without the client seeing it)</span></p>'
22103	    	+ '<p style="margin-bottom: 0; padding-bottom: 2px;">Best option if</p>' + '<ul>' + listPerService + '</ul>';
22104	    
22105	    var listPerTicket = '<li>Your client receives all services at same location</li>'
22106	    	+ '<li>Want to assign the resource at check-in</li>'
22107	    	+ '<li>Want to display <i class="narrow-text">Chair, Station, or Room #</i> on ticket</li>';
22108	    
22109	    var msgPerTicket = '<h3>Set Resource Per Ticket</h3>'
22110	    	+ '<p>' + perTicket + ' is easier to setup</p>'
22111	    	+ '<p>Clients never book resource, staff assign resource on day of appointment <b class="narrow-text">(usually at check-in)</b></p>'
22112	    	+ '<p style="margin-bottom: 0; padding-bottom: 2px;">Best option if</p>' + '<ul>' + listPerTicket + '</ul>';
22113	    
22114	    var htm = '<div id="pop-help-manage-resource-per">' + msg + msgPerService + msgPerTicket + '</div>';
22115    	var ojInfo = GLO.UI.openHelp(element, htm, 'Manage Resource Per Service or Per Ticket');
22116    	var jpop = ojInfo.getPopup().addClass('pop-info2');
22117    }
22118    
22119    _conResourceAdmin.openHelpResourceName = function(event, element) {
22120    	var dragIcon = '<b class="drag-handle ui-sortable-handle" style="font-size: large;"></b>';
22121    	var msg1 = '<p>Create each resource with a unique name such as <span class="resource-list">' + _getHelpResource(false, false, true) + '</span></p>';
22122    	var msg2 = '<p>Press and hold the drag icon ' + dragIcon + ' to drag the resource higher or lower in the list of resources</p>';
22123    	
22124    	if (UTIL.coalesceInt(GLO.Data.provider.resource_per_cd, 10) == 10) {
22125    		var arrow = '<b class="arrow-right">&#10140;</b>';
22126    		var aProfileService = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/4\', this, null, true)">Profile ' + arrow + ' Services</a>'
22127	    	var bStaffOnly = '<b class="narrow-text">Staff Only</b>', bBookOnline = '<b class="narrow-text">Book Online</b>';
22128	    	
22129	    	var msg3 = '<p><b>Staff Only:</b> <ul>'
22130	    					+ '<li>Restrict resource to only staff booking <small>(client cannot book online)</small></li>'
22131	    					+ '<li>If all resources are restricted to ' + bStaffOnly + ' then these services will display no results if a client tries to book online</li>'
22132	    					+ '<li>So, only some resources should be marked ' + bStaffOnly + ' or go to ' + aProfileService + ' to block online booking for these services</li>'
22133	    			 + '</ul></p>';
22134	    	var msg4 = '<p><b>Book Online</b> <ul>'
22135	    					+ '<li>Client will see resource listed as an option when booking online</li>'
22136	    					//+ '<li>Leave both ' + bStaffOnly + ' and ' + bBookOnline + ' un-checked to let ' + GLO.Info.getScheduleAnyoneHtm(
22136) + ' automatically assign resource at time of booking</li>'
22137	    			 + '</ul></p>';
22138	    	var msg5 = '<p style="margin-top: 24px;">To have ' + GLO.Info.getScheduleAnyoneHtm() + ' automatically assign resource without allowing client to pick resource leave both '
22139	    		+ bStaffOnly + ' and ' + bBookOnline + ' un-checked</p>';
22140    	} else {
22141    		var msg3 = '', msg4 = '', msg5 = '';
22142    	}
22143    	
22144    	var htm = '<div id="pop-setup-service-resource-name-help">' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>';
22145    	var ojInfo = GLO.UI.openHelp(element, htm, 'Manage Each Resource');
22146    	var jpop = ojInfo.getPopup().addClass('pop-info2');
22147    }
22148    _conResourceAdmin.openHelpResourceGroup = function(event, element) {
22149    	var msg1 = '<p>Select which services use these resources</p>';
22150    	var msg2 = '<p><b>No Staff:</b> Allow appointments with these services that have no staff (only a resource)</p>';
22151    	var msg3 = '<p><b>Book Online</b> Allow client to book this service online</p>';
22152    	var htm = '<div id="pop-setup-service-resource-name-help">' + msg1 + msg2 + msg3 + '</div>';
22153    	
22154    	var ojInfo = GLO.UI.openHelp(element, htm, 'Which Services Use These Resources?');
22155    	var jpop = ojInfo.getPopup().addClass('pop-info2');
22156    }
22157    _conResourceAdmin.openHelp = function(event, element) {
22158    	if (GLO.Data.provider.resource_per_cd == 20) {
22159    		var resourceList = '<span class="resource-list">chair #1, chair #2, etc.., room A, room B, room C, etc..</span>';
22160    		var msg = '<p>Do you want to reserve or assign a resource like ' + resourceList + ' or something similar on appointments?</p>';
22161    		
22162    		msg += _getCustomHelpMessagePerTicket();
22163    		msg += _getMoreResourceInfo();
22164    	} else {
22165	    	var msg = _getCustomHelpMessage();
22166	    	
22167			msg += '<div style="margin-top: 20px;">When clients book online it will automatically verify a resource is available and then reserve the needed resource.</div>'
22168			
22169			msg += '<div style="margin-top: 24px;">'
22170					+ '<p>When you book an appointment you can specify which resource you want to use or it will automatically select an available resource</p>'
22171					+ '<p>If you select a resource that is not available it will warn you that resource is already scheduled</p>'
22172				+ '</div>';
22173    	}
22174    	
22175    	msg = '<div id="pop-setup-service-resource-help">' + msg + '</div>';
22176    	
22177    	var ojInfo = GLO.UI.openHelp(element, msg, 'Setup Service Resources');
22178    	var jpop = ojInfo.getPopup().addClass('pop-info2').css({ "max-width": "900px" });
22179    	
22180    	//jpop.css({ "background-color": "#275264" });
22181    	//jpop.find('h2').css({ "color": "#4F81BD", "background-color": "#222", "border-radius": "8px", "padding": "9px", "margin-top": "-20px", "margin-bottom": "15px", "margin-left": "-25px" });
22182    	
22183    	//jpop.find('.msg p').remove();
22184    	//window.setTimeout(function() { ojInfo.realign(); }, 100);
22185    }
22186    
22187    function _getHelpResource(isFullList, isResourceGroupNameExample, isResourceNameExample) {
22188    	var nm = _jsonIndustry.resource_group_list_vc;
22189    	var arr = nm.split(',');
22190    	var otherCount = 0;
22191    	
22192    	if (UTIL.isEmpty(nm)) {
22193    		if (UTIL.parseBool(_jsonIndustry.resource_other_equipment_fl)) {
22194    			nm = 'equipment';
22195    			++otherCount;
22196    			
22197    			if (UTIL.parseBool(_jsonIndustry.resource_other_area_fl)) {
22198    				nm += ', area';
22199    				++otherCount;
22200    			}
22201	    	} else if (UTIL.parseBool(_jsonIndustry.resource_other_area_fl)) {
22202	    		nm = 'area';
22203	    		++otherCount;
22204	    	}
22205    	} else {
22206    		if (UTIL.parseBool(_jsonIndustry.resource_other_equipment_fl)) { nm += ', other equipment'; ++otherCount; }
22207    		if (UTIL.parseBool(_jsonIndustry.resource_other_area_fl)) { nm += ', other area'; ++otherCount; }
22208    	}
22209    	
22210    	if (isFullList) {
22211    		if (nm.split(',').length > 1) {
22212    			if (otherCount > 0) {
22213	    			var n = nm.lastIndexOf(',');
22214	    			
22215					if (n !== -1) {
22216						nm = nm.substring(0, n) + ' or ' + nm.substring(n + 1);
22217					}
22218	    		} else {
22219	    			nm += ', etc';
22220	    		}
22221	    	}
22222	    	
22223	    	return nm;
22224    	} else {
22225	    	if (isResourceGroupNameExample) {
22226	    		if (UTIL.isEmpty(arr[0])) {
22227	    			return '';
22228	    		} else {
22229	    			return ' <span style="text-transform: none; font-size: 100%; font-weight: normal;
22229 color: #333;">such as</span> ' + arr[0] + 's';
22230	    		}
22231	    	} else if (UTIL.isEmpty(arr[0])) {
22232	    		arr[0] = 'resource';   					//arr = UTIL.coalesce(nm, 'resource').split(',');
22233	    	}
22234	    	
22235	    	if (isResourceNameExample) {
22236	    		return arr[0] + ' #1, ' + arr[0] + ' #2, etc';
22237	    	} else {
22238	    		return arr[0];
22239	    	}
22240	    }
22241    }
22242    
22243    function _getCustomHelpMessagePerTicket() {
22244    	var msg = '<h3 style="text-align: center;">To Setup Resources below</h3> <ol>';
22245    	var btnAddResourceType = '<span class="btnAdd" onclick="GLO.Provider.Resource.openAddResourceGroup(true)" style="display: inline;"><a style="display: inline-block;">Add Resource Type</a></span>';
22246    	var resourceTypeRows = $('#resource-group-list tbody > tr');
22247    	var msg1 = 'Press the button ' + btnAddResourceType + ' and create a resource type such as<span class="resource-name">' + _getHelpResource(false, true, false) + '</span>';
22248    	
22249    	if (resourceTypeRows.length > 0) {
22250    		var existingResourceList = resourceTypeRows.eq(0).find('.resource-group-name').text();
22251    		
22252    		for (var i=1; i < resourceTypeRows.length; i++) {
22253    			existingResourceList += ', ' + resourceTypeRows.eq(i).find('.resource-group-name').text();
22254    		}
22255    		
22256    		msg1 += ' or select existing <i>Resource Type</i> below like <b class="narrow-text">' + existingResourceList + '</b>';
22257    	}
22258    	
22259    	msg += '<li style="padding: 8px 0;">' + msg1 + '</li>';							//[ Pedicure Chairs ]
22260    	msg += '<li>Create each resource with a unique name such as <span class="resource-list">' + _getHelpResource(false, false, true) + '</span></li>';	//[ Pedicure Chair #1, Pedicure Chair #2, etc ]
22261    	
22262    	msg += '</ol>';
22263    	return '<div>' + msg + '</div>';
22264    }
22265    function _getMoreResourceInfo() {
22266    	var header = '<h3 style="text-align: center;">Quick Overview</h3>';
22267    	var aResourcePerHelp = '<a onclick="GLO.Provider.Resource.openHelpResourcePer()">decide best option for you</a>';
22268    	
22269    	var msg1 = '<p>Can reserve resource at time of booking <i class="narrow-text">(then setup to be per service)</i> ' 
22270    	 		+ 'or assign resource at time of check-in <i class="narrow-text">(then setup to be per ticket)</i> '
22271    	 		+ '<b class="arrow-right">&#10140;</b> ' + aResourcePerHelp + '</p>';
22272    	
22273    	var msg2 = '<p>Staff can double book a resource, but a warning message will appear encouraging them to assign a different resource</p>';
22274    	
22275    	var aResourceCal = '<a onclick="GLO.Uri.gotoUri(\'provider/ResourceView\', this, event, true)">Resource Calendar</a>';
22276    	var msg3 = '<p>Easily view resource schedule on the ' + aResourceCal + '</p>';
22277    	
22278    	return '<div>' + header + msg1 + msg2 + msg3 + '</div>';
22279    }
22280    function _getCustomHelpMessage() {
22281    	var msg = 'Do you need to reserve a <span class="resource-list">' + _getHelpResource(true) + '</span>';							//[ Message room, Waxing room, Cryo chamber, Pedicure chair, etc ]
22282    	
22283    	msg += ' with some services?<br/><br/>';
22284    	msg += 'To Setup: <ol>';
22285    	
22286    	msg += '<li>Create a resource type<span class="resource-name">' + _getHelpResource(false, true, false) + '</span></li>';							//[ Pedicure Chairs ]
22287    	msg += '<li>Select which services use the resource type</span></li>';
22288    	msg += '<li>Create each resource with a unique name such as <span class="resource-list">' + _getHelpResource(false, false, true) + '</span></li>';	//[ Pedicure Chair #1, Pedicure Chair #2, etc ]
22289    	
22290    	msg += '</ol>';
22291    	return '<div>' + msg + '</div>';
22292    }
22293    
22294    _conResourceAdmin.openResourceGroup = function(row) {
22295    	if ($(row).hasClass('selected')) {
22296    		_conResourceAdmin.closeResourceGroup(row);
22297    		return;
22298    	}
22299    	
22300    	$('#resource-group-list').find('tr').removeClass('selected').addClass('hide');
22301    	row = $(row).addClass('selected').removeClass('hide');
22302    	var rgid = row.attr('resource_group_id');
22303    	var rgname = row.find('.resource-group-name').text();
22304    	
22305    	var j = $('#manage-resource-container');
22306    	$('#manage-resource-group-container2').addClass('hide').find('.click-to-edit').addClass('hide');
22307    	$('#manage-resource-group-container').addClass('editing-specific-resource-group');
22308    	//j.find('#resource-group-list').addClass('hide');
22309    	
22310    	var jrg = j.find('#Resource_Group_Name_vc').val(rgname);
22311    	var rg = _getJsonObj(rgid);
22312    	
22313    	_populateServices(j, rg);
22314    	_populateResources(j, rg);
22315    	_initSortResource();
22316    	_displayAutoAssign();
22317    	
22318    	j.removeClass('hide');
22319    	
22320    	var saveUrl = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceGroup?resource_group_id=' + rgid;
22321		_rgNameAutoSave = new UI.AutoSave(jrg, saveUrl, GLO.Provider.Resource.updateResourceGroupComplete);
22322		
22323		$('#manage-resource-group-title').addClass('display-back');
22324		_initSendMessage(rg);
22325    }
22326    
22327    function _initSendMessage(rg) {
22328    	if ($('#manage-resource-type-service').find('tr.resource-service .no_staff_fl').find('input
22328:checked').length > 0) {
22329    		var jmsg = $('#resource-type-message').removeClass('hide');
22330    	} else {
22331    		var jmsg = $('#resource-type-message').addClass('hide');
22332    	}
22333    	
22334    	jmsg.off('change', 'input:visible', GLO.Provider.Resource.saveClientMessages);
22335    	var emailDays = UTIL.coalesceInt(rg.email_reminder_Hr_sr/24, 0);
22336    	
22337    	if (emailDays === 0) { emailDays = ''; }
22338    	
22339    	jmsg.find('#Send_Confirmation_Email_fl').prop('checked', UTIL.parseBool(rg.send_confirmation_email_fl)).change();
22340    	jmsg.find('#Confirm_On_Update_fl').prop('checked', !UTIL.parseBool(rg.no_confirm_on_update_fl)).change();
22341    	jmsg.find('#Email_Reminder_Day_sr').val(emailDays).change();
22342    	jmsg.find('#Text_Reminder_Hr_sr').val(rg.text_reminder_Hr_sr).change();
22343    	
22344    	jmsg.on('change', 'input:visible', GLO.Provider.Resource.saveClientMessages);
22345    }
22346    
22347    _conResourceAdmin.savePer = function() {
22348    	var jper = $('#manage-resource-per-container #Resource_Per_cd');
22349        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourcePer?per=' + jper.val();
22350        var msg1 = '<p>Manage Resources changed to per <b>' + jper.find('option:selected').text() + '</b></p>';
22351        
22352        $.ajax({ type: "POST", url: uri, "cache": false })
22353            .success(function(data, textStatus, jqXHR) {
22354                var msg2 = '<p>Loading Change...</p>';
22355                var htm = '<div id="pop-success-resource-per">' + msg1 + msg2 + '</div>';
22356                
22357                GLO.Popup.Processing.open(htm, 'Manage Resource Setting Saved');
22358                
22359                setTimeout(function() {
22360                	location.reload();
22361                }, 250)
22362		    });
22363    }
22364    
22365    _conResourceAdmin.saveClientMessages = function() {
22366    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22367        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceClientMessage?rgid=' + rgid;
22368        
22369        var jmsg = $('#resource-type-message');
22370        var emailHour = '', emailDay = jmsg.find('#Email_Reminder_Day_sr').val();
22371        var textHour = jmsg.find('#Text_Reminder_Hr_sr').val();
22372        var isSendOnCreate = jmsg.find('#Send_Confirmation_Email_fl').prop('checked');
22373        var isSendOnUpdate = jmsg.find('#Confirm_On_Update_fl').prop('checked');
22374        
22375        if (emailDay > 0) {
22376        	emailHour = emailDay * 24;
22377        }
22378        
22379        var json = { "texthour": textHour, "emailhour": emailHour, "confirmcreate": isSendOnCreate, "confirmupdate": isSendOnUpdate };
22380        
22381        $.ajax({ type: "POST", url: uri, "cache": false, data: json })
22382            .success(function(data, textStatus, jqXHR) {
22383                var rg = _getJsonObj(rgid);
22384                
22385                if (rg) {
22386	                rg.text_reminder_Hr_sr = textHour;
22387	                rg.email_reminder_Hr_sr = emailHour;
22388	                rg.send_confirmation_email_fl = isSendOnCreate;
22389	                rg.no_confirm_on_update_fl = !isSendOnUpdate;
22390                }
22391		    });
22392    }
22393    
22394    _conResourceAdmin.saveResourceBookOnline = function(checkbox) {
22395    	var jcheckbox = $(checkbox);
22396    	var isChecked = jcheckbox.prop('checked');
22397    	var tr = jcheckbox.closest('tr');
22398    	var rid = tr.attr('resource_id');
22399    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22400    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceBookOnline?rgid=' + rgid + '&rid=' + rid + '&bookonline=' + isChecked;
22401        var resource = _getJsonObjResource(rgid, rid);
22402        
22403        resource.book_online_fl = isChecked;
22404        
22405        if (isChecked) {
22406        	resource.no_client_booking_fl = 0;
22407        	tr.find('td.resource-restrict-client-booking input[type="checkbox"]').prop('checked', false);
22408        }
22409        
22410        $.ajax({ type: "POST", url: uri, "cache": false });
22411            //.success(function(data, textStatus, jqXHR) { });
22412    }
22413    _conResourceAdmin.saveResourceNoClientBooking = function(checkbox) {
22414    	var jcheckbox = $(checkbox);
22415    	var isChecked = jcheckbox.prop('checked');
22416    	var tr = jcheckbox.closest('tr');
22417    	var rid = tr.attr('resource_id');
22418    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22419    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/ResourceNoClientBooking?rgid=' + rgid + '&rid=' + rid + '&nobooking=' + isChecked;
22420        var resource = _getJsonObjResource(rgid, rid)
22421        
22422        resource.no_client_booking_fl = isChecked;
22423        
22424        if (isChecked) {
22425        	resource.book_online_fl = 0;
22426        	tr.find('td.resource-book-online input[type="checkbox"]').prop('checked', false);
22427        }
22428        
22429        $.ajax({ type: "POST", url: uri, "cache": false });
22430            //.success(function(data, textStatus, jqXHR) { });
22431    }
22432    
22433    function _getJsonObjResource(rgid, rid) {
22434    	var rg = _getJsonObj(rgid);
22435    	
22436    	for (var i=0; i < rg.resources.length; i++) {
22437            if (rid == rg.resources[i].resource_id) {
22438    			return rg.resources[i];
22439    		}
22440    	}
22441    	
22442    	return null;
22443    }
22444    function _getJsonObj(rgid) {
22445    	for (var i=0; i < _jsonResource.length; i++) {
22446    		if (_jsonResource[i].resource_group_id == rgid) {
22447    			return _jsonResource[i];
22448    		}
22449    	}
22450    	
22451    	return {};
22452    }
22453    
22454    function _populateResources(jcontainer, rg) {
22455    	var tbl = jcontainer.find('#manage-resource-list').find('table > tbody').addClass('hide');
22456    	tbl.find('tr').remove();
22457    	
22458    	if (rg.resources.length > 0) {
22459	    	for (var r=0; r < rg.resources.length; r++) {
22460	    		var tr = _getResourceHtm(rg.resources[r], r + 1);
22461		    	tbl.append(tr);
22462	    	}
22463	    	
22464	    	tbl.removeClass('hide');
22465    	}
22466    }
22467    
22468    function _getResourceHtm(jsonResource, rowNumber) {
22469    	var rid = jsonResource.resource_id;
22470		var name = jsonResource.resource_name_vc;
22471		var isRestrict = '', isBookOnlineChecked = '';
22472    	
22473    	if (UTIL.parseBool(jsonResource.no_client_booking_fl)) { isRestrict = ' checked="checked"'; }
22474		if (UTIL.parseBool(jsonResource.book_online_fl)) { isBookOnlineChecked = ' checked="checked"'; }
22475		
22476		if (UTIL.coalesceInt(GLO.Data.provider.resource_per_cd, 10) == 20) {
22477			var tdStaffOnly = '', tdBookOnline = '';
22478		} else {
22479			var chkidRestrict = 'resource-restrict-client' + rowNumber;
22480			var chkRestrict = '<input id="' + chkidRestrict + '" type="checkbox" onchange="GLO.Provider.Resource.saveResourceNoClientBooking(this)"' + isRestrict + '>';
22481			var lblRestrict = '<label for="' + chkidRestrict + '">Staff Only</label>';
22482			
22483			var chkidOnline = 'resource-book-online' + rowNumber;
22484			var chkOnline = '<input id="' + chkidOnline + '" type="checkbox" onchange="GLO.Provider.Resource.saveResourceBookOnline(this)"' + isBookOnlineChecked + '>';
22485			var lblOnline = '<label for="' + chkidOnline + '">Book Online</label>';
22486			
22487			var tdStaffOnly = '<td class="resource-restrict-client-booking">' + chkRestrict + lblRestrict + '</td>'
22488	        var tdBookOnline = '<td class="resource-book-online">' + chkOnline + lblOnline + '</td>'
22489		}
22490		
22491		var removeIcon = '<td class="remove-icon"> <span title="Remove this resource" onclick="GLO.Provider.Resource.removeResource(this)" class="ui-icon ui-icon-circle-close"></span> </td>';
22492    	var tr = '<tr resource_id="' + rid + '">'
22493        			+ removeIcon
22494        			+ '<td class="resource" onclick="GLO.Provider.Resource.openUpdateResource(this)">' + name + '</td>'
22495        			+ '<td class="resource-drag"><b class="drag-handle"></b></td>'
22496        			+ tdStaffOnly + tdBookOnline
22497    			+ '</tr>';
22498    	return tr;
22499    }
22500    
22501    function _populateServices(jcontainer, rg) {
22502    	var jSvcGroupDD = $($('#ServiceGroupOptionsClone').outerHTML());
22503    	var tbl = jcontainer.find('#manage-resource-type-service').find('table > tbody').addClass('hide');
22504    	var jall = $('#allServiceOptions');
22505    	
22506    	jSvcGroupDD.find('option[default_service_group_id="9"]').remove();
22507    	jSvcGroupDD.find('option[default_service_group_id="1009"]').remove();
22508    	tbl.find('tr').remove();
22509    	
22510    	if (rg.servicegroups.length > 0) {
22511    		for (var sg=0; sg < rg.servicegroups.length; sg++) {
22512	    		var sgid = rg.servicegroups[sg].service_group_id;
22513	    		var sgname = rg.servicegroups[sg].service_group_name_vc;
22514	    		var sgcolor = UTIL.cleanString(rg.servicegroups[sg].css_color_vc);
22515	    		var srows = rg.servicegroups[sg].services;
22516	    		
22517	    		var jdd = jall.find('select#crSvc' + sgid);
22518	    		
22519	    		if (srows.length > 0) {
22520		    		for (var s=0; s < srows.length; s++) {
22521		    			var jsvc = jdd.find('option[value="' + srows[s].service_id + '"]');
22522		    			var noStaffRequired = UTIL.parseBool(jsvc.attr('no_staff_fl'));
22523		    			var canBookResourceOnline = UTIL.parseBool(jsvc.attr('book_resource_online_fl'));
22524		    			
22525		    			_addServiceRowToTable(tbl, sgid, sgname, sgcolor, srows[s].service_id, srows[s].service_name_vc, noStaffRequired, canBookResourceOnline);
22526		    		}
22527	    		} else {
22528	    			//service is required so no longer use -> _addServiceRowToTable(tbl, sgid, sgname, sgcolor, '', '');
22529	    		}
22530	    	}
22531	    	
22532	    	tbl.removeClass('hide');
22533	    	//jSvcGroupDD.find('option[value="' + sgid + '"]').remove();
22534    	}
22535    	
22536    	jcontainer.find('#Service_Group_id').html(jSvcGroupDD.html());
22537    }
22538    
22539    function _addServiceRowToTable(tbl, sgid, sgname, sgcolor, svcid, svcname, noStaffRequired, canBookResourceOnline) {
22540    	var removeIcon = '<td class="remove-icon"> <span title="Remove this service" onclick="GLO.Provider.Resource.removeService(this)" class="ui-icon ui-icon-circle-close"></span> </td>';
22541    	var noStaffChecked = '', allowOnlineChecked = '';
22542    	var rowNumber = tbl.find('tr').length + 1;
22543    	
22544    	if (noStaffRequired) { noStaffChecked = ' checked="checked"'; }
22545    	if (canBookResourceOnline) { allowOnlineChecked = ' checked="checked"'; }
22546    	
22547    	var idNoStaff = 'no_staff_fl' + rowNumber;
22548    	var chkNoStaff = '<input type="checkbox" id="' + idNoStaff + '"' + noStaffChecked + ' onchange="GLO.Provider.Resource.changeNoStaff(this, event)"/>';
22549    	var lblNoStaff = '<label for="' + idNoStaff + '" title="This Service has no staff (only a resource)">' + chkNoStaff + 'No Staff</label>';
22550    	
22551    	var idBookOnline = 'book_resource_online_fl' + rowNumber;
22552    	var chkBookOnline = '<input type="checkbox" id="' + idBookOnline + '"' + allowOnlineChecked + ' onchange="GLO.Provider.Resource.changeBookOnline(this, event)"/>';
22553    	var lblBookOnline = '<label for="' + idBookOnline + '" title="Allow Clients to pick which resource when booking online">' + chkBookOnline + 'Book Online</label>'
22554    	
22555    	var tr = '<tr class="resource-service" service_group_id="' + sgid + '" service_id="' + svcid + '">'
22556        			+ removeIcon
22557        			+ '<td class="service-group" style="color: ' + sgcolor + ';">' + sgname + '</td>'
22558        			+ '<td class="service">' + svcname + '</td>'
22559        			+ '<td class="no_staff_fl">' + lblNoStaff + '</td>'
22560	                + '<td class="book_resource_online_fl">' + lblBookOnline + '</td>'
22561    			+ '</tr>';
22562    	
22563    	tbl.append(tr);
22564    }
22565    
22566    _conResourceAdmin.closeResourceGroup = function() {
22567    	var j = $('#manage-resource-container').addClass('hide');
22568    	
22569    	$('#manage-resource-add-button').find('.btnAdd').hide().fadeIn(2400);
22570    	$('#manage-resource-group-container2').removeClass('hide').find('.click-to-edit').removeClass('hide');
22571    	$('#resource-group-list').find('tr').removeClass('selected').removeClass('hide');
22572    	
22573    	_rgNameAutoSave.off();
22574    	$('#manage-resource-group-title').removeClass('display-back');
22575    	$('#manage-resource-group-container').removeClass('editing-specific-resource-group');
22576    }
22577    
22578    _conResourceAdmin.openAddResourceGroup = function() {
22579    	var msg = $('<div id="pop-resource-group-add"> <h1 class="friendly-msg2">' + SA.Resource.AddResourceType + '</h1>'
22580    					+ '<div class="friendly-msg2"> <input type="text" id="Resource_Group_Name_vc" placeholder="' + SA.Resource.ResourceType + '"/> </div> </div>');
22581		
22582		_openSimplePopup(msg, GLO.Provider.Resource.addResourceGroup);
22583    }
22584    
22585    function _updateServiceAttribute(sgid, svcid, attributeName, attributeValue) {
22586    	var jsvc = $('#allServiceOptions').find('select#crSvc' + sgid).find('option[value="' + svcid + '"]');
22587    	jsvc.attr(attributeName, attributeValue);
22588    }
22589    
22590    _conResourceAdmin.changeNoStaff = function(element, event) {
22591    	var tr = $(element).closest('tr.resource-service');
22592    	var value = 0, sgid = tr.attr('service_group_id'), svcid = tr.attr('service_id');
22593    	
22594    	if (element.checked) { value = 1; }
22595    	
22596    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceService?sgid=' + sgid + '&svcid=' + svcid + '&nostaff=' + value;
22597        
22598        $.ajax({ type: "POST", url: uri, "cache": false })
22599            .success(function(data, textStatus, jqXHR) {
22600                _updateServiceAttribute(sgid, svcid, 'no_staff_fl', value);
22601		    });
22602            //.error(function(jqXHR, textStatus, errorThrown) { });
22603    }
22604    _conResourceAdmin.changeBookOnline = function(element, event) {
22605    	var tr = $(element).closest('tr.resource-service');
22606    	var value = 0, sgid = tr.attr('service_group_id'), svcid = tr.attr('service_id');
22607    	
22608    	if (element.checked) { value = 1; }
22609    	
22610    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceService?sgid=' + sgid + '&svcid=' + svcid + '&bookonline=' + value;
22611        
22612        $.ajax({ type: "POST", url: uri, "cache": false })
22613            .success(function(data, textStatus, jqXHR) {
22614                _updateServiceAttribute(sgid, svcid, 'book_resource_online_fl', value);
22615		    });
22616            //.error(function(jqXHR, textStatus, errorThrown) { });
22617    }
22618    
22619    _conResourceAdmin.addResourceGroup = function() {
22620    	var jpop = $('#pop-resource-group-add').closest('.glopop');
22621        var name = UTIL.coalesce(jpop.find('#Resource_Group_Name_vc').val(), 'Resource Type #' + (_jsonResource.length + 1));
22622        
22623        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/AddResourceGroup?name_vc=' + encodeURIComponent(name);
22624        GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
22625        
22626        $.ajax({ type: "POST", url: uri, "cache": false })
22627            .success(function(data, textStatus, jqXHR) {
22628                GLO.Popup.close(jpop);
22629                var rgid = $(data).attr('resource_group_id');
22630                
22631                _jsonResource.push({ "resource_group_id": rgid, "resource_group_name_vc": name, "resources": [], "servicegroups": [] });
22632                
22633                var tr = '<tr resource_group_id="' + rgid + '" onclick="GLO.Provider.Resource.openResourceGroup(this)">'
22634                			+ '<td class="resource-group-drag-handle"> <b class="drag-handle"></b> </td>'
22635                			+ '<td class="resource-group-name">' + name + '</td>'
22636                        	+ '<td class="service-list"></td>'
22637                    	+ '</tr>';
22638                
22639                var j = $('#resource-group-list');
22640                j.find('.no-result-row').remove();
22641                var tbody = j.find('tbody').append(tr)
22642                
22643                tbody.find('tr[resource_group_id="' + rgid + '"]').click();
22644		    })
22645            .error(function(jqXHR, textStatus, errorThrown) {
22646                GLO.Popup.Error('Unable to add this resource type.  Please try again.');
22647                GLO.UI.Form.resetProcessing();
22648            });
22649    }
22650    
22651    _conResourceAdmin.updateResourceGroup = function() {
22652    	var name = UTIL.coalesce($('#manage-resource-container').find('#Resource_Group_Name_vc').val(), 'Resource Type #' + (_jsonResource.length + 1));
22653        var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22654        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResourceGroup?resource_group_id=' + rgid + '&name_vc=' + encodeURIComponent(name);
22655        
22656        $.ajax({ type: "POST", url: uri, "cache": false })
22657            .success(function(data, textStatus, jqXHR) {
22658                _conResourceAdmin.updateResourceGroupComplete();
22659		    })
22660            .error(function(jqXHR, textStatus, errorThrown) {
22661                GLO.Popup.Error('Unable to add this resource type.  Please try again.');
22662                GLO.UI.Form.resetProcessing();
22663            });
22664    }
22665    
22666    _conResourceAdmin.updateResourceGroupComplete = function() {
22667    	var tr = $('#resource-group-list').find('tr.selected');
22668    	var rgid = tr.attr('resource_group_id');
22669    	var name = UTIL.coalesce($('#manage-resource-container').find('#Resource_Group_Name_vc').val(), 'Resource Type #' + (_jsonResource.length + 1));
22670        
22671        tr.find('.resource-group-name').text(name);
22672    	_getJsonObj(rgid).resource_group_name_vc = name;
22673    }
22674    
22675    _conResourceAdmin.removeResourceGroup = function() {
22676    	var css = 'letter-spacing: 1px; line-height: 200%; text-align: center; font-size: larger;';
22677    	new GLO.Popup.Confirm('<div style="' + css + '">Delete this Group of Resources?</div>', GLO.Provider.Resource.removeResourceGroupConfirmed);
22678    }
22679    
22680    _conResourceAdmin.removeResourceGroupConfirmed = function() {
22681    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22682        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/DeleteResourceGroup?resource_group_id=' + rgid;
22683        
22684        new GLO.Popup.Processing('Deleting Resource Type and associated Resources...');
22685        
22686        $.ajax({ type: "POST", url: uri, "cache": false })
22687            .success(function(data, textStatus, jqXHR) {
22688                document.location = document.location.origin + document.location.pathname + document.location.search;
22689		    })
22690            .error(function(jqXHR, textStatus, errorThrown) {
22691                GLO.Popup.Error('Unable to delete this resource type.  Please try again.');
22692                GLO.UI.Form.resetProcessing();
22693            });
22694    }
22695    
22696    _conResourceAdmin.openUpdateResource = function(td) {
22697    	td = $(td);
22698    	var rid = td.closest('tr').attr('resource_id');
22699    	var name = td.text();
22700    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22701    	
22702    	var msg = $('<div id="pop-resource-update" resource_group_id="' + rgid + '" resource_id="' + rid + '">'
22703					+ '<h1 class="friendly-msg2">' + SA.Resource.UpdateResource + '</h1>'
22704					+ '<div class="friendly-msg2"> <input type="text" id="Resource_Name_vc" value="' + name + '" placeholder="' + SA.Resource.UpdateResource + '"/> </div>'
22705    			+ '</div>');
22706		
22707		_openSimplePopup(msg, GLO.Provider.Resource.updateResource);
22708    }
22709    
22710    function _openSimplePopup(msg, saveFn) {
22711    	var oj = new GLO.Popup.Custom(msg, saveFn);
22712    	
22713    	var jpop = oj.getPopup().addClass('no-persist');
22714    	var jbtn = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "letter-spacing": "1px" });
22715    	jbtn.find('.btnNo').removeClass('btnNo').addClass('btnCancel').find('a').text('Cancel');
22716    	jbtn.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('a').text('Save');
22717    }
22718    
22719    _conResourceAdmin.addResource = function(td) {
22720    	var j = $('#manage-resource-list');
22721    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22722    	var name = j.find('#Resource_Name_vc').val();
22723    	
22724        if (UTIL.isEmpty(name)) {
22725        	new GLO.Popup.Warning('Please Enter Resource Name', function() { $('#manage-resource-list').find('#Resource_Name_vc').focus(); });
22726        	return;
22727        }
22728        
22729        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/AddResource?resource_group_id=' + rgid + '&name_vc=' + encodeURIComponent(name);
22730        GLO.UI.Form.beginProcessing( j.find('.btnAdd') );
22731        
22732        $.ajax({ type: "POST", url: uri, "cache": false })
22733            .success(function(data, textStatus, jqXHR) {
22734                var tbody = $('#resource-list').find('tbody').removeClass('hide');
22735    			var trs = tbody.find('tr');
22736    			var trlast = trs.eq(trs.length - 1);
22737    			
22738    			rid = parseInt($(data).attr('resource_id'));
22739                var isNoClientBook = trlast.find('.resource-restrict-client-booking input').prop('checked');
22740                var isBookOnline = trlast.find('.resource-book-online input').prop('checked');
22741    			
22742    			var jsonResource = { "resource_id": rid, "resource_name_vc": name, "no_client_booking_fl": isNoClientBook, "book_online_fl": isBookOnline };
22743                var rg = _getJsonObj(rgid);
22744                rg.resources.push(jsonResource);
22745    			
22746    			var tr = _getResourceHtm(jsonResource, trs.length + 1);
22747    			tbody.append(tr);
22748                
22749                j.find('#Resource_Name_vc').val('');
22750                GLO.UI.Form.resetProcessing();
22751		    })
22752            .error(function(jqXHR, textStatus, errorThrown) {
22753                GLO.Popup.Error('Unable to add this resource type.  Please try again.');
22754                GLO.UI.Form.resetProcessing();
22755            });
22756    }
22757    
22758    _conResourceAdmin.updateResource = function() {
22759    	var jpop = $('#pop-resource-update').addClass('no-persist');
22760    	var rgid = jpop.attr('resource_group_id');
22761    	var rid = jpop.attr('resource_id');
22762        var name = jpop.find('#Resource_Name_vc').val();
22763        
22764        if (UTIL.isEmpty(name)) {
22765        	new GLO.Popup.Warning('Please Enter Resource Name', function() { $('#pop-resource-update').find('#Resource_Name_vc').focus(); });
22766        	return;
22767        }
22768        
22769        jpop = jpop.closest('.glopop');
22770        var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/UpdateResource?resource_id=' + rid + '&resource_group_id=' + rgid + '&name_vc=' + encodeURIComponent(name);
22771        GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
22772        
22773        $.ajax({ type: "POST", url: uri, "cache": false })
22774            .success(function(data, textStatus, jqXHR) {
22775                GLO.Popup.close(jpop);
22776                var rg = _getJsonObj(rgid);
22777                
22778                for (var i=0; i < rg.resources.length; i++) {
22779                	if (rid == rg.resources[i].resource_id) {
22780                		rg.resources[i].resource_name_vc = name;
22781                	}
22782                }
22783                
22784                var tr = $('#resource-list').find('tr');
22785                
22786                for (var i=0; i < tr.length; i++) {
22787                	if (rid == tr.eq(i).attr('resource_id')) {
22788                		tr.eq(i).find('td.resource').text(name);
22789                	}
22790                }
22791		    })
22792            .error(function(jqXHR, textStatus, errorThrown) {
22793                GLO.Popup.Error('Unable to add this resource type.  Please try again.');
22794                GLO.UI.Form.resetProcessing();
22795            });
22796    }
22797    
22798    _conResourceAdmin.removeService = function(element) {
22799    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22800    	var tr = $(element).closest('tr');
22801    	var sgid = tr.attr('service_group_id');
22802    	var svcid = tr.attr('service_id');
22803    	var name = tr.find('td.service').text();
22804    	
22805    	var fn = function() {
22806    		GLO.Provider.Resource.removeServiceConfirmed(tr, rgid, sgid, svcid);
22807    	};
22808    	
22809    	var css = 'letter-spacing: 1px; line-height: 200%; text-align: center; font-size: larger;';
22810    	new GLO.Popup.Confirm('<div style="' + css + '">Delete ' + name + '?</div>', fn);
22811    }
22812    
22813    _conResourceAdmin.removeServiceConfirmed = function(tr, rgid, sgid, svcid) {
22814    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/RemoveService?resource_group_id=' + rgid + '&service_group_id=' + sgid + '&service_id=' + svcid;
22815        var oj = new GLO.Popup.Processing('<div style="letter-spacing: 1px; line-height: 200%; letter-spacing: 1px;">Deleting Service</div>');
22816        var jservices = $('#manage-resource-type-service').find('tr.resource-service[service_group_id="' + sgid + '"]');
22817        
22818        $.ajax({ type: "POST", url: uri, "cache": false })
22819            .success(function(data, textStatus, jqXHR) {
22820                oj.close();
22821                var rg = _getJsonObj(rgid);
22822                
22823                for (var sg=0; sg < rg.servicegroups.length; sg++) {
22824                	if (rg.servicegroups[sg].service_group_id == sgid) {
22825                		var svc = rg.servicegroups[sg].services;
22826                		
22827                		for (var s=0; s < svc.length; s++) {
22828		                	if (svc[s].service_id == svcid) {
22829		                		svc.splice(s, 1);
22830		                		break;
22831		                	}
22832		                }
22833		                
22834		                break;
22835                	}
22836                }
22837                
22838                tr.remove();
22839                
22840                if (jservices.length === 1) {
22841                	_conResourceAdmin.removeServiceGroupFromList(rgid, sgid);
22842                }
22843		    })
22844            .error(function(jqXHR, textStatus, errorThrown) {
22845                oj.close();
22846                GLO.Popup.Error('Unable to delete this service.  Please try again.');
22847                GLO.UI.Form.resetProcessing();
22848            });
22849    }
22850    
22851    _conResourceAdmin.removeServiceGroupFromList = function(rgid, sgid) {
22852    	$('#resource-group-list').find('tr[resource_group_id="' + rgid + '"]').find('td.service-list').find('span[sgid="' + sgid + '"]').remove();
22853    }
22854    _conResourceAdmin.addServiceGroupToList = function(rgid, sgid, sgname, sgcolor) {
22855    	$('#resource-group-list').find('tr[resource_group_id="' + rgid + '"]').find('td.service-list').append(', <span sgid="' + sgid + '" style="color: ' + sgcolor + ';">' + sgname + '</span>');
22856    }
22857    
22858    _conResourceAdmin.addServiceGroup = function(dd) {
22859    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22860    	var sgid = dd.value;
22861    	var sgname = dd.options[dd.selectedIndex].text;
22862    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/AddServiceGroup?resource_group_id=' + rgid + '&service_group_id=' + sgid;
22863        
22864        if (UTIL.coalesceInt(sgid, 0) === 0) { return; }
22865        
22866        var htm = '<div style="letter-spacing: 2px; font-size: larger;">Adding Services to Resource...</div>';
22867        var ojProcessing = new GLO.Popup.Processing(htm);
22868        
22869        $.ajax({ type: "POST", url: uri, "cache": false })
22870            .success(function(data, textStatus, jqXHR) {
22871                var options = $('#allServiceOptions #crSvc' + sgid).find('option');
22872                var rg = _getJsonObj(rgid);
22873                var j = $('#manage-resource-type-service');
22874                
22875                var ddSG = j.find('#Service_Group_id');
22876                ddSG.find('option[value="' + sgid + '"]').remove();
22877                
22878                var tbl = j.find('tbody').removeClass('hide');
22879                var removeIcon = '<td class="remove-icon"> <span title="Remove service" onclick="GLO.Provider.Resource.removeService(this)" class="ui-icon ui-icon-circle-close"></span> </td>';
22880                var arrSvc = [], servicesAdded = 0;
22881                
22882                for (var i=0; i < options.length; i++) {
22883	                if (UTIL.isEmpty(options.eq(i).attr('resource_group_id'))) {
22884		                var svcid = options.eq(i).attr('value');
22885		                var svcname = options.eq(i).text();
22886		                var noStaffRequired = UTIL.parseBool(options.eq(i).attr('no_staff_fl'));
22887		                var canBookResourceOnline = UTIL.parseBool(options.eq(i).attr('book_resource_online_fl'));
22888		                var sgcolor = $(data).attr('rgb_color');
22889		                
22890		                arrSvc.push({ "service_id": svcid, "service_name_vc": svcname });
22891		                _addServiceRowToTable(tbl, sgid, sgname, sgcolor, svcid, svcname, noStaffRequired, canBookResourceOnline);
22892		                ++servicesAdded;
22893	                }
22894                }
22895                
22896                if (servicesAdded > 0) {
22897                	rg.servicegroups.push({ "service_group_id": sgid, "service_group_name_vc": sgname, "css_class_vc": "", "css_color_vc": "", "services": arrSvc });
22898                	_conResourceAdmin.addServiceGroupToList(rgid, sgid, sgname, sgcolor);
22899                } else {
22900                	var msg1 = '<p>All ' + sgname + ' Services already attached to a Resource</p>';
22901                	var msg2 = '<p style="letter-spacing: 0; font-size: smaller;">To attach these services to a different resource first remove from current resource</p>';
22902                	var htm = '<div id="pop-warn-no-service">' + msg1 + msg2 + '</div>';
22903                	GLO.Popup.Warning.open(htm, 'Services Already Attached to Resource');
22904                }
22905                
22906                $('#manage-resource-container #Resource_Group_Name_vc').focus();			//= move focus away from SG drop down so don't accidentally select another service group.
22907                ojProcessing.close();			//GLO.UI.Form.resetProcessing();
22908		    })
22909            .error(function(jqXHR, textStatus, errorThrown) {
22910                GLO.Popup.Error('Unable to add this resource type.  Please try again.');
22911                GLO.UI.Form.resetProcessing();
22912            });
22913    }
22914    
22915    _conResourceAdmin.removeResource = function(td) {
22916    	var rgid = $('#resource-group-list').find('tr.selected').attr('resource_group_id');
22917    	var tr = $(td).closest('tr');
22918    	var rid = tr.attr('resource_id');
22919    	var name = tr.find('td.resource').text();
22920    	
22921    	var fn = function() {
22922    		GLO.Provider.Resource.removeResourceConfirmed(rgid, rid);
22923    	};
22924    	
22925    	var css = 'letter-spacing: 1px; line-height: 200%; text-align: center; font-size: larger;';
22926    	new GLO.Popup.Confirm('<div style="' + css + '">Delete ' + name + '?</div>', fn);
22927    }
22928    
22929    _conResourceAdmin.removeResourceConfirmed = function(rgid, rid) {
22930    	var uri = GLO.Link.WebsiteDomain + 'ScheduleConfig/DeleteResource?resource_group_id=' + rgid + '&resource_id=' + rid;
22931        
22932        var oj = new GLO.Popup.Processing('<div style="letter-spacing: 1px; line-height: 200%; letter-spacing: 1px;">Deleting Resource</div>');
22933        
22934        $.ajax({ type: "POST", url: uri, "cache": false })
22935            .success(function(data, textStatus, jqXHR) {
22936                oj.close();
22937                var rg = _getJsonObj(rgid);
22938                
22939                for (var r=0; r < rg.resources.length; r++) {
22940                	if (rg.resources[r].resource_id == rid) {
22941                		rg.resources.splice(r, 1);
22942		                break;
22943                	}
22944                }
22945                
22946                $('#resource-list').find('tr[resource_id="' + rid + '"]').remove();
22947		    })
22948            .error(function(jqXHR, textStatus, errorThrown) {
22949                oj.close();
22950                GLO.Popup.Error('Unable to delete this resource.  Please try again.');
22951                GLO.UI.Form.resetProcessing();
22952            });
22953    }
22954    
22955    return _conResourceAdmin;
22956})();
22957
22958
22959GLO.Provider.Loyalty = (function() {
22960    function _cLoyalty() { }
22961    var _isEnabledOnLoad = false, _popOpenResetPoints = null;
22962    
22963    _cLoyalty.init = function(start, earnCode, redeemCode) {
22964        var j = $('#manage-loyalty');
22965        var jearn = j.find('#Loyalty_Earn_cd'), jredeem = j.find('#Loyalty_Redeem_cd');
22966        var yearRange = GLO.UI.getYearRange(true);					//'2012:' + (new Date().getFullYear() + 2);
22967        var isPerVisit = j.find('#Loyalty_Earn_By_Visit_fl').prop('checked');
22968        
22969        var jstart = j.find('#Loyalty_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, maxDate: 0
22970        							, changeYear: true, yearRange: yearRange, calculateWeek: UTIL.datePickerCalculateWeek, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadD
22970atepicker });
22971		
22972    	if (UTIL.isDate(start)) {
22973    		jstart.val(start).attr('original_value', start);
22974    	}
22975    	
22976    	if (earnCode > 0 || isPerVisit) {
22977    		j.find('#Loyalty_Enable_fl').prop('checked', true).change();
22978    		jearn.val(earnCode);
22979    		
22980    		_isEnabledOnLoad = true;
22981    	}
22982    	
22983    	if (redeemCode > 0) {
22984    		jredeem.val(redeemCode);
22985    	} else {
22986    		j.find('#Loyalty_Redeem_By_Dollar_fl').prop('checked', false).change();
22987    	}
22988    	
22989    	jearn.removeClass('hide');
22990    	jredeem.removeClass('hide');
22991    	
22992    	j.find('#Loyalty_Earn_By_Dollar_fl').change();
22993    	j.find('#Loyalty_Earn_By_Visit_fl').change();
22994    	
22995    	GLO.Info.init();
22996    	var isInvalidPackage = ((GLO.Info.providerPackage == 4 && UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 79) || GLO.Info.providerPackage == 1);
22997    	
22998    	if (GLO.Info.roleType < 220 || isInvalidPackage) {
22999    		j.find('input,select').prop('disabled', true);
23000    		j.find('.btnSave').remove();
23001    		
23002    		if (isInvalidPackage) {
23003    			var msg = 'Gold package required to enable Loyalty';
23004    		} else {
23005    			var msg = 'Manage or Admin required to setup Loyalty';
23006    		}
23007    		
23008    		GLO.Popup.Info.open(msg, 'Loyalty Restriction');
23009    	}
23010    	
23011    	j.find("#manage-loyalty-earn input:checkbox").change(UI.CrossOutCheckbox).change();
23012    	//_initAutoSave(j);
23013    	_initDetectChange(j);
23014    	_initLoyaltyUrl();
23015    }
23016    function _initLoyaltyUrl() {
23017    	var highlight = GLO.Uri.url('highlight');
23018    	
23019    	if (!UTIL.isEmpty(highlight)) {
23020    		var jhigh = $('#manage-loyalty').find('#' + highlight + ', .' + highlight);
23021    		UI.highlight(jhigh, 300, 6000, true);
23022    	}
23023    }
23024    function _initDetectChange(jcontainer) {
23025    	var jlist = jcontainer.find('#Loyalty_Enable_fl, #Loyalty_Earn_cd, #Loyalty_Redeem_cd, #Loyalty_Start_dt, #Loyalty_Earn_By_Dollar_fl, #Loyalty_Earn_By_Visit_fl, #Loyalty_Earn1_pct, #Loyalty_Earn2_pct, #Loyalty_Redeem1_pct, #Loyalty_Redeem2_pct, #Loyalty_Cash_Bonus_pct');
23026    	jlist.change(GLO.Provider.Loyalty.changeByUser);
23027    	
23028    	jlist.keyup(function(event) {
23029    		if (UI.keyPressIsNumber(event)) {
23030    			GLO.Provider.Loyalty.changeByUser(this, event);
23031    		}
23032    	});
23033    }
23034    function _initAutoSave(jcontainer) {
23035    	var jfields = jcontainer.find('input,select');
23036    	var uriSave = GLO.Link.WebsiteDomain + 'loyalty/save';
23037		new UI.AutoSave(jfields, uriSave, GLO.Provider.Loyalty.afterAutoSave, 2400);
23038    }
23039    
23040    _cLoyalty.changePerCheckbox = function(checkbox) {
23041    	var jparent = $(checkbox).closest('div');
23042    	var jfields = jparent.find('input[type="number"], select');
23043    	
23044    	if ($(checkbox).prop('checked')) {
23045    		jfields.prop('disabled', false);
23046    		jparent.css({ "text-decoration": "" }).removeClass('is-disabled').addClass('is-enabled');
23047    	} else {
23048    		jfields.prop('disabled', true);
23049    		jparent.css({ "text-decoration": "line-through" }).removeClass('is-enabled').addClass('is-disabled');
23050    	}
23051    }
23052    
23053    _cLoyalty.afterAutoSave = function() {
23054    
23055    }
23056    
23057    _cLoyalty.changeEnable = function() {
23058    	var j = $('#manage-loyalty');
23059    	
23060    	if (j.find('#Loyalty_Enable_fl').prop('checked')) {
23061    		j.addClass('loyalty-enabled');
23062    		j.find('#Loyalty_Redeem_By_Dollar_fl').prop('checked', false).click();
23063    	} else {
23064    		j.removeClass('loyalty-enabled');
23065    	}
23066    }
23067    
23068    _cLoyalty.changeByUser = function(element, event) {
23069    	var j = $('#manage-loyalty');
23070    	var jsave = j.find('.btnSave');
23071    	
23072    	if (!jsave.hasClass('btn-has-change')) {
23073	    	jsave.addClass('btn-has-change');
23074	    	
23075	    	window.onbeforeunload = function() {
23076				return 'Are you sure you want to leave without saving changes?';
23077			};
23078    	}
23079    }
23080    _cLoyalty.changeDeleteBonus = function(element) {
23081    	var jbonus = $('#pop-confirm-reset-loyalty-bonus-inner');
23082    	
23083    	if ($(element).prop('checked')) {
23084    		jbonus.removeClass('hide');
23085    	} else {
23086    		jbonus.addClass('hide');
23087    	}
23088    	
23089    	_popOpenResetPoints.realign();
23090    	setTimeout(_popOpenResetPoints.realign, 80);
23091    }
23092    _cLoyalty.openResetPoints = function(btn) {
23093    	var jmain = $('#manage-loyalty');
23094    	
23095    	if (jmain.find('.btnSave.btn-has-change').length) {
23096    		GLO.Popup.Warning.open('Loyalty Program has unsaved changes<br/>Please save changes before deleting loyalting points', 'Un-Saved Changes');
23097    		return;
23098    	}
23099    	
23100    	var startDate = jmain.find('#Loyalty_Start_dt').val();
23101    	var msg = 'Delete Loyalty Points Earned by Clients';
23102		
23103		if (UTIL.isDate(startDate)) {
23104			msg += ' before ' + startDate;
23105			var origDate = jmain.find('#Loyalty_Start_dt').attr('original_value');
23106			
23107			if (new Date(startDate).toGloDate() != new Date(startDate).toGloDate()) {
23108				var warningMsg = '<p>Please save change to <b>Loyalty Program Start Date</b> before <b style="color: red;">Deleting Points</b></p>';
23109				GLO.Popup.Warning.open(warningMsg, 'Un-Saved Changes');
23110				return;
23111			}
23112		}
23113		
23114		var checkboxBonus = '<div id="pop-confirm-reset-loyalty-bonus-checkbox">'
23115					+ '<input type="checkbox" id="Loyalty_Delete_Bonus_fl" onchange="GLO.Provider.Loyalty.changeDeleteBonus(this)" style="height: 24px; width: 24px; margin-top: -4px;">'
23116					+ '<label for="Loyalty_Delete_Bonus_fl" style="font-weight: bold; font-size: 120%;">Delete All Bonus Points</label>'
23117				+ '</div>'
23118		
23119		var passwordInput = '<div id="pop-confirm-reset-loyalty-password">'
23120					+ '<label for="Delete_Loyalty_Password_vc">Enter Password to Confirm Delete</label>'
23121					+ '<input type="password" id="Delete_Loyalty_Password_vc" maxlength="50" style="width: 150px;">'
23122				+ '</div>'
23123		var msgIncludes = '<span class="narrow-text">(this includes any loyalty points uploaded from another scheduling system or loyalty program)</span>';
23124		var msgBonus = '<p style="padding: 12px 0; line-height: 1.4;">Delete Bonus Loyalty Points given to Clients ' + msgIncludes + '</p>';
23125		var msgWarning = '<p style="text-align: center; font-weight: bold; font-size: 120%; color: red;">Be careful, this cannot be undone!</p>';
23126		var divBonusInner = '<div id="pop-confirm-reset-loyalty-bonus-inner" class="hide">' + msgBonus + msgWarning + passwordInput + '</div>';
23127		var divBonus = '<div id="pop-confirm-reset-loyalty-bonus">' + checkboxBonus + divBonusInner + '</div>';
23128		
23129		var htmMsg = '<p style="text-align: center;"> <b class="checkmark-icon"></b> ' + msg + '</p>';
23130		var htm = '<div id="pop-confirm-reset-loyalty">' + htmMsg + divBonus + '</div>';
23131		_popOpenResetPoints = GLO.Popup.Custom.openSimple(htm, 'Delete Client Loyalty Points', GLO.Provider.Loyalty.saveResetPoints, null, true);
23132		
23133		var jbtns = _popOpenResetPoints.getPopup().find('.pop-buttons').addClass('pop-buttons2').css({ "max-width": "500px", "font-size": "150%" });
23134		jbtns.find('.btnSave').removeClass('btnSave').addClass('btnDelete').css({ "float": "right", "width": "180px", "margin": "0" }).find('>a').text('Delete Points');
23135    }
23136    _cLoyalty.saveResetPoints = function() {
23137    	var jpop = $('#pop-confirm-reset-loyalty').closest('.glopop');
23138    	var isDeleteBonus = jpop.find('#Loyalty_Delete_Bonus_fl').prop('checked');
23139    	var password = jpop.find('#Delete_Loyalty_Password_vc').val();
23140    	
23141    	var uri = GLO.Link.WebsiteDomain + 'loyalty/DeletePoints';
23142		var jd = { "isRefreshPoints": 0, "isDeleteBonus": isDeleteBonus, "password": password };
23143		
23144    	var jstart = $('#manage-loyalty #Loyalty_Start_dt');
23145    	var startDate = jstart.val(), startDateOriginal = jstart.attr('original_value');
23146    	
23147		if (UTIL.isDate(startDate)) {			// && new Date(startDate).toGloDate() != new Date(startDateOriginal).toGloDate()
23148			jd.isRefreshPoints = 1;
23149		}
23150    	
23151    	var jbtn = jpop.find('.btnDelete');
23152		GLO.UI.Form.beginProcessing(jbtn);
23153		
23154        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
23155            .success(function(data, textStatus, jqXHR) {
23156                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23157            	var jresponse = $(data);
23158            	
23159            	if (!UTIL.isEmpty(jresponse.attr('error_cd')) || jresponse.hasClass('error')) {
23160            		GLO.Popup.Error.open(data, 'Unable to Delete Loyalty Points');
23161            	} else if (!UTIL.isEmpty(jresponse.attr('warning_cd')) || jresponse.hasClass('warning')) {
23162            		GLO.Popup.Error.open(data, 'Issue Deleting Loyalty Points');
23163            	} else {
23164	            	GLO.Popup.closeIfExist(jpop);
23165	            	GLO.Popup.Success.open('Loyalty Points Deleted', 'Delete Successful', 19000);
23166	            	_popOpenResetPoints = null;
23167            	}
23168            })
23169            .error(function(jqXHR, textStatus, errorThrown) {
23170                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23171                GLO.Popup.Error.open('Please try again later', 'Unable to Delete Loyalty Points');
23172            });
23173    }
23174    
23175    function _saveIsValid(jcontainer) {
23176    	var fnSave = function() { GLO.Provider.Loyalty.save(true); }
23177    	
23178    	if (!_isEnabledOnLoad && !jcontainer.find('#Loyalty_Enable_fl').prop('checked')) {
23179    		var fnAction = function() {
23180    			GLO.Popup.close($('#pop-confirm-loyalty-enable').closest('.glopop'));
23181    			$('#manage-loyalty').find('#Loyalty_Enable_fl').prop('checked', true).change();
23182    			GLO.Provider.Loyalty.save();
23183    		}
23184    		
23185    		var htm = '<div id="pop-confirm-loyalty-enable" style="margin-top: 8px;">Do you want to Enable Loyalty?</div>';
23186    		GLO.Popup.Confirm.open(htm, 'Enable Loyalty?', fnAction, fnSave);
23187    		return false;
23188    	}
23189    	
23190    	return true;
23191    }
23192    
23193    _cLoyalty.save = function(isOverride) {
23194    	var uri = GLO.Link.WebsiteDomain + 'loyalty/save';
23195		var j = $('#manage-loyalty');
23196		var jbtn = j.find('.btnSave');
23197		
23198		if (!isOverride) {
23199			if (!_saveIsValid(j)) { return; }
23200		}
23201		
23202		GLO.UI.Form.beginProcessing(jbtn);
23203		
23204        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: j.serialize() })
23205            .success(function(data, textStatus, jqXHR) {
23206                window.onbeforeunload = null;
23207                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23208            	jbtn.removeClass('btn-has-change');
23209            	
23210            	new GLO.Popup.Success(data, 19000);
23211            })
23212            .error(function(jqXHR, textStatus, errorThrown) {
23213                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23214                //new GLO.Popup.Error('Unable to order the calendars staff');
23215            });
23216    }
23217    
23218    return _cLoyalty;
23219})();
23220
23221GLO.Provider.ShoppingCart = (function() {
23222	function _cShoppingCart() { }
23223
23224	_cShoppingCart.initConfig = function(cartConfig) {
23225		if (cartConfig !== null && cartConfig !== undefined) {
23226			var j = $('#manage-cart');
23227			j.find('#Shipping_Policy_Note_vc').val(cartConfig.ShippingPolicyText);
23228			j.find('#Refund_Policy_Note_vc').val(cartConfig.RefundPolicyText);
23229			j.find('#store_popup_note_vc').val(cartConfig.PopupText);
23230			if (cartConfig.PopupImagePath !== '') {
23231				var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + cartConfig.PopupImagePath;
23232				j.find('#store-popup-image-path').val(cartConfig.PopupImagePath);
23233				j.find('#store-popup-image-preview').attr("src",img_path);
23234				$('.store-popup-add-image').addClass('hide');
23235				$('.store-popup-remove-image').removeClass('hide');
23236			}
23237			j.find('input[name="Shopping_Cart_Enable_fl"]')[0].checked = cartConfig.CartEnabled;
23238			j.find('input[name="Sell_Memberships_fl"]')[0].checked = cartConfig.SellMemberships;
23239			j.find('input[name="Sell_Packages_fl"]')[0].checked = cartConfig.SellPackages;
23240		} else {
23241			GLO.UI.Form.resetProcessing(); 		
23242			new GLO.Popup.Error('Unable to retrieve Store settings. Please refresh page.');
23243		}
23244		
23245		GLO.Provider.ShoppingCart.changeEnable();
23246	}
23247
23248	_cShoppingCart.validateEnable = function() {
23249		//check if on gold plan
23250		//check if products are setupo
23251		//check if merchant account is setup
23252		
23253		initConfig
23254	}
23255
23256	_cShoppingCart.changeEnable = function() {
23257		var j = $('#manage-cart');
23258    	
23259    	if (j.find('#Shopping_Cart_Enable_fl').prop('checked')) {
23260			j.addClass('is-enabled');
23261    	} else {
23262			j.removeClass('is-enabled');
23263    	}
23264    }	
23265
23266	_cShoppingCart.saveConfig = function() {
23267    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/cartconfig';
23268		var j = $('#manage-cart');
23269		var jbtn = j.find('.btnSave');
23270		
23271		var ShippingPolicyNote = j.find('#Shipping_Policy_Note_vc').val();
23272		var RefundPolicyNote = j.find('#Refund_Policy_Note_vc').val();
23273		var StorePopupNote = j.find('#store_popup_note_vc').val();
23274		var PopupImagePath = j.find('#store-popup-image-path').val();
23275		var EnableCart = j.find('input[name="Shopping_Cart_Enable_fl"]:checked').val();
23276		var EnableMemberships = j.find('input[name="Sell_Memberships_fl"]:checked').val();
23277		var EnablePackages = j.find('input[name="Sell_Packages_fl"]:checked').val();
23278		var UpdatedByStaffId = GLO.Info.getStaffId();
23279
23280		
23281		GLO.UI.Form.beginProcessing(jbtn);
23282		
23283		var viewModel = {
23284			"ProviderId":GLO.Data.provider.id, "ShippingPolicyText": ShippingPolicyNote, "RefundPolicyText": RefundPolicyNote, "CartEnabled": (EnableCart == 'on' ? 'true' : 'false')
23285			, "SellMemberships": (EnableMemberships == 'on' ? 'true' : 'false'), "SellPackages": (EnablePackages == 'on' ? 'true' : 'false'), "UpdatedByStaffId": UpdatedByStaffId,
23286			"PopupText":StorePopupNote,"PopupImagePath":PopupImagePath
23287		}
23288
23289        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: viewModel })
23290            .success(function(data, textStatus, jqXHR) {
23291                window.onbeforeunload = null;
23292                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23293            	jbtn.removeClass('btn-has-change');
23294            	
23295            	GLO.Popup.Success.open('Store settings updated', 'Store Config', 19000);
23296            })
23297            .error(function(jqXHR, textStatus, errorThrown) {
23298                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23299                new GLO.Popup.Error('Unable to update Store settings');
23300            });
23301	}
23302
23303	_cShoppingCart.launchStorePopupImages= function(event) {
23304
23305		GLO.UI.loadBulkitCss();
23306
23307		$('#store-popup-images-container').modal();
23308		var jModal = $('#simplemodal-container #store-popup-images-container');
23309		var h = $(window).height() * 0.8;
23310        var w = $(window).width() * 0.8;
23311        
23312        $.modal.update(h,w);
23313        $(window).resize(); 
23314		$('.modalCloseImg').css("margin-top","20px");
23315		$('.modalCloseImg').css("margin-right","20px");
23316		$('.modalCloseImg').on("click",function() { GLO.Provider.ShoppingCart.closeStorePopupImages(); });
23317		
23318		if (GLO.Info.isMobile()) {
23319			$('#simplemodal-container').draggable({disable:true});
23320		}
23321		$('#simplemodal-container').css("overflow-y","auto");
23322
23323        // var frm = $('#inventory-item-form');
23324		// var iid = frm.find('#Inventory_id').val();
23325
23326		// GLO.Inventory.Item.getItemImages(iid);
23327    }
23328
23329	_cShoppingCart.closeStorePopupImages = function() {
23330
23331		$('.modalCloseImg').off("click");
23332		GLO.UI.removeBulkitCss();
23333	}
23334
23335
23336	_cShoppingCart.uploadImageAndResize = function () {
23337		//define the width to resize e.g 180px
23338		var resize_width = 500;//without px
23339
23340		//get the image selected
23341		var item = document.querySelector('#uploader').files[0];
23342
23343		//create a FileReader
23344		var reader = new FileReader();
23345
23346		//image turned to base64-encoded Data URI.
23347		reader.readAsDataURL(item);
23348		reader.name = item.name;//get the image's name
23349		reader.size = item.size; //get the image's size
23350		reader.onload = function(event) {
23351			var img = new Image();//create a image
23352			img.src = event.target.result;//result is base64-encoded Data URI
23353			img.name = event.target.name;//set name (optional)
23354			img.size = event.target.size;//set size (optional)
23355			img.onload = function(el) {
23356				var elem = document.createElement('canvas');//create a canvas
23357
23358				//scale the image to 600 (width) and keep aspect ratio
23359				var scaleFactor = resize_width / el.target.width;
23360				elem.width = resize_width;
23361				elem.height = el.target.height * scaleFactor;
23362
23363				//draw in canvas
23364				var ctx = elem.getContext('2d');
23365				ctx.drawImage(el.target, 0, 0, elem.width, elem.height);
23366
23367				//get the base64-encoded Data URI from the resize image
23368				var srcEncoded = ctx.canvas.toDataURL('image/png', 1);
23369
23370				//assign it to thumb src
23371				document.querySelector('#store-popup-image').src = srcEncoded;
23372
23373				$('#btnSaveItemImage').removeClass('is-hidden');
23374				$('#btnSaveItemImage').on("click",function() { GLO.Provider.ShoppingCart.saveStorePopupImage(srcEncoded,resize_width); });
23375			}
23376		}
23377	}		
23378
23379	_cShoppingCart.saveStorePopupImage = function(data,width) {
23380
23381		//remove the attached handler
23382		$('#btnSaveItemImage').off("click");
23383		
23384		var jcontainer = $('#uploader');
23385		
23386		//reset error
23387		$('#itemImageUploadErrorMessage').addClass('is-hidden');
23388
23389		var fnCallback = function(jcontainer, fileName, imgId, imgSize) {
23390			if (fileName!=null && fileName.length > 0) {
23391				var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName;
23392				// console.log(img_path);
23393
23394				//clear the image display
23395				document.querySelector('#store-popup-image').src ='';
23396				$('#btnSaveItemImage').addClass('is-hidden');
23397				// $('#btnCloseModal').addClass('is-hidden');			
23398
23399				//set hidden field value
23400				$('#store-popup-image-path').val(fileName);
23401
23402				//assign it to preview src
23403				document.querySelector('#store-popup-image-preview').src = img_path;				
23404				$('.store-popup-add-image').addClass('hide');
23405				$('.store-popup-remove-image').removeClass('hide');
23406
23407				//close the modal
23408				$('.simplemodal-close').click();		
23409				// closeItemOptionUploadColorSwatch	
23410				
23411			}
23412			else {
23413				//display error
23414				$('#itemImageUploadErrorMessage').removeClass('is-hidden');
23415			}
23416		}
23417		
23418		if (SA.Uploader.uploadImage(data, 'png', width, jcontainer, fnCallback)) {
23419			return true;
23420		}
23421	}	
23422
23423	_cShoppingCart.removePopupImage = function(event) {	
23424		$('#store-popup-image-path').val('');
23425
23426		//assign it to preview src
23427		document.querySelector('#store-popup-image-preview').src = '';				
23428		$('.store-popup-add-image').removeClass('hide');
23429		$('.store-popup-remove-image').addClass('hide');
23430	}
23431
23432	
23433	_cShoppingCart.openCreateShipping = function() {
23434		// var jhead = $('#gift-card-manage #report-header-help-gift');
23435		// var customCards = UTIL.coalesceInt(jhead.attr('custom_gift_card_count_sr'), 0);
23436		
23437		var small1 = '<small style="letter-spacing: 0;">(Birthday, Anniversary, Happy Graduation, etc)</small>';
23438		var p1 = '<p>Setup how much you charge for shipping at checkout.</p>';
23439		var p2 = '<p>Create custom flat-rate shipping options for customer to choose from.</p>';
23440		var msg = '<div id="pop-info-shipping-option">' + p1 + p2 + '</div>';
23441		var gcLabel = 'Shipping Rate ';
23442		
23443		if (innerWidth < 400) { gcLabel = ''; }
23444		
23445		var lblName = '<label for="Shipping_Option_Name_vc">' + gcLabel + 'Name</label>';
23446		var inputName = '<input id="Shipping_Option_Name_vc" type="text" placeholder="Shipping Rate Name" value="Flat-rate shipping"/>';
23447		var htmName = '<div id="pop-create-shipping-option-name">' + lblName + inputName + '</div>';
23448		
23449		var lblAmount = '<label for="Shipping_Option_Price_mn">' + gcLabel + 'Amount</label>';
23450		var inputAmount = '<input id="Shipping_Option_Price_mn" type="text" pattern="[0-9]*" onkeypress="UI.numberOnly(event, false, false, true)" placeholder="Shipping Rate" value="25"/>';
23451		var htmAmount = '<div id="pop-create-shipping-option-price">' + lblAmount + '<b class="dollar-sign">$</b>' + inputAmount + '</div>';
23452		
23453		// if (false && customCards > 0) {
23454		// 	var lblDefault = '<label for="Default_Gift_Card_fl">Default Gift Card</label>';
23455		// 	var inputDefault = '<input id="Default_Gift_Card_fl" type="checkbox"/>';
23456		// 	var htmDefaultCard = '<div id="pop-create-gift-card-default">' + inputDefault + lblDefault + '</div>';
23457		// } else {
23458		// 	var htmDefaultCard = '';
23459		// }
23460		
23461		// var htmVoucherInput = '<input id="Gift_Only_fl" type="checkbox"/>';
23462		// var htmVoucherLabel = '<label for="Gift_Only_fl">
23462Is Gift Voucher</label>';
23463		// var htmVoucherHelp = '<p>Gift Voucher cannot be used by client purchasing voucher, voucher must be used by different client</p>';
23464		// var htmVoucher = '<div id="pop-create-gift-voucher">' + htmVoucherInput + htmVoucherLabel + htmVoucherHelp + '</div>';
23465		
23466		// var htmExpireInput = '<input id="Expire_Days_sr" type="text"/>';
23467		// var htmExpireLabel1 = '<label for="Expire_Days_sr">Voucher Expires</label>';
23468		// var htmExpireLabel2 = '<label for="Expire_Days_sr">Weeks After Purchase</label>';
23469		// var htmExpire = '<div id="pop-create-gift-expire">' + htmExpireLabel1 + htmExpireInput + htmExpireLabel2 + '</div>';
23470		var htmDefaultCard = '';
23471		var htm = '<div id="pop-create-shipping-option"><p>' + msg + '</p> <form>' + htmName + htmAmount + htmDefaultCard + '</form></div>';		// + htmExpire + htmVoucher
23472		var jpop = GLO.Popup.Custom.openSimple(htm, 'Add New Shipping Rate', GLO.Provider.ShoppingCart.saveShipping);
23473	}
23474	
23475	_cShoppingCart.saveShipping = function() {
23476		var jpop = $('#pop-create-shipping-option').closest('.glopop');
23477		var amt = UTIL.displayMoney(jpop.find('#Shipping_Option_Price_mn').val(), true);
23478		var nm = $.trim(UTIL.htmlEncode4(jpop.find('#Shipping_Option_Name_vc').val()));
23479		var jd = { "name": nm, "amount": amt };
23480		var url = GLO.Info.http + document.location.host + '/Inventory/AddShippingRate';
23481		
23482		GLO.UI.Form.beginProcessing( jpop.find('.btnSave') );
23483		
23484    	$.ajax({ type: "POST", url: url, "cache": false, data: jd })
23485            .success(function(data, textStatus, jqXHR) {
23486			
23487				if (data!==null && data.status =='success') {
23488					var msg1 = '<p>Shipping Rate Successfully Created</p>';
23489					var htm = '<div id="pop-success-create-shipping-option">' + msg1 + '</div>';
23490					
23491					GLO.Popup.Success.open(htm, 'Shipping Rate Added', 3000);
23492					GLO.Popup.close(jpop);
23493				}
23494				else {
23495					GLO.Popup.Error('Unable to save shipping rate. Please try again'); 
23496					// console.log(data.message);
23497					GLO.UI.Form.resetProcessing();
23498				}
23499
23500
23501            })
23502            .error(function(jqXHR, textStatus, errorThrown) {
23503                GLO.Popup.Error('Unable to save shipping rate. Please try again'); 
23504                GLO.UI.Form.resetProcessing();
23505            });
23506	}
23507	
23508
23509	_cShoppingCart.openHelp = function() {
23510		//TODO: DISPLAY SHOPPING CART SETUP HELP DOCS
23511	}
23512	return _cShoppingCart;
23513})();
23514
23515GLO.Provider.ReputationManagement = (function() {
23516	function _reputation() { }
23517
23518	_reputation.init = function(providerReputationConfig) {
23519		var j = $('#manage-reputation');
23520		var btnSave = j.find('.btnSave');
23521		
23522    	if (providerReputationConfig.Enable_Appt_Survey == true) {
23523			j.addClass('reputation-enabled');
23524			$('#appt_survey_message').prop('disabled',false);
23525			j.find('#Send_Appt_Survey_fl').prop('checked',true);
23526			$('#appt_survey_message').val(providerReputationConfig.Appt_Survey_Message);
23527			
23528    	} else {
23529			j.removeClass('reputation-enabled');
23530			$('#appt_survey_message').prop('disabled',true);
23531			$('#appt_survey_message').val('');
23532			j.find('#Send_Appt_Survey_fl').prop('checked',false);
23533		}
23534
23535		if (providerReputationConfig.Enable_Testimonials_Page == true) { 
23536			j.find('#enable_testimonials_on_website_fl').prop('checked',true);
23537		}
23538		else {
23539			j.find('#enable_testimonials_on_website_fl').prop('checked',false);
23540		}
23541
23542		j.find('.review-link-input').on('keyup', GLO.Provider.ReputationManagement.keyupSocialMediaKey).keyup();
23543		j.find('input, select').change(function() { UI.buttonDisplayChange(btnSave); });
23544    	j.find('input').keyup(function() { UI.buttonDisplayChange(btnSave); });
23545	}
23546	
23547	_reputation.keyupSocialMediaKey = function() {
23548    	var jthis = $(this);
23549    	var urlKey = jthis.val();
23550		var jparent = jthis.closest('.manage-repuation-review-link');
23551		var jlink = jparent.find('.social-media-link-column');
23552		var url = '';
23553		
23554    	if (!UTIL.isEmpty(urlKey)) {
23555			url = jparent.find('.review-domain').text() + urlKey;
23556			
23557	    	if (innerWidth > 999) {
23558	    		var urlCSS = '', urlCaption = url;
23559	    	} else {
23560	    		var urlCaption = '&#10140;';			//Heavy Round-Tipped Right Arrow
23561	    		var urlCSS = ' class="arrow-link"';
23562	    	}
23563	    	
23564	    	var link = '<a' + urlCSS + ' onclick="SA.App.openLinkInBrowser(\'https://' + url + '\', \'social-media-link\', true, null, true)">' + urlCaption + '</a>';
23565	    	//var link = '<a' + urlCSS + ' onclick="GLO.Uri.gotoUri(\'' + url + '\', this, event, true)">' + url + '</a>';
23566    	} else {
23567    		var link = '';
23568    	}
23569    	
23570    	jlink.html(link);
23571    }
23572	
23573	_reputation.highlightThumbsUpGoto = function() {
23574		var jgoto = $('#manage-reputation-great-goto');
23575		UI.highlight(jgoto, 80, 4500, false);
23576	}
23577	_reputation.changeEnable = function() {
23578		var j = $('#manage-reputation');
23579    	
23580    	if (j.find('#Send_Appt_Survey_fl').prop('checked')) {
23581			j.addClass('reputation-enabled');
23582			$('#appt_survey_message').prop('disabled',false);
23583			
23584    	} else {
23585			j.removeClass('reputation-enabled');
23586			$('#appt_survey_message').prop('disabled',true);
23587			$('#appt_survey_message').val('');
23588    	}
23589    }
23590    
23591    _reputation.openHelp = function(popId, h1) {
23592    	var htm = $('#' + popId).outerHTML();
23593    	var ojpop = GLO.Popup.Info.open(htm, h1);
23594    	
23595    	ojpop.addScrollBar();
23596    	ojpop.getPopup().addClass('pop-help-appt-survey');
23597    }
23598    
23599    _reputation.openHelpGoogleReview = function() {
23600    	var htm = $('#pop-review-google-link').outerHTML();
23601    	GLO.Popup.Info.open(htm, 'Google Review Link').getPopup();
23602    }
23603    _reputation.openHelpFacebookReview = function() {
23604    	var htm = $('#pop-facebook-review-link-help').outerHTML();
23605    	var jpop = GLO.Popup.Info.open(htm, 'Facebook Review Link').getPopup().addClass('help-review-link');
23606    }
23607    
23608    _reputation.save = function(isOverride) {
23609    	var uri = GLO.Link.WebsiteDomain + 'repman/save';
23610		var j = $('#manage-reputation');
23611		var jbtn = j.find('.btnSave');
23612		
23613		var SendApptSurvey = j.find('#Send_Appt_Survey_fl').prop('checked');
23614		var EnableTestimonialsPage = j.find('#enable_testimonials_on_website_fl').prop('checked');
23615		var ApptSurveyMessage = j.find('#appt_survey_message').val();
23616		var greatGoTo = j.find('input[name="appt-survey-great-goto"]:checked').val();
23617		
23618		var googleReviewUrl = j.find('#Google_Review_Url').val();
23619		var facebookReviewUrl = j.find('#Facebook_Review_Url').val();
23620		
23621		
23622		GLO.UI.Form.beginProcessing(jbtn);
23623		
23624		var viewModel = {
23625			"Enable_Appt_Survey": SendApptSurvey, "Appt_Survey_Message": ApptSurveyMessage, "GoToOnPositiveExperience": greatGoTo
23626			, "GoogleReviewUrl": googleReviewUrl, "FacebookReviewUrl": facebookReviewUrl, "YelpReviewUrl": "", "Enable_Testimonials_Page": EnableTestimonialsPage
23627		}
23628
23629        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: viewModel })
23630            .success(function(data, textStatus, jqXHR) {
23631                window.onbeforeunload = null;
23632                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23633            	jbtn.removeClass('btn-has-change');
23634            	
23635            	GLO.Popup.Success.open(data, 'Appointment Survey', 19000);
23636            })
23637            .error(function(jqXHR, textStatus, errorThrown) {
23638                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
23639                //new GLO.Popup.Error('Unable to order the calendars staff');
23640            });
23641    }
23642	return _reputation;
23643})();
23644
23645
23646GLO.Provider.MemberService = (function() {
23647    function _cMemberService() { }
23648    
23649    _cMemberService.init = function(isRefresh) {
23650    	_initReport('Member Service Report', isRefresh);
23651    }
23652    _cMemberService.initActivityReport = function(isRefresh) {
23653    	var jhead = $('#report-main .report-search-header');
23654	    var htmSummary = $.trim($('#membership-report tfoot .member-column-duration').html());
23655		
23656		if (!UTIL.isEmpty(htmSummary) && (UTIL.isDate(jhead.find('#Member_Start_dt').val()) || UTIL.isDate(jhead.find('#Member_End_dt').val())) ) {
23657			htmSummary = '<div style="font-weight: bold;">During Searched Period</div>' + htmSummary;
23658		}
23659		
23660		$('#membership-report-summary').html(htmSummary);
23661	    
23662    	if (!isRefresh) {
23663    		var yearRange = GLO.UI.getYearRange(true);
23664	    	
23665	    	jhead.find('.is-date-picker').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
23666	    												, dateFormat: "M d, yy", numberOfMonths: 1, beforeShow: UI.loadDatepicker, changeYear: true, yearRange: yearRange });
23667    	}
23668    	
23669    	_initReport('Member Activity Report', isRefresh);
23670    	_initFromUrl();
23671    }
23672    function _initFromUrl() {
23673    	var highlight = GLO.Uri.url('highlight');
23674    	var open = GLO.Uri.url('open');
23675    	var step = GLO.Uri.url('step');
23676    	
23677    	if (open == 'membership-setup-how-to' || open == 'how-to-guide-membership') {
23678    		GLO.Provider.Membership.Help.openHowToSetup(step);
23679    	} 
23680    	
23681    	if (!UTIL.isEmpty(highlight)) {
23682    		var jhigh = jm.find('#' + highlight);
23683    		
23684    		if (jhigh.length) {
23685    			UI.highlight(jhigh, 300, 8000, true);
23686    		} else {
23687    			setTimeout(function() {
23688    				var jhigh = $('.glopop #' + highlight);
23689    				UI.highlight(jhigh, 300, 9000, true);
23690    			}, 800);
23691    		}
23692    	}
23693    }
23694    function _initReport(reportName, isRefresh) {
23695    	var jrpt = $('#membership-report.tablesorter');
23696        UI.initTableSorter(jrpt);
23697        
23698        GLO.Report.enableFullPageCheck();
23699        GLO.Report.CellSummary.initReport(jrpt, false, true);
23700        
23701        if (!isRefresh) {
23702	        GLO.Report.portalName = reportName;
23703	    	GLO.Report.setupFastClick();
23704	    	GLO.Staff.Filter.isReportPortal = true;
23705	    	
23706	    	var mid = UTIL.cleanString(GLO.Uri.query('membership'));
23707	    	var jhead = $('#report-main .report-search-header');
23708	    	var dd = GLO.Provider.Membership.getMembershipDropDown();
23709	    	
23710	    	jhead.find('#Membership_id').replaceWith(dd);
23711	    	jhead.find('#Membership_id').val(mid).change(GLO.Provider.Membership.searchReport).find('option:first').text('(all memberships)');
23712	    	
23713	    	_initShortcut();
23714	    	_initUri();
23715    	}
23716    }
23717    
23718    function _initUri() {
23719    	var cid = GLO.Uri.url('client');
23720    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
23721    	var start = GLO.Uri.url('start');
23722    	var end = GLO.Uri.url('end');
23723    	
23724    	if (UTIL.isNumber(cid)) {
23725    		var tr = $('#membership-report').find('tr[client_id="' + cid + '"]');
23726    		
23727    		if (tr.length === 1 && !UTIL.isEmpty(open)) {
23728    			if (open === 'profile' || open === 'client') {
23729    				tr.find('.membership-column-client, .member-column-client').find('>a').click();
23730    			} else if (open === 'membership' || open === 'name') {
23731    				tr.find('.membership-column-name, .member-column-membership').find('>a').click();
23732    			} else if (open === 'status' || open === 'pay-status') {
23733    				tr.find('.membership-column-pay-status, .member-column-status').click();
23734    			} else {
23735    				tr.find('.membership-column-' + open + '.member-column-' + open).click();
23736    			}
23737    		}
23738    	}
23739    	
23740    	if (UTIL.isDate(start)) {
23741    		$('#Member_Start_dt').val(new Date(start).toGloDate());
23742    	}
23743    	
23744    	if (UTIL.isDate(end)) {
23745    		$('#Member_End_dt').val(new Date(end).toGloDate());
23746    	}
23747    }
23748    function _initShortcut() {
23749    	$(document).keydown(function(event) {
23750           if (event.altKey) {
23751                if (event.which === 82) {                                //R: refresh report
23752                    GLO.Provider.Membership.searchReport();	//GLO.Provider.Membership.searchReport();
23753                }
23754            }
23755        });
23756        $(window).bind('keypress', function(e) {
23757            if (e.altKey) {
23758                if (e.which === 82) {               				//R: refresh report
23759                    e.preventDefault();
23760                }
23761            }
23762        });
23763    }
23764    
23765    _cMemberService.clearDates = function(icon) {
23766    	var jhead = $(icon).closest('.report-search-header');
23767    	jhead.find('.is-date-picker').val('').change();
23768    }
23769    
23770    _cMemberService.searchReport = function() {
23771    	var qs = '', jhead = $('#report-main .report-search-header');
23772    	var mid = jhead.find('#Membership_id').val();
23773    	
23774    	if (!UTIL.isEmpty(mid)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'membership=' + mid); }
23775    	
23776    	var url = window.location.origin + window.location.pathname + qs;
23777    	window.history.pushState('', '', url);
23778    	
23779    	//if (title) { document.title = title; }
23780    	
23781    	$('h2#membership-report-header .fa-refresh').click();
23782    }
23783    _cMemberService.refreshReport = function(button) {
23784    	var jd = {};
23785    	button = $(button);
23786    	
23787    	if (button.hasClass('fa-spin')) {
23788    		return;
23789    	} else if (!GLO.Report.hasReportPassword(jd)) {
23790    		return;
23791	    } else if (button.hasClass('fa')) {
23792    		button.addClass('fa-spin');
23793    	} else {
23794    		GLO.UI.Form.beginProcessing(button.parent());
23795    	}
23796    	
23797    	GLO.UI.Form.beginProcessing($('.report-search-header .btnSearch'));
23798    	
23799    	var jrpt = $('.report-container');
23800    	var uri = GLO.Uri.addQueryKeyAndValue(location.href, 'ispartial=1');
23801    	
23802    	var jqxhr = $.ajax({ "type": "POST", "url": uri, "cache": false, "data": jd })
23803            .success(function(data, textStatus, jqXHR) {
23804                button.removeClass('fa-spin');
23805                GLO.UI.Form.resetProcessing();
23806                
23807                jrpt.html($(data).outerHTML());
23808                
23809                if ($('#member-activity-report.report-container').length) {
23810                	_cMemberService.initActivityReport(true);
23811                } else {
23812                	_cMemberService.init(true);
23813                }
23814            })
23815            .error(function(jqXHR, textStatus, errorThrown) {
23816            	button.removeClass('fa-spin');
23817            	GLO.UI.Form.resetProcessing();
23818            	
23819            	var htm = '<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>';
23820            	jrpt.html(htm);
23821            });
23822    }
23823    
23824    return _cMemberService;
23825})();
23826
23827
23828GLO.Provider.Membership = (function() {
23829    function _cMembership() { }
23830    
23831    var _popEditType, _popEditTypeService;
23832    
23833    function _loadPopup(popid) {
23834    	var jpop = $('#' + popid);
23835        var htm = jpop.outerHTML();
23836        jpop.remove();
23837        return htm;
23838    }
23839    
23840    _cMembership.init = function() {
23841        GLO.Info.init();
23842        
23843        _popEditType = _loadPopup('pop-membership-edit');
23844    	_popEditTypeService = _loadPopup('pop-membership-service-edit');
23845        
23846    	var j = $('#manage-membership');
23847        var isInvalidPackage = ((GLO.Info.providerPackage == 4 && UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 79) || GLO.Info.providerPackage == 1);
23848    	
23849    	if (isInvalidPackage) {
23850    		j.find('input,select').prop('disabled', true);
23851    		j.find('.btnSave, .btnAddMembership').remove();
23852    		
23853    		if (isInvalidPackage) {
23854    			var msg = 'Gold package required to enable Membership';
23855    		} else {
23856    			var msg = 'Manager or Admin required to setup Membership';
23857    		}
23858    		
23859    		GLO.Popup.Info.open(msg, 'Membership Restriction');
23860    		return;
23861    	}
23862    	
23863    	var jtbl = j.find('table#membership-list');
23864    	var jtbody = jtbl.find('tbody');
23865    	
23866    	jtbody.on('click', '.column-member-name, .column-member-price, .column-member-period, .column-member-
23866auto-bill, .column-member-description', GLO.Provider.Membership.openEditType);
23867    	jtbody.on('click', 'tr.membership-type-service', GLO.Provider.Membership.openEditService);
23868    	
23869    	if (jtbody.find('tr').length > 0) { jtbl.removeClass('hide'); }
23870    	_initTable(jtbody);
23871    	_initUrlMembershipSetup();
23872    }
23873    function _initUrlMembershipSetup() {
23874    	var isCreateMembership = UTIL.cleanString(GLO.Uri.url('create')).toLowerCase() === 'membership';
23875    	var msvcid = GLO.Uri.url('mservice');
23876    	var mid = GLO.Uri.url('membership');
23877    	var jm = $('#manage-membership');
23878    	var highlight = GLO.Uri.url('highlight');
23879    	var open = GLO.Uri.url('open');
23880    	var step = GLO.Uri.url('step');
23881    	
23882    	if (isCreateMembership) {
23883    		GLO.Provider.Membership.openEditType();
23884    	} else if (!UTIL.isEmpty(msvcid)) {
23885    		if (msvcid > 1) {
23886    			var jTypeService = jm.find('.membership-type-service[membership_service_id="' + msvcid + '"]');
23887    		} else {
23888    			var jTypeService = jm.find('.membership-type-service:first');
23889    		}
23890    		
23891    		jTypeService.click();
23892    		jm = $('#pop-membership-service-edit').glopop('.closest');
23893    	} else if (open == 'membership-setup-how-to' || open == 'how-to-guide-membership') {
23894    		GLO.Provider.Membership.Help.openHowToSetup(step);
23895    	} else if (open == 'edit-membership') {
23896    		if (!UTIL.isEmpty(mid)) {
23897    			var jmembership = $('#membership-list').find('tr.membership-type[membership_id="' + mid + '"]');
23898    		} else {
23899    			var jmembership = $('#membership-list').find('tr.membership-type');
23900    		}
23901    		
23902    		jmembership.find('td.column-member-name').click();
23903    	}
23904    	
23905    	if (!UTIL.isEmpty(highlight)) {
23906    		var jhigh = jm.find('#' + highlight);
23907    		
23908    		if (jhigh.length) {
23909    			UI.highlight(jhigh, 300, 8000, true);
23910    		} else {
23911    			setTimeout(function() {
23912    				var jhigh = $('.glopop #' + highlight);
23913    				UI.highlight(jhigh, 300, 9000, true);
23914    			}, 800);
23915    		}
23916    	}
23917    }
23918    _cMembership.initReport = function(isReload) {
23919        GLO.Info.init();
23920        GLO.Staff.Filter.isReportPortal = true;
23921    	GLO.Report.Template.initStaffFilter();
23922        
23923        var jrpt = $('#membership-report.tablesorter');
23924        UI.initTableSorter(jrpt);
23925        GLO.Report.enableFullPageCheck();
23926        GLO.Report.CellSummary.initReport(jrpt, false, true);
23927        
23928        if (innerWidth < 800 && $('body.report-full-page').length === 0) {
23929        	$('#membership-report thead td.membership-column-period').attr('colspan', 3);
23930        }
23931        
23932        if (!isReload) {
23933        	GLO.Report.portalName = 'Membership Report';
23934        	GLO.Report.setupFastClick();
23935        	GLO.Staff.Filter.isReportPortal = true;
23936        	
23937        	var mid = UTIL.cleanString(GLO.Uri.query('membership')), status = UTIL.cleanString(GLO.Uri.query('status'));
23938        	var sfilter = GLO.Uri.url('sfilter');
23939        	
23940        	var jhead = $('#report-main .report-search-header');
23941        	var dd = _cMembership.getMembershipDropDown();
23942        	jhead.find('#Membership_id').replaceWith(dd);
23943        	
23944        	jhead.find('#Membership_id').val(mid).change(GLO.Provider.Membership.searchReport).find('option:first').text('(all memberships)');
23945        	jhead.find('#Membership_Status_cd').val(status).change(GLO.Provider.Membership.searchReport);
23946        	
23947        	if (GLO.Info.roleType > 209 && !UTIL.isEmpty(sfilter) && sfilter.toLowerCase() !== 'all') {
23948        		GLO.Report.setStaffFilter(sfilter);				//$('#staff-filter').val(sfilter).change();
23949        	}
23950        	
23951        	_initShortcut();
23952        	_initUri();
23953        	
23954        	if (GLO.Info.isMobile()) {
23955	        	$('#staff-filter').prepend('<option value="">All</option>');
23956	        	
23957	        	if (UTIL.isEmpty(sfilter)) {
23958	        		$('#staff-filter').val(sfilter);
23959	        	}
23960	        }
23961	        
23962	        _setMembershipReportOverview();
23963	        _initNoMemberships();
23964	        _initUrlMembershipSetup();
23965        }
23966        
23967        jrpt.on('click.open-tag', '.client-tag', GLO.Report.openTag);
23968    }
23969    function _initNoMemberships() {
23970    	if (GLO.Data.provider.MembershipList.length === 0) {
23971    		var msg1 = '<p>No Memberships Setup</p>';
23972    		var msg2 = '<p>Go to <a onclick="GLO.Uri.gotoUriWithSpinner(\'membership\', this, event, true)">Membership Setup</a></p>';
23973    		
23974    		GLO.Popup.Info.open('<div id="pop-help-no-memberships">' + msg1 + msg2 + '</div>', 'No Memberships Setup');
23975    	}
23976    }
23977    function _initUri() {
23978    	var cid = GLO.Uri.url('client');
23979    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
23980    	
23981    	if (!UTIL.isEmpty(cid)) {
23982    		if (cid > 1) {
23983    			var tr = $('#membership-report').find('tr[client_id="' + cid + '"]');
23984    		} else {
23985    			var tr = $('#membership-report').find('tbody tr:first');
23986    		}
23987    		
23988    		if (tr.length === 1 && !UTIL.isEmpty(open)) {
23989    			if (open === 'profile' || open === 'client') {
23990    				tr.find('.membership-column-client').find('>a').click();
23991    			} else if (open === 'membership' || open === 'name') {
23992    				tr.find('.membership-column-name').find('>a').click();
23993    			} else if (open === 'status' || open === 'pay-status') {
23994    				tr.find('.membership-column-pay-status').click();
23995    			} else {
23996    				tr.find('.membership-column-' + open).click();
23997    			}
23998    			
23999    			setTimeout(GLO.Provider.Membership.initUri2, 1500);
24000    		}
24001    	}
24002    }
24003    _cMembership.initUri2 = function() {
24004    	var open2 = UTIL.cleanString(GLO.Uri.url('open2')).toLowerCase();
24005		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
24006		var highlightClass = UTIL.cleanString(GLO.Uri.url('highlight-class')).toLowerCase();
24007		var jpop = $('.glopop, #simplemodal-container');
24008		
24009		if (open2 == 'commission-price') {
24010			jpop.find('.adjust-total-service-price:first .help-icon4').click();		//GLO.Provider.Membership.openServicePriceHelp(this);		//$('#pop-member-view').closest('.glopop')
24011			return;
24012		} else if (!UTIL.isEmpty(highlight)) {
24013			var jhigh = jpop.find('#' + highlight);
24014		} else if (!UTIL.isEmpty(highlightClass)) {
24015			var jhigh = jpop.find('.' + highlightClass);
24016		}
24017		
24018		if (jhigh && jhigh.length) {
24019			UI.highlight(jhigh, 300, 6000, true);
24020		}
24021    }
24022    
24023    function _initShortcut() {
24024    	$(document).keydown(function(event) {
24025           if (event.altKey) {
24026                if (event.which === 82) {                                //R: refresh report
24027                    GLO.Provider.Membership.searchReport();
24028                }
24029            }
24030        });
24031        $(window).bind('keypress', function(e) {
24032            if (e.altKey) {
24033                if (e.which === 82) {               				//R: refresh report
24034                    e.preventDefault();
24035                }
24036            }
24037        });
24038    }
24039    
24040    function _initTable(jtbody) {
24041    	var rowCSS = null, trs = jtbody.find('> tr');
24042    	
24043    	for (var i=1; i < trs.length; i++) {
24044    		var tr = trs.eq(i);
24045    		
24046    		if (tr.hasClass('membership-type')) {
24047    			if (!UTIL.isEmpty(rowCSS)) {
24048    				rowCSS = null;
24049    			} else {
24050    				rowCSS = 'odd-row-membership';
24051    			}
24052    		}
24053    		
24054    		if (!UTIL.isEmpty(rowCSS)) {
24055    			tr.addClass(rowCSS);
24056    		}
24057    	}
24058    	
24059    	_updateMembershipCount();
24060    }
24061    
24062    function _updateMembershipCount() {
24063    	var cnt = $('#membership-list').find('tr.membership-type').length;
24064    	var msg = UTIL.pluralLabel(cnt, 'membership');
24065    	
24066    	$('#member-header-info #membership-count').text(msg);
24067    }
24068    
24069    _cMembership.openSell = function(event) {
24070    	var htm = '<div id="pop-sell-membership">';
24071    	var dd = '<div id="pop-sell-membership-select"> <label for="Membership_id">Select Membership</label>' + _cMembership.getMembershipDropDown() + '</div>';
24072    	
24073    	/* toDo: add start date
24074    	var dtStart = new Date().toGloDate();
24075    	var htmStartInput = '<input type="text" id="Membership_Start_dt" pattern="[0-9]*" value="' + dtStart + '" onclick="GLO.UI.displayDatePicker(this)"/>';
24076    	var htmStart = '<div id="pop-sell-membership-start"> <label for="Membership_Start_dt">Start Date</label>' + htmStartInput + '</div>';
24077    	*/
24078    	
24079    	htm += dd + '</div>';
24080    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Select Membership');
24081    	jpop.find('#Membership_id').change(GLO.Provider.Membership.openSell2);
24082    	GLO.Popup.Custom.singleButton(jpop, 'Close');
24083    }
24084    
24085    _cMembership.openSell2 = function() {
24086    	var jpop = $('#pop-sell-membership-select').closest('.glopop');
24087    	var membershipId = jpop.find('#Membership_id').val();
24088    	var membership = GLO.ClientProfile.getMembership(membershipId);
24089    	
24090    	GLO.Popup.close(jpop);
24091    	
24092    	UserPortal.Price.quit();
24093    	UserPortal.Price.inventoryXml = '<li amount_nr="1" tax_rate_pct="0"  cost_mn="0" vendor_id="" product_line_id="" vendor_merchant_id=""'
24094    					+ ' price_mn="' + membership.price + '" employee_price_mn="' + membership.price + '" membership_id="' + membershipId + '"'
24095						+ ' inventory_id="' + membership.inventory_id + '" inventory_vc="' + UTIL.removeBadCharacters(UTIL.replaceQuotes(membership.name)) + '"/>';
24096        
24097        UserPortal.Price.open(null, true, null, false);
24098        var jPricePop = $('#appt-price-popup').closest('.glopop');
24099        
24100        if (UTIL.coalesceMoney(membership.price) === 0) {
24101        	jPricePop.find('.booking-product-price').click();
24102        } else {
24103        	jPricePop.find('#purchaser-autocomplete-input').click();
24104        }
24105    }
24106    
24107    _cMembership.openPeriodSummary = function() {
24108    	var tr = $('#membership-report').find('td.cell-summary-selected').closest('tr');
24109    	var membershipId = tr.attr('membership_id'), iid = tr.attr('inventory_id'), cid = tr.attr('client_id');
24110    	var cname = tr.find('td.membership-column-client > a').text();
24111    	
24112    	_cMembership.openPeriodSummary2(membershipId, iid, cid, cname);
24113    }
24114    
24115    function _getMember(tr) {			//= gets price of next member payment (or balance due if current period) + other details for next member payment
24116    	var membershipId = tr.attr('membership_id'), nextMembershipId = tr.attr('next_membership_id');
24117    	var balance = UTIL.coalesceMoney(tr.attr('balance_mn')), billPeriod = tr.attr('billing_period_cd');
24118    	
24119    	var membership = GLO.ClientProfile.getMembership(membershipId);
24120    	var customPrice = tr.attr('custom_price_mn');
24121    	var price = UTIL.coalesceMoney(customPrice, membership.price);
24122    	var hasCustomBillPeriod = (UTIL.coalesceInt(billPeriod, membership.period) != membership.period);
24123    	
24124    	var dtNextBill = tr.attr('next_bill_dt');
24125    	var periodEnd = new Date(tr.attr('period_end_dt')), today = new Date(new Date().toGloDate());
24126    	var isNewMemberPeriod = (today >= periodEnd);
24127    	
24128    	if (UTIL.isDate(dtNextBill)) {
24129    		dtNextBill = new Date(dtNextBill);
24130    		
24131    		if (hasCustomBillPeriod && periodEnd > dtNextBill) {
24132	    		isNewMemberPeriod = false;				//= next billing period is not a new member period.
24133	    	}
24134    	} else {
24135    		dtNextBill = new Date(periodEnd).addDays(1);
24136    	}
24137    	
24138    	if (!UTIL.isEmpty(nextMembershipId) && isNewMemberPeriod) {
24139    		var membership = GLO.ClientProfile.getMembership(nextMembershipId);
24140    		price = membership.price;
24141    	} else if (hasCustomBillPeriod) {
24142    		var memberMonthCount = _cMembership.getPeriodMonthCount(membership.period);
24143	    	//var billMonthCount = _cMembership.getPeriodMonthCount(billPeriod);
24144	    	
24145	    	/* just use listed price (much simplier)
24146    		if (memberMonthCount > billMonthCount) {				//= always use price (unless member period > billing period)
24147	    		price = UTIL.coalesceMoney(price * billMonthCount/memberMonthCount, true, false, true);
24148	    	}
24149    		*/
24150    	}
24151		
24152		var due = _getDueAmount(price, balance, dtNextBill, isNewMemberPeriod);
24153    	var member = {
24154    					"price_mn": price, "due_mn": due, "balance_mn": balance, "is_new_member_period": isNewMemberPeriod, "is_custom_bill_period": hasCustomBillPeriod
24155    					, "bill_dt": dtNextBill, "membership": membership
24156    				};
24157    	
24158    	if (!UTIL.isEmpty(customPrice) && UTIL.isEmpty(nextMembershipId)) { member.custom_price_mn = customPrice; }
24159    	
24160    	if (isNewMemberPeriod) {
24161    		member.new_period_start_dt = new Date(periodEnd).addDays(1);
24162    		member.new_period_end_dt = _cMembership.getPeriodEnd(membership.period, member.new_period_start_dt);
24163    		
24164    		if (new Date() > member.new_period_end_dt) {
24165    			member.new_period_start_dt = new Date();
24166    			member.new_period_end_dt = _cMembership.getPeriodEnd(membership.period, member.new_period_start_dt);
24167    		}
24168    		
24169    		/* if (UTIL.isEmpty(nextMembershipId) && hasCustomBillPeriod) {
24170    			member.next_bill_dt = new Date(new Date(member.new_period_start_dt).setMonth(member.new_period_start_dt.getMonth() + billMonthCount));
24171    		} else {
24172    			member.next_bill_dt = new Date(member.new_period_end_dt).addDays(1);
24173    		} */
24174    	//} else if (hasCustomBillPeriod) {
24175		//	member.next_bill_dt = new Date(new Date(dtNextBill).setMonth(dtNextBill.getMonth() + billMonthCount));
24176		}
24177    	
24178    	member.card_on_file_fl = UTIL.parseBool(tr.attr('card_on_file_fl'));
24179    	member.auto_bill_fl = UTIL.parseBool(tr.find('.is-auto-bill').length);
24180    	return member;
24181    }
24182    
24183    function _getDueAmount(price, balance, dtNextBill, isNewMemberPeriod) {
24184    	if (balance < 0 && !isNewMemberPeriod) {
24185    		return UTIL.coalesceMoney(-balance);
24186    	} else if (balance - price < 0) {
24187			if (balance < 0 && dtNextBill > new Date()) {
24188				return UTIL.coalesceMoney(-balance);
24189			} else {
24190				return UTIL.coalesceMoney(price - balance);
24191			}
24192		} else if (price > 0) {
24193			return 0;
24194		}
24195    }
24196    
24197    _cMembership.changeWeb = function() {
24198    	var jpop = $('#pop-membership-edit').closest('.glopop');
24199    	var webAccess = jpop.find('#Web_cd').val();
24200    	var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99);
24201    	
24202    	if (webAccess == 10) {
24203    		if (mt > 24) {
24204    			var htm = '<div id="pop-warn-merchant-required">Selling Memberships Online Requires Merchant Account</div>';
24205    			GLO.Popup.Warning.open(htm, 'Merchant Account Required');
24206    			jpop.find('#Web_cd').val(20);
24207    		}
24208    	}
24209    }
24210    
24211    /* _cMembership.openPayMembershipFromCellSummary = function() {
24212    	var tr = $('#membership-report').find('td.cell-summary-selected').closest('tr');
24213    } */
24214    _cMembership.openPayMembershipFromPopup = function(membershipId, iid, cid, cname) {
24215    	var tr = $('#membership-report').find('tr[client_id="' + cid + '"]');
24216    	var jpop = $('#pop-member-view').closest('.glopop');
24217    	var customPrice = null;
24218    	
24219    	if (jpop.length) {
24220    		jpop.find(':focus').blur();
24221    		
24222    		if (jpop.find('.btnSave > a.unsaved').length) {
24223    			jpop.find('.btnSave > a').removeClass('unsaved');
24224    			
24225    			var fnYes = function() { jpop.find('.btnSave > a').click(); };
24226    			var fnNo = function() { jpop.find('#btnPayMembership > a').click(); };
24227    			
24228    			GLO.Popup.Confirm.open('Save Changes to Member Profile?', 'Un-Saved Changes', fnYes, fnNo);
24229    			return;
24230    		} else {
24231    			var periodPrice = jpop.find('#Period_Price_mn').val();
24232    			var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val());
24233    			
24234    			if (UTIL.isNumber(periodPrice, true) && periodPrice != GLO.ClientProfile.getMembership(membershipId).price_mn) {
24235    				customPrice = periodPrice;
24236    			}
24237    			
24238    			if (balance != 0) {
24239    				var dtStart = jpop.find('#Period_Start_dt').val();
24240	    			var dtEnd = jpop.find('#Period_End_dt').val();
24241	    			
24242	    			if (UTIL.isDate(dtStart) && UTIL.isDate(dtEnd) && new Date() < new Date(dtEnd)) {
24243	    				customPrice = -balance;
24244	    			} else {
24245	    				customPrice = customPrice - balance;
24246	    			}
24247    			}
24248    		}
24249    		
24250    		GLO.Popup.close(jpop);
24251    		GLO.Popup.Processing.open('<div id="pop-procesing-price-wait">Creating Membership Purchase Ticket...</div>', 'Creating Ticket');
24252    	}
24253    	
24254    	setTimeout(function() {							//= make async so UI closes popup (see above code) immediately
24255	    	if (tr.length === 1 && tr.attr('membership_id') == membershipId) {
24256	    		_cMembership.openPayMembership(tr);
24257	    	} else {
24258	    		_cMembership.openPayMembership2(membershipId, iid, cid, cname, customPrice);
24259	    	}
24260    	}, 90);
24261    }
24262    _cMembership.openPayMembership = function(tr) {
24263    	var membershipId = tr.attr('membership_id'), iid = tr.attr('inventory_id'), cid = tr.attr('client_id');
24264    	var cname = tr.find('td.membership-column-client > a').text();
24265    	var member = _getMember(tr);
24266    	
24267    	if (member.due_mn > 0) {
24268    		var customPrice = member.due_mn;
24269    	} else {
24270    		var customPrice = member.price_mn;
24271    	}
24272    	
24273    	_cMembership.openPayMembership2(membershipId, iid, cid, cname, customPrice);
24274    }
24275    _cMembership.openPayMembership2 = function(membershipId, iid, cid, cname, customPrice, startDate) {
24276    	var membership = GLO.ClientProfile.getMembership(membershipId);
24277    	var price = UTIL.coalesceMoney(customPrice, membership.price);
24278    	var payInfo = $('<h2 client_id="' + cid + '" client_vc="' + cname + '"></h2>');
24279    	
24280    	if (UTIL.isEmpty(iid)) {
24281    		iid = membership.inventory_id;
24282    	}
24283    	
24284    	GLO.Popup.close($('#pop-member-pay-summary').closest('.glopop'));
24285    	GLO.Popup.close($('#pop-help-cell-summary').closest('.glopop'));
24286    	
24287    	UserPortal.Price.quit();
24288    	UserPortal.Price.inventoryXml = '<li amount_nr="1" tax_rate_pct="0"  cost_mn="0" vendor_id="" product_line_id="" vendor_merchant_id=""'
24289    					+ ' price_mn="' + price + '" employee_price_mn="' + price + '" membership_id="' + membershipId + '" membership_start_dt="' + UTIL.cleanString(startDate) + '"'
24290						+ ' inventory_id="' + membership.inventory_id + '" inventory_vc="' + UTIL.removeBadCharacters(UTIL.replaceQuotes(membership.name)) + '"/>';
24291        
24292        UserPortal.Price.open(null, true, payInfo, false);
24293        var jPricePop = $('#appt-price-popup').closest('.glopop');
24294        
24295        if (UTIL.coalesceMoney(membership.price) === 0) {
24296        	jPricePop.find('.booking-product-price').focus();
24297        }
24298    }
24299    
24300    _cMembership.searchReport = function() {
24301    	var qs = '', jhead = $('#report-main .report-search-header');
24302    	var mid = jhead.find('#Membership_id').val();
24303    	var status = jhead.find('#Membership_Status_cd').val();
24304    	var sfilter = GLO.Uri.url('sfilter');						//$('#staff-filter').val();
24305    	
24306    	var start = jhead.find('#Member_Start_dt').val();
24307    	var end = jhead.find('#Member_End_dt').val();
24308    	
24309    	if (!UTIL.isEmpty(mid)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'membership=' + mid); }
24310    	if (!UTIL.isEmpty(status)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'status=' + status); }
24311    	if (!UTIL.isEmpty(sfilter)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'sfilter=' + sfilter); }
24312    	
24313    	if (!UTIL.isEmpty(start)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'start=' + start); }
24314    	if (!UTIL.isEmpty(end)) { qs = GLO.Uri.addQueryKeyAndValue(qs, 'end=' + end); }
24315    	
24316    	var url = window.location.origin + window.location.pathname + qs;
24317    	window.history.pushState('', '', url);
24318    	
24319    	//if (title) { document.title = title; }
24320    	
24321    	$('h2#membership-report-header .fa-refresh').click();
24322    }
24323    
24324    _cMembership.refreshReportOnEdit = function(button) {
24325    	$('#membership-report-header').find('.fa-refresh').click();
24326    }
24327    
24328    _cMembership.refreshReport = function(button) {
24329    	var jd = {};
24330    	button = $(button);
24331    	
24332    	if (button.hasClass('fa-spin')) {
24333    		return;
24334    	//} else if (!GLO.Report.hasReportPassword(jd)) {
24335    	//	return;
24336	    } else if (button.hasClass('fa')) {
24337    		button.addClass('fa-spin');
24338    	} else {
24339    		GLO.UI.Form.beginProcessing(button.parent());
24340    	}
24341    	
24342    	GLO.UI.Form.beginProcessing($('.report-search-header-button .btnSearch'));
24343    	
24344    	var jrpt = $('.report-container'), jTagFilter = $('#tag-filter-container');
24345    	var uri = GLO.Uri.addQueryKeyAndValue(location.href, 'ispartial=1');
24346    	var qs = GLO.Message.Bulk.getTagQueryString(jTagFilter);
24347    	
24348    	_setMembershipReportOverview();
24349    	
24350    	var jqxhr = $.ajax({ "type": "POST", "url": uri + qs, "cache": false, "data": jd })
24351            .success(function(data, textStatus, jqXHR) {
24352                button.removeClass('fa-spin');
24353                GLO.UI.Form.resetProcessing();
24354                
24355                jrpt.html($(data).outerHTML());
24356                _cMembership.initReport(true);
24357            })
24358            .error(function(jqXHR, textStatus, errorThrown) {
24359            	button.removeClass('fa-spin');
24360            	GLO.UI.Form.resetProcessing();
24361            	
24362            	var htm = '<div style="padding: 20px 0; line-height: 200%; letter-spacing: 1px;">Unable to refresh report</br>Please try again</div>';
24363            	jrpt.html(htm);
24364            });
24365    }
24366    
24367    function _setMembershipReportOverview() {
24368    	var jhead = $('#bd-page .report-search-header');
24369    	var mstatus = jhead.find('#Membership_Status_cd');
24370    	//var sfilter = $('#staffFilter .hello-bar-label');			//cannot use because not on mobile
24371    	var sids = GLO.Uri.query('sfilter');
24372    	var htm = '';
24373    	
24374    	if (!UTIL.isEmpty(sids)) {
24375    		var sfilter = GLO.Report.getStaffHelloLabel(sids);
24376    		
24377    		if (!UTIL.isEmpty(sfilter)) {
24378    			htm = '<p>Members with an appointment with one of these staff members: <small style="letter-spacing: 0;">' + sfilter + '</small></p>';
24379    		}
24380    	}
24381    	
24382    	if (!UTIL.isEmpty(mstatus.val())) {
24383    		if (!UTIL.isEmpty(htm)) {
24384    			htm += '<p style="padding-left: 8px; padding-bottom: 16px;">and have';
24385    		} else {
24386    			htm = '<p>Members with';
24387    		}
24388    		
24389    		htm += ' a membership status of ' + mstatus.find(':selected').text() + '</p>';
24390    		
24391    		//if (mstatus.val() == 0) { htm += '<div margin-top: "8px;">New membership status</div>'; }
24392    	}
24393    	
24394    	$('#membership-report-overview').html(htm);
24395    }
24396    
24397    _cMembership.openEditType = function(event) {
24398    	if (!GLO.Info.isGold()) {
24399    		GLO.Popup.Warning.open('Managing memberships requires the Gold Package', 'Gold Package Only');
24400    		return;
24401    	}
24402    	
24403    	var tr = $(this).closest('tr');
24404    	
24405    	if (tr.hasClass('membership-type')) { 
24406    		var memberId = tr.attr('membership_id');
24407    		var strFnRemove = 'GLO.Provider.Membership.remove()';
24408    		var h1 = 'Edit Membership';
24409    	} else {
24410    		var tr = null, memberId = null, strFnRemove = null, h1 = 'Create Membership';
24411    	}
24412    	
24413    	var jpop = _openPopup(_popEditType, h1, GLO.Provider.Membership.save, strFnRemove);
24414    	
24415		if (tr) {
24416			var jdesc = tr.find('.column-member-description');
24417			var hasEmailReminderDay = false, emailReminderDay = tr.attr('email_reminder_day_sr'), webAccess = tr.attr('web_cd');
24418			
24419			if (UTIL.coalesceInt(emailReminderDay, 0) > 0) { hasEmailReminderDay = true; }
24420			
24421			jpop.attr('membership_id', tr.attr('membership_id'));
24422			jpop.find('#Membership_Name_vc').val(tr.find('.column-member-name').text());
24423			jpop.find('#Membership_Price_mn').val(UTIL.replaceAll(tr.find('.column-member-price').text(), '$', ''));
24424			jpop.find('#Membership_Period_cd').val(tr.attr('membership_period_cd'));
24425			jpop.find('#Billing_Period_cd').val(tr.attr('billing_period_cd'));
24426			
24427			jpop.find('#Auto_Billing_fl').prop('checked', tr.find('.column-member-auto-bill .is-auto-bill').length);
24428			jpop.find('#Email_Reminder_fl').prop('checked', hasEmailReminderDay);
24429			jpop.find('#Email_Reminder_Day_sr').val(emailReminderDay);
24430			jpop.find('#Membership_Description_vc').val(UTIL.coalesce(jdesc.attr('title'), jdesc.text()));
24431			
24432			if (webAccess) {
24433				jpop.find('#Web_cd').val(webAccess);
24434			}
24435		} else {
24436			jpop.find('#Auto_Billing_fl').prop('checked', true);
24437		}
24438    }
24439    
24440    _cMembership.openEditService = function(event, membershipId) {
24441    	var tr = $(this);
24442    	
24443    	if (tr.hasClass('membership-type-service')) { 
24444    		membershipId = tr.attr('membership_id');
24445    	} else {
24446    		tr = null;
24447    	}
24448    	
24449		if (tr) {
24450			var membershipServiceId = tr.attr('membership_service_id');
24451			var limit = tr.attr('limit_nr');
24452			var rolloverUnused = tr.attr('rollover_unused_pct');
24453			
24454			var discountMoney = tr.attr('discount_mn'), discountPercent = tr.attr('discount_pct');
24455			var svcFilter = tr.attr('service_id');
24456			
24457			if (UTIL.isEmpty(svcFilter)) { svcFilter = 'sg' + tr.attr('service_group_id'); }
24458			
24459			var isRequireMembership = UTIL.parseBool(tr.attr('require_membership_fl'));
24460			var commissionPrice = tr.attr('price_mn');
24461		} else {
24462			var membershipServiceId, limit, rolloverUnused, svcFilter, discountMoney, discountPercent;
24463			var isRequireMembership = false, commissionPrice = null;
24464		}
24465		
24466		var jpop = _cMembership.openEditService2(null, membershipId, membershipServiceId, limit, rolloverUnused, svcFilter, discountMoney, discountPercent, commissionPrice);
24467		jpop.find('#Require_Membership_fl').prop('checked', isRequireMembership);
24468    }
24469    _cMembership.openAddCustomService = function(clientId, membershipId) {
24470    	if (!UTIL.isEmpty(_popEditTypeService)) {
24471			_cMembership.openAddCustomService2(clientId, membershipId);
24472		} else {
24473			_cMembership.retrieveAddCustomServiceHtm(clientId, membershipId);
24474		}
24475    }
24476    _cMembership.retrieveAddCustomServiceHtm = function(clientId, membershipId) {
24477    	var ojprocessing = GLO.Popup.Processing.open('Opening Add Custom Service Popup....', 'Custom Member Service');
24478    	
24479    	var uri = GLO.Link.WebsiteDomain + 'membership/AddMembershipServicePopup';
24480    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
24481            .success(function(data, textStatus, jqXHR) {
24482                ojprocessing.close();
24483                
24484                if ($(data).attr('id') == 'pop-membership-service-edit') {
24485                	_popEditTypeService = data;
24486                } else if ($(data).find('#pop-membership-service-edit').length) {
24487                	_popEditTypeService = $(data).find('#pop-membership-service-edit').outerHTML();
24488                } else {
24489                	GLO.Popup.Warning.open('Unable to Add Custom Service to this Member\'s Profile', 'Member Custom Service');
24490                	return;
24491                }
24492                
24493                _cMembership.openAddCustomService2(clientId, membershipId);
24494            })
24495            .error(function(jqXHR, textStatus, errorThrown) { });
24496    }
24497    _cMembership.openAddCustomService2 = function(clientId, membershipId) {
24498    	var jpopAddCustomSvc = _cMembership.openEditService2(clientId, membershipId).attr('client_id', clientId);
24499    	var jpopMember = $('#pop-member-view').closest('.glopop');
24500    	
24501    	var clientName = jpopMember.find('.client-name-link').text();
24502    	var spanStart = '<span style="display: inline-block; white-space: nowrap; margin-right: 12px; color: white;">';
24503    	
24504    	if (!UTIL.isEmpty(clientName)) {
24505    		jpopAddCustomSvc.find('h1').html(spanStart + 'Add Custom Service</span>' + spanStart + clientName + ' Membership</span>');
24506    		jpopAddCustomSvc.find('#pop-mse-require').remove();		//removes row for 'Require_Membership_fl'
24507    	}
24508    }
24509    _cMembership.openEditService2 = function(clientId, membershipId, membershipServiceId, limit, rolloverUnused, svcFilter, discountMoney, discountPercent, commissionPrice) {
24510    	if (!UTIL.isEmpty(clientId)) {
24511    		var strFnRemove = null, h1 = 'Add Custom Service';
24512    	} else if (!UTIL.isEmpty(membershipServiceId)) {
24513    		var strFnRemove = 'GLO.Provider.Membership.removeService()';
24514    		var h1 = 'Edit Membership Service';
24515    	} else {
24516    		var strFnRemove = null, h1 = 'Add Membership Service';
24517    	}
24518    	
24519    	var jpop = _openPopup(_popEditTypeService, h1, GLO.Provider.Membership.saveService, strFnRemove).attr('membership_id', membershipId);
24520    	
24521    	jpop.attr('membership_service_id', membershipServiceId);
24522		jpop.find('.Service_Filter').val(svcFilter);
24523		jpop.find('#Limit_nr').val(limit);
24524		jpop.find('#Rollover_Unused_pct').val(rolloverUnused);
24525		jpop.find('#Service_Commission_Price_mn').val(UTIL.displayMoney(commissionPrice, true, false, true));
24526		
24527		if (!UTIL.isEmpty(discountMoney)) {
24528			jpop.find('#Discount_Money_fl').prop('checked', true);
24529			jpop.find('#Discount_mn').val(discountMoney);
24530		} else if (!UTIL.isEmpty(discountPercent)) {
24531			jpop.find('#Discount_Percent_fl').prop('checked', true);
24532			jpop.find('#Discount_pct').val(discountPercent);
24533		} else {
24534			jpop.find('#Free_fl').prop('checked', true);
24535		}
24536		
24537    	jpop.find('#Discount_Money_fl').click(function() { UI.changeFocus(this, 'Discount_mn'); });
24538		jpop.find('#Discount_Percent_fl').click(function() { UI.changeFocus(this, 'Discount_pct'); });
24539		
24540		jpop.find('#Discount_mn').change(function() { UI.markCheckbox(this, 'Discount_Money_fl'); }).change();
24541		jpop.find('#Discount_pct').change(function() { UI.markCheckbox(this, 'Discount_Percent_fl'); }).change();
24542		return jpop;
24543    }
24544    function _openPopup(htm, h1, fnSave, strFnDelete) {
24545    	var ojpop = GLO.Popup.Custom.openSimple(htm, h1, fnSave, null, true);
24546		var jpop = ojpop.getPopup();
24547		var btnSave = jpop.find('.btnSave');
24548		
24549		jpop.find(':text, select').change(function() { UI.buttonDisplayChange(btnSave); });
24550    	jpop.find(':text').keyup(function() { UI.buttonDisplayChange(btnSave); });
24551    	
24552    	jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none", "letter-spacing": "1px", "font-size": "larger" }).find('>a').text('Close');
24553    	
24554    	if (!UTIL.isEmpty(strFnDelete)) {
24555	    	var btnDelete = '<span class="btnDelete" style="position: absolute; left: 8px; margin: 0;">
24555<a onclick="' + strFnDelete + '">Delete</a></span>';
24556	    	jpop.find('.pop-buttons').prepend(btnDelete);
24557    	}
24558    	
24559    	if (innerWidth < 640) {
24560    		jpop.css({ "width": "98%" });
24561    	} else {
24562    		jpop.css({ "width": "600px" });
24563    	}
24564    	
24565    	ojpop.realign();
24566    	return jpop;
24567    }
24568    
24569    _cMembership.getIcon = function(membershipId, cid, cname) {
24570    	var arr = GLO.Data.provider.MembershipList;
24571    	
24572    	for (var i=0; i < arr.length; i++) {
24573    		if (arr[i].id == membershipId) {
24574    			var css = '', nm = arr[i].name + ' (' + _cMembership.getPeriodName(arr[i].period) + ')';
24575    			
24576    			if (!UTIL.isEmpty(arr[i].color)) {
24577    				css = 'color: ' + arr[i].color + ';';
24578    			}
24579    			
24580    			var fn = 'GLO.Provider.Membership.Client.openViewMemberFromTicket(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)';
24581    			var icon = '<span onclick="' + fn + '" style="' + css + '">' + UTIL.coalesce(arr[i].letter, 'M') + '</span>';
24582    			var cssClass = 'client-membership-icon' + UserPortal.Price.Discount.getMembershipIconClass(cid);
24583    			
24584    			return '<span class="' + cssClass + '" membership_id="' + membershipId + '" title="' + nm + '">' + icon + '</span>';
24585    		}
24586    	}
24587    	
24588    	return {};
24589    }
24590    _cMembership.getName = function(membershipId, includePeriod) {
24591    	var arr = GLO.Data.provider.MembershipList;
24592    	
24593    	for (var i=0; i < arr.length; i++) {
24594    		if (arr[i].id == membershipId) {
24595    			var name = arr[i].name;
24596    			
24597    			if (includePeriod) {
24598    				name += ' <small style="letter-spacing: 0; font-weight: normal;">(' + _cMembership.getPeriodName(arr[i].period) + ')</small>';
24599    			}
24600    			
24601    			return name
24602    		}
24603    	}
24604    	
24605    	return '';
24606    }
24607    _cMembership.getPeriodNameCount = function(period, count) {
24608    	var nm;
24609    	
24610    	if (period == 10) {
24611    		nm = 'day';
24612    	} else if (period == 20) {
24613    		nm = 'week';
24614    	} else if (period == 30 || period == 40 || period == 50 || period == 60) {
24615    		nm = 'month';
24616    		
24617    		if (period == 40) {
24618    			count = count * 2;
24619    		} else if (period == 50) {
24620    			count = count * 3;
24621    		} else if (period == 60) {
24622    			count = count * 6;
24623    		}
24624    	} else if (period == 70) {
24625    		nm = 'year';
24626    	} else if (period == 100) {
24627			nm = 'lifetime';
24628		}
24629		
24630		return UTIL.pluralLabel(count, nm);
24631    }
24632    _cMembership.getPeriodName = function(period) {
24633    	if (period == 10) { return 'Daily'; }
24634		if (period == 20) { return 'Weekly'; }
24635		if (period == 30) { return 'Monthly'; }
24636		if (period == 40) { return 'Bi-Monthly'; }
24637		if (period == 50) { return 'Quarterly'; }
24638		if (period == 60) { return 'Semi-Annual'; }
24639		if (period == 70) { return 'Annual'; }
24640		if (period == 100) { return 'Lifetime'; }
24641		return '';
24642    }
24643    _cMembership.getPeriodMonthCount = function(period) {
24644    	if (period == 30) { return 1; }
24645		if (period == 40) { return 2; }
24646		if (period == 50) { return 3; }
24647		if (period == 60) { return 6; }
24648		if (period == 70) { return 12; }
24649		
24650		return 0;
24651    }
24652    _cMembership.getPeriodEnd = function(period, dtStart) {
24653    	if (period == 10) {
24654    		return new Date(dtStart).addDays(1);
24655    	} else if (period == 20) {
24656    		return new Date(dtStart).addDays(7);
24657    	}
24658    	
24659    	var months = _cMembership.getPeriodMonthCount(period);
24660    	return new Date(new Date(dtStart).setMonth(dtStart.getMonth() + months));
24661    }
24662    
24663    _cMembership.switchToChangeStatus = function(element, event) {
24664    	var dd = '<select id="Member_Status_cd">'
24665		    		+ '<option value="0">New</option>'
24666		    		+ '<option value="50">Active</option>'
24667		    		+ '<option value="30">Unpaid</option>'
24668		    		+ '<option value="40">Partial Payment</option>'
24669		    		+ '<option value="500">Payment Issue</option>'
24670		    		+ '<option value="900">Inactive</option>'
24671	    		+ '</select>';
24672    	
24673    	var jelement = $(element);
24674    	var mstatus = jelement.attr('member_status_cd');
24675    	var jparent = jelement.parent();
24676    	
24677    	jelement.replaceWith(dd);
24678    	jparent.find('#Member_Status_cd').val(mstatus);
24679    }
24680    
24681    _cMembership.getMembershipDropDown = function() {
24682    	var dd = '<select id="Membership_id"> <option value=""></option>';
24683    	var arr = GLO.Data.provider.MembershipList;
24684    	
24685    	for (var i=0; i < arr.length; i++) {
24686    		dd += '<option value="' + arr[i].id + '" period_cd="' + arr[i].period + '" title="' + arr[i].description + '">' + arr[i].name + '</option>';
24687    	}
24688    	
24689    	return dd + '</select>';
24690    }
24691    
24692	function _saveIsValid(jcontainer) {
24693    	var fnSave = function() { GLO.Provider.Membership.save(true); }
24694    	
24695    	if (false) {
24696    		var fnAction = function() {
24697    			GLO.Popup.close($('#pop-confirm-membership-save').closest('.glopop'));
24698    			GLO.Provider.Membership.save();
24699    		}
24700    		
24701    		var htm = '<div id="pop-confirm-membership-save" style="margin-top: 8px;">Do you want to Save Membership Changes?</div>';
24702    		GLO.Popup.Confirm.open(htm, 'Save Membership?', fnAction, fnSave);
24703    		return false;
24704    	}
24705    	
24706    	return true;
24707    }
24708    
24709    _cMembership.remove = function() {
24710    	var jpop = $('#pop-membership-edit').closest('.glopop');
24711    	var msg = '<p style="color: rgb(240,0,0);">Are you sure you want to delete the membership</p>';
24712    	var membershipName = '<p style="text-align: center; font-size: larger;">' + jpop.find('#Membership_Name_vc').val() + '</p>';
24713    	var htm = '<div id="pop-confirm-member-service-remove" style="margin-top: 8px; font-weight: bold;">' + msg + membershipName + '</div>';
24714	    
24715	    GLO.Popup.Confirm.open(htm, 'Confirm Delete Membership', GLO.Provider.Membership.removeConfirmed);
24716    }
24717    
24718    _cMembership.removeConfirmed = function() {
24719    	var jpop = $('#pop-membership-edit').closest('.glopop');
24720    	var membershipId = UTIL.cleanString(jpop.attr('membership_id'));
24721    	var jbtn = jpop.find('.btnDelete');
24722		var uri = GLO.Link.WebsiteDomain + 'membership/delete?membership=' + membershipId;
24723    	
24724		GLO.UI.Form.beginProcessing(jbtn);
24725		
24726		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false })
24727            .success(function(data, textStatus, jqXHR) {
24728                GLO.Popup.close(jpop);						//GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
24729                var tr = $('#membership-list tr[membership_id="' + membershipId + '"]');
24730                var trAddSvcBtn = tr.next();
24731                
24732                tr.remove();
24733                
24734                if (trAddSvcBtn.hasClass('membership-type-service-add')) {
24735                	trAddSvcBtn.remove();
24736                }
24737                
24738                var jtbody = $('table#membership-list').find('tbody');
24739                jtbody.find('tr.odd-row-membership').removeClass('odd-row-membership');
24740    			_initTable(jtbody);
24741            })
24742            .error(function(jqXHR, textStatus, errorThrown) {
24743                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
24744            });
24745    }
24746    
24747    _cMembership.removeService = function() {
24748    	var jpop = $('#pop-membership-service-edit').closest('.glopop');
24749    	var membershipId = jpop.attr('membership_id');
24750    	var membershipName = GLO.ClientProfile.getMembership(membershipId).name;
24751    	var htm = '<div id="pop-confirm-member-service-remove">' + 'Are you sure you want to remove this service from the membership ' + membershipName + '?</div>';
24752	    
24753	    GLO.Popup.Confirm.open(htm, 'Confirm Remove Membership Service', GLO.Provider.Membership.removeServiceConfirmed);
24754    }
24755    
24756    _cMembership.removeServiceConfirmed = function() {
24757    	var jpop = $('#pop-membership-service-edit').closest('.glopop');
24758    	var membershipId = UTIL.cleanString(jpop.attr('membership_id')), membershipServiceId = UTIL.cleanString(jpop.attr('membership_service_id'));
24759    	var jbtn = jpop.find('.btnDelete');
24760		var uri = GLO.Link.WebsiteDomain + 'membership/deleteService?membership=' + membershipId + '&msid=' + membershipServiceId;
24761    	
24762		GLO.UI.Form.beginProcessing(jbtn);
24763		
24764		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false })
24765            .success(function(data, textStatus, jqXHR) {
24766                GLO.Popup.close(jpop);
24767            	$('#membership-list tr.membership-type-service[membership_service_id="' + membershipServiceId + '"]').remove();
24768            })
24769            .error(function(jqXHR, textStatus, errorThrown) {
24770                GLO.UI.Form.resetProcessing();
24771            });
24772    }
24773    
24774    _cMembership.changeEmailRemindDays = function() {
24775    	var j = $('#pop-membership-edit-reminder');
24776    	var jhas = j.find('#Email_Reminder_fl');
24777    	var days = UTIL.coalesceInt(j.find('#Email_Reminder_Day_sr').val(), 0);
24778    	
24779    	if (days > 0) {
24780    		jhas.prop('checked', true);
24781    	} else {
24782    		jhas.prop('checked', false);
24783    	}
24784    }
24785    _cMembership.save = function() {
24786    	var jpop = $('#pop-membership-edit').closest('.glopop');
24787		var membershipId = UTIL.cleanString(jpop.attr('membership_id'));
24788		var period = jpop.find('#Membership_Period_cd').val(), billPeriod = jpop.find('#Billing_Period_cd').val();
24789		var price = UTIL.coalesceMoney(jpop.find('#Membership_Price_mn').val());
24790		var name = UTIL.htmlEncode(jpop.find('#Membership_Name_vc').val()), description = UTIL.htmlEncode(jpop.find('#Membership_Description_vc').val());
24791		var webAccess = jpop.find('#Web_cd').val();
24792		
24793		var uri = GLO.Link.WebsiteDomain + 'membership/save?membership=' + membershipId + '&period=' + period + '&price=' + price;
24794		var jbtn = jpop.find('.btnSave');
24795		var jd = { "name": name, "description": description, "web": webAccess };
24796		
24797		if (UTIL.isEmpty(period)) {
24798			GLO.Popup.Warning.open('Please Enter a Membership Period', 'Membership Period Required', function() { jpop.find('#Membership_Period_cd').focus(); });
24799			return;
24800		}
24801		
24802		if (UTIL.parseBool(jpop.find('#Auto_Billing_fl').prop('checked'))) { uri += '&autobill=1'; }
24803		if (!UTIL.isEmpty(billPeriod)) { uri += '&billperiod=' + billPeriod; }
24804		
24805		if (jpop.find('#Email_Reminder_fl').prop('checked')) {
24806			jd.emailremind = jpop.find('#Email_Reminder_Day_sr').val();
24807		}
24808		
24809		GLO.UI.Form.beginProcessing(jbtn);
24810		
24811        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
24812            .success(function(data, textStatus, jqXHR) {
24813                GLO.Popup.close(jpop);				//GLO.UI.Form.resetProcessing();
24814            	var jtbody = $('#membership-list').removeClass('hide').find('tbody');
24815            	
24816            	if (!UTIL.isEmpty(membershipId)) {
24817            		jtbody.find('tr.membership-type-service[membership_id="' + membershipId + '"]').remove();
24818            		jtbody.find('tr.membership-type[membership_id="' + membershipId + '"]').replaceWith(data);
24819            	} else {
24820            		jtbody.append(data);
24821            	}
24822            	
24823            	_initTable(jtbody);
24824            })
24825            .error(function(jqXHR, textStatus, errorThrown) {
24826                GLO.UI.Form.resetProcessing();
24827            });
24828    }
24829    
24830    _cMembership.saveService = function() {
24831    	var jpop = $('#pop-membership-service-edit').closest('.glopop');
24832		var membershipId = UTIL.cleanString(jpop.attr('membership_id')), msid = UTIL.cleanString(jpop.attr('membership_service_id')), clientId = UTIL.cleanString(jpop.attr('client_id'));
24833		var limit = jpop.find('#Limit_nr').val();
24834		var rolloverUnused = UTIL.cleanString(jpop.find('#Rollover_Unused_pct').val());
24835		var jbtn = jpop.find('.btnSave');
24836		
24837		var discountMoney = '', discountPercent = '', sgid = '', svcid = '', isRequireMembership = 0;
24838		var svc = jpop.find('.Service_Filter').val();
24839		var price = UTIL.coalesceMoney(jpop.find('#Service_Commission_Price_mn').val());
24840		
24841		if (!UTIL.isEmpty(svc)) {
24842			isRequireMembership = jpop.find('#Require_Membership_fl').prop('checked');
24843			
24844			if (svc.substring(0,2) === 'sg') {
24845				sgid = svc.substring(2);
24846				
24847				if (false && isRequireMembership) {
24848					var htm = '<div style="text-align: center;">To require membership please select a service <span style="display: block; white-space: nowrap;">(not a group of services)</span></div>';
24849					GLO.Popup.Warning.open(htm, 'Service Not Selected');
24850					return;					//isRequireMembership = 0;
24851				}
24852			} else {
24853				svcid = svc;
24854				sgid = UserPortal.getServiceGroupId(svcid);
24855			}
24856		}
24857		
24858		if (jpop.find('#Discount_Money_fl').prop('checked')) {
24859			discountMoney = jpop.find('#Discount_mn').val();
24860		} else if (jpop.find('#Discount_Percent_fl').prop('checked')) {
24861			discountPercent = jpop.find('#Discount_pct').val();
24862		} else if (jpop.find('#Free_fl').prop('checked')) {
24863			discountPercent = 100;
24864		}
24865		
24866		var uri = GLO.Link.WebsiteDomain + 'membership/SaveService?membership=' + membershipId + '&msid=' + msid + '&client=' + clientId 
24867				+ '&limit=' + limit + '&sgid=' + sgid + '&svcid=' + svcid + '&isrequire=' + isRequireMembership 
24868				+ '&money=' + discountMoney + '&percent=' + discountPercent + '&price=' + price + '&rolloverUnused=' + rolloverUnused;
24869		
24870		GLO.UI.Form.beginProcessing(jbtn);
24871		
24872        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: {} })
24873            .success(function(data, textStatus, jqXHR) {
24874                GLO.Popup.close(jpop);
24875            	
24876            	if (_reloadMemberProfile(clientId, 'with new custom member service')) {
24877            		return;
24878            	}
24879            	
24880            	var tbody = $('#membership-list').find('tbody');
24881            	var isOddRow = tbody.find('tr.membership-type[membership_id="' + membershipId + '"]').hasClass('odd-row-membership');
24882            	
24883            	if (isOddRow) { data = $(data).addClass('odd-row-membership'); }
24884            	
24885            	if (!UTIL.isEmpty(msid)) {
24886            		tbody.find('tr[membership_service_id="' + msid + '"]').replaceWith(data);
24887            	} else {
24888            		var tr = tbody.find('tr.membership-type-service[membership_id="' + membershipId + '"]:last');
24889            		
24890            		if (tr.length === 0) {
24891            			tr = tbody.find('tr.membership-type[membership_id="' + membershipId + '"]');
24892            		}
24893            		
24894            		tr.after(data);
24895            	}
24896            })
24897            .error(function(jqXHR, textStatus, errorThrown) {
24898                GLO.UI.Form.resetProcessing();
24899            });
24900    }
24901    function _reloadMemberProfile(clientId, msgCustom) {
24902    	if (!UTIL.isEmpty(clientId)) {
24903		    var jpopMember = $('#pop-member-view').closest('.glopop');
24904		    var clientName = jpopMember.find('.client-name-link').text();
24905	    	
24906	    	if (jpopMember.length) {
24907	    		var htm = '<div id="pop-loading-view-member">Updating ' + clientName + ' member profile ' + msgCustom + '...</div>';
24908	    		
24909	    		GLO.Popup.close(jpopMember);
24910	    		GLO.Popup.Processing.open(htm, 'Updating Member Profile');
24911	    		GLO.Provider.Membership.Client.openViewMember(clientId, clientName);
24912	    		
24913	    		return true;
24914	    	}
24915	    }
24916	    
24917	    return false;
24918    }
24919    _cMembership.validateMembershipPurchase = function(jPricePop) {
24920    	if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10) { return true; }
24921    	
24922    	var jproduct = jPricePop.find('tr.appt-product-row .booking-product');
24923    	
24924    	if (jproduct.length === 0) { return true; }
24925    	
24926    	var currentMembershipId = UserPortal.Price.Discount.getMembershipId(jPricePop);
24927		var newMembershipId = null;
24928		
24929		for (var i=0; i < jproduct.length; i++) {
24930			var rowMembershipId = jproduct.eq(i).attr('membership_id');
24931			
24932			if (!UTIL.isEmpty(newMembershipId) && !UTIL.isEmpty(rowMembershipId) && newMembershipId != rowMembershipId) {
24933				var htm = '<div id="pop-membership-purchase-warning"><p>Cannot purchase more than one type of membership</p><p>A client can only have one membership at a time</p></div>';
24934				GLO.Popup.Warning.open(htm, 'Multiple Memberships');
24935				return false;
24936			} else {
24937				newMembershipId = rowMembershipId;
24938			}
24939		}
24940		
24941		if (!UTIL.isEmpty(newMembershipId)) {
24942			var h2 = jPricePop.find('h2');
24943			var userId = UTIL.coalesce(h2.attr('user_id'), h2.attr('client_id'), h2.find('.client-name-header-link').attr('cid'));
24944			
24945			if (UTIL.isEmpty(userId) || String(userId).substring(0,1) === 'S') {
24946            	var htm = '<div id="pop-membership-purchase-warning"><p>Client required on ticket to purchase membership</p></div>';
24947				GLO.Popup.Warning.open(htm, 'Client Required');
24948				return false;
24949			}
24950		}
24951		
24952		//changing membership: if (UTIL.coalesce(newMembershipId, currentMembershipId, 0
24952) != UTIL.coalesce(currentMembershipId, newMembershipId, 0)) { }
24953		
24954		return true;
24955    }
24956    
24957    function _getPeriodDropDown(id) {
24958    	var id = UTIL.coalesceString(id, 'Membership_Period_cd');
24959    	
24960    	return '<select id="' + id + '" name="' + id + '">'
24961            + '<option value="">(same as Membership period)</option>'
24962	            + '<!-- <option value="20">Weekly</option> -->'
24963	            + '<option value="30">Monthly</option>'
24964	            + '<!-- <option value="40" title="Every Other Month">Bi-Monthly</option> -->'
24965	            + '<option value="50" title="Every 3 Months">Quarterly</option>'
24966	            + '<option value="60" title="Every 6 Months">Semi-Annual</option>'
24967	            + '<option value="70">Yearly</option>'
24968	        + '</select>';
24969    }
24970    
24971    _cMembership.openMemberOnlyServiceHelp = function(icon) {
24972    	var msgMore = '<i class="narrow-text">(clients with this membership or another membership you setup that also includes this service)</i>';
24973    	var msg = '<p>When you check the box <b style="color: purple;">This Service Requires Membership</b> then this service can only be booked by clients who have a membership</p>' + msgMore + '</p>';
24974    	var htm = '<div id="pop-help-membership-service-rollover" style="margin-bottom: 8px;"><div>' + msg + '</div></div>';
24975    	var h1 = 'Member Only Services';
24976    	GLO.Popup.Info.open(htm, h1);
24977    }
24978    _cMembership.openServiceRolloverHelp = function(icon) {
24979    	var msg1 = 'Rollover 0% to 100% of un-used services to the next membership period';
24980    	var htm = '<div id="pop-help-membership-service-rollover" style="margin-bottom: 8px;"><div>' + msg1 + '</div></div>';
24981    	var h1 = 'Rollover Un-Used Services';
24982    	GLO.Popup.Info.open(htm, h1);
24983    }
24984    _cMembership.openServicePriceHelp = function(icon) {
24985    	var msg1 = 'Membership Service Commission Price';
24986    	var li1 = '<li>used when calculating staff commission</li>';
24987    	var li2 = '<li>the membership price does not have to equal the <span style="font-size: 100%; color: purple;">commission price</span></li>';
24988    	//var li3 = '<li>the <span style="font-size: 100%; color: purple;">membership service commission price</span> helps you account for costs</li>';
24989    	//var li4 = '<li>the membership price is what the client pays</li>';
24990    	//var li5 = '<li>helpful when breaking down how the membership should be priced</li>';
24991    	
24992    	var setupScreen = '<a style="letter-spacing: 0; font-size: 90%;" onclick=\'GLO.Report.Template2.goToReport("Membership Setup", "membership", event)\'>Membership Setup Screen</a>';
24993		var rpt = '<a style="letter-spacing: 0; font-size: 90%;" onclick=\'GLO.Report.Template2.goToReport("Membership Report", "membership/report", event)\'>Membership Report</a>';
24994		var msg3 = 'Set the default membership service commission price on the ' + setupScreen + ' and set for specific clients on the ' + rpt;
24995    	var h1 = 'Membership Service Commission Price';
24996    	
24997    	var jPopMemberProfile = $('#pop-member-view').closest('.glopop');
24998    	
24999    	if (icon && jPopMemberProfile.length) {
25000    		var jsvc = $(icon).closest('li.membership-service-row');
25001    		var svcName = jsvc.find('.membership-service-label').text();
25002    		var memberProfileServiceList = _openServicePriceHelp_MemberProfile(jsvc);
25003    		
25004    		if (!UTIL.isEmpty(svcName)) {
25005    			h1 = UTIL.cleanString(jPopMemberProfile.find('h1 .client-name-link').text() + ' ') + svcName + ' Commission Price';
25006    		}
25007    	} else {
25008    		var memberProfileServiceList = _openServicePriceHelp_MembershipSetup();
25009    		var svcName = $('#pop-membership-service-edit').closest('.glopop').find('.Service_Filter option:selected').text();
25010    		
25011    		if (!UTIL.isEmpty(svcName)) {
25012    			h1 = svcName + ' Membership Commission Price';
25013    		}
25014    	}
25015    	
25016    	msg1 = '<div>' + msg1 + '<ul style="padding-left: 12px;">' + li1 + li2 + '</ul></div>';			// + li3 + li4 + li5
25017    	var htm = '<div id="pop-help-membership-service-price">' + msg1 + '<div style="padding-bottom: 12px;">' + msg3 + '</div>' + memberProfileServiceList + '</div>';
25018    	
25019    	GLO.Popup.Info.open(htm, h1).getPopup().css({ "background-color": "white" });
25020    }
25021    
25022    _cMembership.changeCostPerService = function(btn) {
25023    	var jparent = $(btn).closest('#pop-preview-cost-per-service');
25024    	var cost = UTIL.coalesceMoney(jparent.find('#Cost_Per_Service_mn').val());
25025    	var limit = UTIL.coalesceInt(jparent.attr('limit_sr'));
25026    	var msid = jparent.attr('membership_service_id');
25027    	var totalCost = UTIL.displayMoney(cost * limit, true, false, true);
25028    	var jPopMemberProfile = $('#pop-member-view').closest('.glopop');
25029    	
25030    	if (jPopMemberProfile.length) {
25031    		jPopMemberProfile.find('#membership-service-list li[membership_service_id="' + msid + '"]').find('input.cost').val(totalCost);
25032    	} else {
25033    		var jPopMembershipService = $('#pop-membership-service-edit').closest('.glopop');
25034    		jPopMembershipService.find('#Service_Commission_Price_mn').val(totalCost);
25035    	}
25036    	
25037    	GLO.Popup.close($('#pop-help-membership-service-price').closest('.glopop'));
25038    }
25039    
25040    function _getCostPerServiceHtm(cost, limit, msid) {
25041    	if (limit > 0) {
25042	    	var label = '<label for="Cost_Per_Service_mn">Commission Price per Service</label> <span class="dollar-sign">$</span>';
25043	    	var htmInput = '<input id="Cost_Per_Service_mn" type="text" value="' + UTIL.displayMoney(cost/limit, true) + '"/>';
25044	    	var btnSave = '<span class="btnAdd"><a onclick="GLO.Provider.Membership.changeCostPerService(this)">Change</a></span>';
25045	    	
25046	    	return '<div id="pop-preview-cost-per-service" limit_sr="' + limit + '" membership_service_id="' + UTIL.cleanString(msid) + '">' + label + htmInput + btnSave + '</div>';
25047	    } else {
25048	    	return '';
25049	    }
25050    }
25051    
25052    function _openServicePriceHelp_MembershipSetup() {
25053    	var jpop = $('#pop-membership-service-edit').closest('.glopop');
25054    	var cost = UTIL.coalesceMoney(jpop.find('#Service_Commission_Price_mn').val());
25055    	var limit = UTIL.coalesceInt(jpop.find('#Limit_nr').val(), 0);
25056    	
25057    	return _getCostPerServiceHtm(cost, limit);
25058    }
25059    
25060    function _openServicePriceHelp_MemberProfile(jsvc) {
25061    	var totalPrice = UTIL.coalesceMoney(jsvc.find('.adjust-total-service-price .cost').val());
25062		var msid = jsvc.attr('membership_service_id');
25063		var htm = '', cnt = 0, remaining = UTIL.coalesceInt(jsvc.find('.remaining').val(), 0);
25064		
25065		while (jsvc.next().hasClass('membership-appt-row')) {
25066			jsvc = jsvc.next();
25067			++cnt;
25068		}
25069		
25070		if (cnt > 0 || remaining > 0) {
25071    		htm += '<div style="margin-top: 6px; font-size: 16px; font-weight: bold;"><label>Scheduled Appointments <small>(this period)</small></label> = <span>' + cnt + '</span></div>';
25072			htm += '<div style="margin-top: 12px; font-size: 16px; font-weight: bold;"><label>Remaining Appointments <small>(this period)</small></label> = <span>' + remaining + '</span></div>';
25073			htm += '<div style="margin-top: 6px; font-size: 16px; font-weight: bold;"><label>Total Appointments <small>(this period)</small></label> = <span>' + (remaining + cnt) + '</span></div>';
25074    		htm += _getCostPerServiceHtm(totalPrice, remaining + cnt, msid);
25075		}
25076		
25077		var htmDefaultCost = '', ms = GLO.ClientProfile.getMembershipService(msid);
25078		
25079		if (ms.limit_nr < 900) {
25080			if (ms.limit_nr > 0 && (totalPrice > 0 || UTIL.coalesceMoney(ms.price_mn) > 0)) {
25081				htmDefaultCost = '<span id="membership-service-default-cost"> (commission price of ' + UTIL.displayMoney(UTIL.coalesceMoney(ms.price_mn)/ms.limit_nr) + ' per service) </span>';
25082			}
25083			
25084			htm += '<div id="pop-help-membership-service-default"><span id="membership-service-default-label">Normal Membership Service Setup: </span>';
25085			htm += '<span id="membership-service-default-limit">' + UTIL.pluralLabel(ms.limit_nr, 'service') + '</span>' + htmDefaultCost;
25086			htm += '<span id="membership-service-default-rollover"> rollover ' + UTIL.coalesceInt(ms.rollover_unused_pct) + '% of un-used services</span> </div>';
25087		}
25088		
25089		return htm;
25090    }
25091    
25092    _cMembership.Client = (function() {
25093	    function _cMemberClient() {}
25094	    
25095	    _cMemberClient.open = function(btn) {
25096	    	var jclient = $('form#client-form');
25097	    	var membershipId = jclient.find('#Membership_id').val();
25098	    	var cid = jclient.find('#Client_id').val();
25099	    	var cname = UTIL.coalesce(jclient.find('#Full_Name_vc').val(), jclient.find('#First_Name_vc').val() + ' ' + jclient.find('#Last_Name_vc').val());
25100	    	var linkedProviderId = $('#clientProfile-buttons #clientProfile-import').attr('link_provider_id');
25101	    	
25102	    	if (!UTIL.isEmpty(membershipId)) {
25103	    		GLO.UI.Form.beginProcessing(btn);
25104	    		_cMemberClient.openViewMember(cid, cname, null, null, linkedProviderId);
25105	    	} else {
25106	    		_openAddMember(jclient, cid, cname);
25107	    	}
25108	    }
25109	    
25110	    function _getViewMemberProfileLink(cid, cname) {
25111	    	var clientName = UTIL.replaceQuotesTitle(cname);
25112	    	var btnViewMember = '<a onclick="GLO.Provider.Membership.Client.openViewMember(' + cid + ', \'' + clientName + '\', this)">View Member Profile</a>';
25113	    	var htmViewMember = '<div id="pop-member-view-profile" style="margin-top: 12px;"><span id="btnViewMember" class="btnAdd">' + btnViewMember + '</span></div>';
25114	    	return htmViewMember;
25115	    }
25116	    
25117	    _cMemberClient.openPaySummaryByClientId = function(cid) {
25118	    	GLO.Popup.close($('#pop-member-profile'));
25119	    	
25120	    	var td = $('#membership-report').find('tr[client_id=' + cid + ']').find('.membership-column-next-bill-date');
25121	    	
25122	    	_cMemberClient.openPaySummary(td);
25123	    }
25124	    
25125	    _cMemberClient.openPaySummary = function(btn) {
25126	    	//GLO.Popup.Processing.open(msg, h1);
25127	    	var tr = $(btn).closest('tr');
25128	    	var cid = tr.attr('client_id'), iid = tr.attr('inventory_id'), mcid = tr.attr('membership_client_id'), status = tr.attr('member_status_cd');
25129	    	var membershipId = tr.attr('membership_id'), nextMembershipId = tr.attr('next_membership_id');
25130	    	var nextBillDate = tr.attr('next_bill_dt'), periodEndDate = tr.attr('period_end_dt')
25131	    	var payCount = UTIL.coalesceInt(tr.attr('payment_count_sr')), lastPurchaseDate = tr.attr('last_purchase_dt');
25132	    	var balance = tr.attr('balance_mn'), payFail = tr.attr('payment_fail_vc'), hasCardOnFile = tr.attr('card_on_file_fl');
25133	    	var autoBill = tr.find('.membership-column-auto-bill .is-auto-bill').length, cname = tr.find('.membership-column-client > a').text();
25134	    	
25135	    	if (UTIL.isDate(nextBillDate)) {
25136	    		periodEndDate = new Date(nextBillDate);
25137	    	} else {
25138	    		periodEndDate = new Date(periodEndDate).addDays(1);
25139	    	}
25140	    	
25141	    	var htmNextPeriod = _getNextPeriodHtm(balance, autoBill, nextMembershipId, true);
25142	    	var htmCardOnFile = _getCardOnFileButton(hasCardOnFile, cid);
25143	    	var htmViewMember = _getViewMemberProfileLink(cid, cname);
25144	    	
25145	    	var btnPreviewNextPeriod = '<a onclick="GLO.Provider.Membership.Client.openPreviewNextPeriod(' + cid + ', this)">
25145Preview Next Period</a>';
25146	    	var htmPreviewNextPeriod = '<div id="pop-member-preview-next-period" style="margin-top: 12px;"><span id="btnPreviewNextPeriod" class="btnAdd">' + btnPreviewNextPeriod + '</span></div>';
25147	    	
25148	    	var htmData = '<input type="hidden" id="Membership_Client_id" value="' + mcid + '"/>';
25149	    	var h3 = '<h3 style="padding: 2px 16px 1px; font-size: 20px; color: white; background-color: #003366;">Membership Payments</h3>';
25150	    	var htmNextPayment = _getNextPayHtm(tr, membershipId, nextMembershipId, cid, cname, payFail, balance, nextBillDate, periodEndDate, status);
25151	    	var htmLastPayment = _getLastPayHtm(cid, cname, iid, payCount, lastPurchaseDate);
25152	    	
25153	    	var htm = '<div id="pop-member-pay-summary" client_id="' + cid + '">' + htmNextPeriod + htmCardOnFile + htmViewMember + htmPreviewNextPeriod + htmData + h3 + htmNextPayment + htmLastPayment + '</div>';
25154            var h1 = '<a class="client-name-link" onclick="GLO.Provider.Membership.Client.openClientProfile(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\')">' + UTIL.coalesce(cname, 'View Member') + '</a>';
25155            
25156            var jpop = GLO.Popup.Custom.openSimple(htm, h1);
25157            jpop.find('h1').css({ "margin-bottom": "0" }).find('a').css({ "border-bottom": "none", "text-decoration": "underline", "color": "white" });
25158            jpop.find('#Auto_Billing_fl').change(GLO.Provider.Membership.Client.saveAutoBill);
25159            jpop.find('.btnSave').remove();
25160            jpop.find('.btnCancel').css({ "position": "relative", "left": "inherit", "float": "none" }).find('>a').text('Close').focus();
25161	    }
25162	    
25163	    _cMemberClient.openApptHistoryByDate = function(element, cid, start, end) {
25164	    	GLO.UI.Form.beginProcessing($(element));
25165	    	GLO.ClientHistory.open(cid, true, null, start, end);
25166	    }
25167	    _cMemberClient.openApptHistory = function(btn) {
25168	    	var tr = $('#membership-report').find('td.cell-summary-selected').closest('tr');
25169	    	var cid = tr.attr('client_id');
25170	    	var start = tr.attr('period_start_dt');
25171	    	var end = tr.attr('period_end_dt');
25172	    	
25173	    	GLO.UI.Form.beginProcessing($(btn));
25174	    	GLO.ClientHistory.open(cid, true, null, start, end);
25175	    }
25176	    
25177	    _cMemberClient.openViewMemberFromTicket = function(cid, cname, btn) {
25178	    	GLO.Popup.closeIfExist($('#pop-warn-member-status').closest('.glopop'));
25179	    	
25180	    	_cMemberClient.openViewMember(cid, cname, btn);
25181	    }
25182	    
25183	    _cMemberClient.openViewMember = function(cid, cname, btn, clickOn, linkedProviderId) {
25184	    	var uri = GLO.Link.WebsiteDomain + 'membership/GetClient?cid=' + cid;
25185	    	var jPopPreview = $('#pop-preview-next-period').closest('.glopop');
25186	    	
25187	    	if (!UTIL.isEmpty(linkedProviderId)) {
25188	    		uri += '&linkedprovider=' + linkedProviderId;
25189	    	}
25190	    	
25191	    	GLO.Popup.closeIfExist(jPopPreview);
25192	    	
25193	    	if (btn) {
25194	    		if ($(btn).hasClass('btnProcessing4')) {
25195	    			return;
25196	    		}
25197	    		
25198	    		GLO.UI.Form.beginProcessing($(btn));
25199	    	}
25200	    	
25201	    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
25202	            .success(function(data, textStatus, jqXHR) {
25203	                GLO.UI.Form.resetProcessing();
25204	                GLO.Popup.closeIfExist($('#pop-loading-view-member').closest('.glopop'));
25205	                
25206	                var isLinkedProviderMembership = false;
25207	                var jsonContainer = JSON.parse(data);
25208	                var json = jsonContainer.member;
25209	                var membership = GLO.ClientProfile.getMembership(json.membership_id);
25210	                
25211	                if (UTIL.isEmpty(membership.id) && !UTIL.isEmpty(linkedProviderId)) {
25212	                	var membership = jsonContainer.membership[0];
25213	                	isLinkedProviderMembership = true;
25214	                }
25215	                
25216	                var membershipName = membership.name;		// GLO.Provider.Membership.getName(json.membership_id, !GLO.Info.isMobile());
25217	                
25218	                if (UTIL.isEmpty(membershipName)) {
25219	                	GLO.Popup.Warning.open('<div id="pop-warn-member-not-found">Unable to find membership</div>', 'Membership Not Found');
25220	                	return;
25221	                } else if ($('#pop-member-view').closest('.glopop').length) {
25222	                	return;			//=member profile already open.
25223	                }
25224	                
25225	                var jhelp = $('#pop-help-cell-summary').closest('.glopop'), jClosePo
25225p = $('#pop-member-pay-summary').closest('.glopop');
25226	                if (jhelp.length) { GLO.Popup.close(jhelp); }					//= if open from sales detail report cell summary automatically opened.
25227	                if (jClosePop.length) { GLO.Popup.close(jClosePop); }
25228	                
25229	                var statusName = GLO.ClientProfile.getStatusName(json.member_status_cd);
25230	                var statusCSS = GLO.ClientProfile.getStatusCSS(json.member_status_cd);
25231	                
25232	                var priceTitle = 'default price = ' + UTIL.displayMoney(membership.price, false, false, true);
25233	                var htmName = '<div id="pop-member-view-name"><b onclick="GLO.Provider.Membership.Client.displayChangeMembership(this)" title="' + priceTitle + '">' + membershipName + '</b></div>';
25234	                var htmStatus = '<span id="pop-member-view-status"><label>Status</label><b>' + statusName + '</b></span>';
25235	                var htmStart = '<span id="pop-member-view-start" start_dt="' + json.start_dt + '"><label>Start Date: </label><b>' + new Date(json.start_dt).toSADate(true) + '</b></span>';
25236	                var htmStartAndStatus = '<div id="pop-member-view-ss">' + htmStart + htmStatus + '</div>';
25237	                var htmCurrentPeriod = _getCurrentPeriodHtm(json.end_dt, json.period_start_dt, json.period_end_dt, cid, cname);
25238	                var htmPrice = _getPriceAndNextHtm(json.price_mn, json.custom_price_mn, json.billing_period_cd, json.next_bill_dt, json.period_end_dt, json.member_status_cd, membership);
25239	                
25240	                var btnPayNow = _getPayNowButton(membership.id, json.next_membership_id, json.next_bill_dt, json.period_end_dt, cid, cname);
25241	                var htmNextPeriod = _getNextPeriodHtm(json.balance_mn, json.auto_billing_fl, json.next_membership_id, false, btnPayNow);
25242	                
25243	                var htmServiceList = _getServiceListHtm(json.services, cid, cname);
25244	                var htmHidden = _getHiddenHtm(json.membership_id, cid);
25245	                var htm = '<div id="pop-member-view">' + htmHidden + htmStartAndStatus + htmCurrentPeriod + htmPrice + htmNextPeriod + htmName + htmServiceList + '</div>';
25246	                
25247	                var h1 = '<a class="client-name-link" onclick="GLO.Provider.Membership.Client.openClientProfile(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\')">' + UTIL.coalesce(cname, 'View Member') + '</a>';
25248	                var h1QuietStart = '<a class="quietest-left quietest no-animate" style="margin-top: 0;" ';
25249	                
25250	                if ($('#membership-report').length > 0) {
25251	                	h1 = h1QuietStart + 'onclick="GLO.Provider.Membership.Client.openPaySummaryByClientId(' + cid + ')">pay summary</a>' + h1;
25252	                } else if (GLO.Info.roleType >= 170) {
25253	                	h1 = h1QuietStart + 'onclick="GLO.Provider.Membership.Client.openMemberPayHistory(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)">payments</a>' + h1;
25254	                }
25255	                
25256	                var ojpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Provider.Membership.Client.save, null, true);
25257	                var jpop = ojpop.getPopup().attr('id', 'pop-member-profile');
25258	                jpop.find('h1').addClass(statusCSS).css({ "margin-bottom": "0" }).find('a').css({ "border-bottom": "none", "text-decoration": "underline", "color": "white" });
25259	                
25260	                var cssCancel = { "position": "relative;", "left": "inherit", "float": "none", "padding": 0, "margin-left": "-4px", "letter-spacing": "1px", "font-weight": "bold", "font-size": "large" };
25261	                var btnCancel = jpop.find('.btnCancel').css(cssCancel);
25262		            
25263	                if (GLO.Info.roleType > 199) {
25264		                var btnDelete = '<span class="btnDelete" style="position: absolute; left: 10px; margin: 0;"><a onclick="GLO.Provider.Membership.Client.remove()">Delete</a></span>';
25265		                btnCancel.before(btnDelete);
25266		                
25267		                jpop.find('#Period_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
25268						jpop.find('#Period_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
25269		            } else {
25270		            	jpop.find('.btnSave').remove();
25271		            	jpop.find('input,select').prop('disabled', true);
25272		            }
25273		            
25274		            _openViewMember2(jpop, json.next_bill_dt, json.billing_period_cd);
25275		            _addMemberProfileHelloBar(jpop);
25276		            
25277		            ojpop.realign();
25278		            btnCancel.find('>a').text('Close');
25279		            jpop.find(':focus').blur();
25280		            
25281		            if (isLinkedProviderMembership) {
25282		            	_setPopupToReadOnly(jpop, true);
25283		            	
25284		            	var css = 'margin-top: 16px; padding: 8px; letter-spacing: 1px; text-align: center; font-weight: bold; background-color: ' + jsonContainer.provider.bgcolor + '; color: white;';
25285		            	var htm = '<p style="' + css + '">this membership is at ' + jsonContainer.provider.name + '</p>';
25286		            	jpop.find('.pop-buttons-parent').before(htm);
25287		            } else if (clickOn) {
25288		            	jpop.find(clickOn).click();
25289		            } else {
25290		            	setTimeout(function() { jpop.find(':focus').blur(); }, 100);
25291		            }
25292	            })
25293	            .error(function(jqXHR, textStatus, errorThrown) {
25294	            	GLO.UI.Form.resetProcessing();
25295	            });
25296	    }
25297	    
25298	    function _addMemberProfileHelloBar(jpop) {
25299	    	jpop.find('#hello-bar-change-next-bill').remove();
25300	    	
25301	    	var dtStart = jpop.find('#Period_Start_dt').val();
25302	    	var dtEnd = jpop.find('#Period_End_dt').val();
25303	    	var dtNextBill = jpop.find('#Next_Bill_dt').val();
25304	    	
25305	    	var billPeriod = jpop.find('#Billing_Period_cd option:selected').attr('value');
25306	    	var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val());
25307	    	
25308	    	if (GLO.Info.roleType > 209 && UTIL.isEmpty(billPeriod) && balance === 0 && UTIL.isDate(dtStart) && UTIL.isDate(dtEnd) && UTIL.isDate(dtNextBill)) {
25309	    		if (new Date(dtNextBill).toGloDate() != new Date(dtEnd).addDays(1).toGloDate()) {
25310	    			var cssClass = '', label = '<label></label>', id = 'hello-bar-change-next-bill';
25311					var aChange = '<a onclick="GLO.Provider.Membership.Client.changeBillDateToDefault()">Change Next Bill Date to Start of Next Period</a>';
25312					var btnChange = '<span class="btnAdd">' + aChange + '</span>';
25313					var htmHello = '<div>' + label + btnChange + '</div>';
25314					
25315	    			GLO.Popup.addHelloBar(jpop, htmHello, id, cssClass);
25316	    		}
25317	    	}
25318	    }
25319	    
25320	    function _setPopupToReadOnly(jpop, isRemoveButtons) {
25321	    	jpop.find('input,select,textarea').prop('disabled', true);
25322	    	
25323	    	if (isRemoveButtons) {
25324	    		jpop.find('.btnAdd, .btnSave, .btnDelete').remove();
25325	    		GLO.Popup.Custom.singleButton(jpop, 'Close');
25326	    	}
25327	    }
25328	    
25329	    function _openViewMember2(jpop, next_bill_dt, billing_period_cd) {
25330	    	if (!UTIL.isEmpty(next_bill_dt) || !UTIL.isEmpty(billing_period_cd)) {
25331	    		GLO.Provider.Membership.Client.changeBillDate();
25332	    		
25333	    		if (billing_period_cd) { jpop.find('#Billing_Period_cd').val(billing_period_cd); }
25334	    		if (UTIL.isDate(next_bill_dt)) { jpop.find('#Next_Bill_dt').val(next_bill_dt); }
25335	    		
25336	    		_cMemberClient.setPricePerPeriod();
25337	    	}
25338	    	
25339	    	if (GLO.Info.roleType < 170) {
25340	    		jpop.find('input,select').prop('disabled', true);
25341	    	} else {
25342	    		jpop.find('input,select').change(function() {
25343	    			$('#pop-member-view').closest('.glopop').find('.btnSave > a').addClass('unsaved');
25344	    		});
25345	    	}
25346	    }
25347	    
25348	    function _getAutoBillStatusHtm(member) {
25349	    	if (!member.card_on_file_fl) {
25350	    		var status = 'No Card on File';
25351	    		var style = 'background-color: rgba(255,0,0,.6);';
25352	    	} else if (member.auto_bill_fl) {
25353	    		var status = 'Enabled';
25354	    		var style = 'background-color: rgba(0,255,0,.8);';
25355	    	} else {
25356	    		var status = 'Disabled';
25357	    		var style = 'background-color: orange;';
25358	    	}
25359	    	
25360	    	return '<div id="pop-preview-bill-status" style="' + style + '"> <label>Auto Billing Status</label> <b style="color: white;">' + status + '</b> </div>'
25361	    }
25362	    
25363	    _cMemberClient.openPreviewNextPeriod = function(cid, btn) {
25364			var tr = $('#membership-report').find('tr[client_id="' + cid + '"]');
25365			var cname = tr.find('td.membership-column-client > a').text();
25366			var member = _getMember(tr);
25367			
25368			if (UTIL.isEmpty(member.membership.name)) {
25369				GLO.Popup.Warning.open('Membership Not Found', 'Membership Deleted?');
25370				return;
25371			}
25372			
25373			var htmAutoBillStatus = _getAutoBillStatusHtm(member);
25374			var htmNewPeriod = '', dueLabel = '', price = '', due = UTIL.displayMoney(member.due_mn, false, false, true);
25375			
25376			if (new Date() > member.bill_dt) {
25377				var dt = 'now';
25378			} else {
25379				var dt = member.bill_dt.toSADate(true);
25380			}
25381			
25382			if (member.new_period_end_dt >= member.bill_dt || new Date() > member.bill_dt) {
25383				price = UTIL.displayMoney(UTIL.coalesceMoney(member.custom_price_mn, member.membership.price, false, false, true));
25384				
25385				if (price > 0) {
25386					if (UTIL.isEmpty(due)) {
25387						dueLabel = 'pre-paid';
25388					} else {
25389						dueLabel = 'Due';
25390					}
25391				}
25392			}
25393			
25394			var htmPayDate = '<span style="float: left;"><label>Next Payment</label> <b>' + dt + '</b></span>';
25395			var htmPayDue = '<span style="float: right;"><label>' + dueLabel + '</label> <b>' + due + '</b></span>';
25396			var htmPay = '<div id="pop-preview-pay-date">' + htmPayDate + htmPayDue + '</div>';
25397			var htmMembership = '<div id="pop-preview-membership" style="clear: both;"> <b>' + member.membership.name + ' <i>' + price + '</i> </div>';
25398			
25399			if (member.is_new_member_period) {
25400				var dateRange = member.new_period_start_dt.toSADate(true) + ' - ' + member.new_period_end_dt.toSADate(true);
25401				htmNewPeriod = '<div id="pop-preview-new-period"> <label>New Member Period</label> <b>' + dateRange + '</b> </div>';
25402				//htmNewPeriod += '<div id="pop-preview-new-period"> <label>Next Billing Date</label> <b>' + member.next_bill_dt.toSADate(true) + '</b> </div>';
25403			//} else if (member.is_custom_bill_period) {
25404			//	htmNewPeriod = '<div id="pop-preview-new-period"> <label>Next Billing Date</label> <b>' + member.next_bill_dt.toSADate(true) + '</b> </div>';
25405			}
25406			
25407			var htmViewMember = _getViewMemberProfileLink(cid, cname);
25408			var htmThrobber = '<div id="pop-preview-throbber" style="margin-top: 16px;">' + GLO.Report.Template2.getBlueThrobber() + '</div>';
25409			var htmServices = '<div id="pop-preview-services">' + '<h4 style="margin-top: 16px;">Member Services</h4>' + htmThrobber + '</div>';
25410			var htm = '<div id="pop-preview-next-period">' + htmAutoBillStatus + htmPay + htmMembership + htmNewPeriod + htmViewMember + htmServices + '</div>';
25411			
25412			if (btn) {
25413				GLO.UI.Form.beginProcessing($(btn));
25414				var jPopPaySummary = $('#pop-member-pay-summary').closest('.glopop');
25415				if (jPopPaySummary.length) { GLO.Popup.close(jPopPaySummary); }
25416			}
25417			
25418			var ojpop = GLO.Popup.Custom.openSimple(htm, cname + ': Preview Next Perio
25418d', null, null, true);
25419			var jpop = ojpop.getPopup();
25420			GLO.Popup.Custom.singleButton(jpop, 'Close');
25421			
25422			jpop.find('h1').css({ "margin-bottom": 0 });
25423			GLO.UI.Form.resetProcessing();
25424			
25425			if (member.is_new_member_period || member.balance_mn >= 0) {
25426				_getNextPeriodServices(cid, jpop, ojpop);
25427			} else {
25428				var htm = '<div id="pop-preview-pay-balance"><p>Same Membership Period</p><p>Next Payment is for Balance Due</p></div>';
25429				jpop.find('#pop-preview-services #pop-preview-throbber').replaceWith(htm);
25430			}
25431	    }
25432	    function _getNextPeriodServices(cid, jpop, ojpop) {
25433	    	var uri = GLO.Link.WebsiteDomain + 'membership/PreviewNextPeriod?client=' + cid;
25434	    	
25435	    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false, "dataType": "json" })
25436	            .complete(function(data, textStatus, jqXHR) {
25437	                var warning = null, arr = data.responseJSON;
25438	                
25439	                if (arr && arr.length > 0) {
25440	                	warning = arr[0].warning_vc
25441	                }
25442	                
25443	                if (!UTIL.isEmpty(warning)) {
25444	                	var htm = '<div>' + warning + '</div>';
25445	                } else {
25446	                	var htm = _getNextPeriodServices2(arr);
25447	                }
25448	                
25449	                jpop.find('#pop-preview-services #pop-preview-throbber').replaceWith(htm);
25450	                ojpop.realign(); ojpop.realign(); ojpop.realign();
25451	            });
25452	            //.error(function(jqXHR, textStatus, errorThrown) { });
25453	    }
25454	    function _getNextPeriodServices2(arr) {
25455	    	var htm = '';
25456	    	
25457	    	for (var i=0; i < arr.length; i++) {
25458            	var nm = UTIL.coalesceString(arr[i].service_vc, 'any service');
25459            	var cost = arr[i].price_mn, costPerService = arr[i].price_per_service_mn;
25460            	
25461            	if (innerWidth < 640) { nm = UTIL.maxString(nm, 20); }
25462            	
25463            	if (UTIL.isEmpty(arr[i].limit_sr)) {
25464            		var rollover = 0, limit = '<span style="letter-spacing: 0; font-weight: normal; font-size: 11px;">unlimited</span>';
25465            	} else {
25466            		var limit = UTIL.coalesceInt(arr[i].limit_sr), rollover = UTIL.coalesceInt(arr[i].rollover_sr);
25467            	}
25468            	
25469            	if (arr[i].discount_pct > 0) {
25470            		var discount = parseInt(arr[i].discount_pct) + '%';
25471            	} else {
25472            		var discount = UTIL.displayMoney(arr[i].discount_mn);
25473            	}
25474            	
25475            	var li = '<li><b class="preview-service-limit">' + limit;
25476            	
25477            	if (rollover > 0) {
25478            		li += '<small class="preview-service-rollover" style="margin-left: 2px;">(' + rollover + ' <span style="font-size: 11px;">rollover</span>)</small>';
25479            	}
25480            	
25481            	li += '</b>' + '<b class="preview-service-name">' + nm + '</b><b class="preview-service-discount">' + discount + '</b>';
25482            	
25483            	if (cost > 0 && limit > 0) {
25484            		li += '<span class="preview-service-cost">Commission: ' + UTIL.displayMoney(cost, false, false, true);
25485            		
25486            		if (limit > 1) {
25487            			li += '<small style="margin-left: 4px;">(' + UTIL.displayMoney(costPerService) + ' per service)</small>';
25488            		}
25489            		
25490            		li += '</span>';
25491            	}
25492            	
25493            	htm += li + '</li>';
25494            }
25495            
25496            return '<ul id="preview-service-list">' + htm + '</ul>';
25497	    }
25498	    
25499	    _cMemberClient.openClientProfile = function(cid, cname) {
25500	    	var jpop = $('#pop-member-view, #pop-member-pay-summary').closest('.glopop');
25501	    	GLO.Popup.close(jpop);
25502	    	ClientProfile.goto(cid, true, cname);
25503	    }
25504	    
25505	    _cMemberClient.openMemberPayHistory = function(cid, cname, btn) {
25506	    	var uri = GLO.Link.WebsiteDomain + 'membership/PaymentHistory?client=' + cid;
25507	    	
25508	    	if (btn) {
25509	    		GLO.UI.Form.beginProcessing($(btn));
25510	    	}
25511	    	
25512	    	var jpop = GLO.Popup.getTopCustomPopup();
25513			if (jpop && jpop.length > 0) { GLO.Popup.close(jpop); }
25514			
25515			$.modal.close();
25516			var ojpop = GLO.Popup.Processing.open(SA.Resource.LookingUp + ' ' + SA.Resource.PaymentHistory + ' for ' + cname + '...', SA.Resource.LookingUp + ' ' + SA.Resource.PaymentHistory);
25517	    	
25518	    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
25519	            .success(function(data, textStatus, jqXHR) {
25520	                GLO.UI.Form.resetProcessing();
25521	                ojpop.close();
25522	                
25523	                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
25524	                	GLO.Popup.Warning.open(data, SA.Resource.PaymentHistory + ' ' + SA.Resource.NotFound);
25525	                	return;
25526	                }
25527	                
25528	                var h1 = '<span style="padding-right: 4px; white-space: nowrap; color: white;">' + cname + '</span> <span style="white-space: nowrap; color: white;">Membership ' + SA.Resource.PaymentHistory + '</span>';
25529	                var jpop = GLO.Popup.Custom.openSimple(data, h1);
25530	                GLO.Popup.Custom.singleButton(jpop);
25531	                var jtbl = jpop.find('#membership-payment-report');
25532	                
25533	                UI.initTableSorter(jtbl);
25534	                
25535	                jpop.find('h1').css({ "margin-bottom": "0" });
25536	            })
25537	            .error(function(jqXHR, textStatus, errorThrown) {
25538	            	GLO.UI.Form.resetProcessing();
25539	            	ojpop.close();
25540	            });
25541	    }
25542	    
25543	    _cMemberClient.openMemberPeriodHistory = function(cid, cname, btn) {
25544	    	var uri = GLO.Link.WebsiteDomain + 'membership/PeriodHistory?client=' + cid;
25545	    	
25546	    	if (btn) {
25547	    		GLO.UI.Form.beginProcessing($(btn));
25548	    	}
25549	    	
25550	    	var jpop = GLO.Popup.getTopCustomPopup();
25551			if (jpop && jpop.length > 0) { GLO.Popup.close(jpop); }
25552			
25553			$.modal.close();
25554			var ojpop = GLO.Popup.Processing.open('Looking up Period History for ' + cname + '...', 'Member Period History');
25555	    	
25556	    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
25557	            .success(function(data, textStatus, jqXHR) {
25558	                GLO.UI.Form.resetProcessing();
25559	                ojpop.close();
25560	                
25561	                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
25562	                	GLO.Popup.Warning.open(data, 'Period History Not Found');
25563	                	return;
25564	                }
25565	                
25566	                var h1 = '<span style="padding-right: 4px; white-space: nowrap; color: white;">' + cname + '</span> <span style="white-space: nowrap; color: white;">Member Period History</span>';
25567	                var jpop = GLO.Popup.Custom.openSimple(data, h1).css({ "max-width": "1100px" });
25568	                GLO.Popup.Custom.singleButton(jpop);
25569	                var jtbl = jpop.find('#member-period-report');
25570	                
25571	                UI.initTableSorter(jtbl);
25572	                GLO.Report.CellSummary.initReport(jtbl, false, true);
25573	                
25574	                jpop.find('h1').css({ "margin-bottom": "0" });
25575	            })
25576	            .error(function(jqXHR, textStatus, errorThrown) {
25577	            	GLO.UI.Form.resetProcessing();
25578	            	ojpop.close();
25579	            });
25580	    }
25581	    
25582	    _cMemberClient.openAddCustomService = function(cid, cname, btn) {
25583	    	var jpopMember = $('#pop-member-view').closest('.glopop');
25584	    	var membershipId = jpopMember.find('#Membership_id').val();
25585	    	GLO.Provider.Membership.openAddCustomService(cid, membershipId);
25586	    }
25587	    
25588	    _cMemberClient.addCardOnFile = function(btn, cid) {
25589	    	var jpop = $('#pop-member-pay-summary');
25590	    	var cid = jpop.attr('client_id');
25591	    	
25592	    	jpop = jpop.closest('.glopop');
25593	    	var cname = UTIL.directTagOnly(jpop.find('.pop-header h1'));
25594	    	
25595	    	ClientProfile.goto(cid, true, cname, ClientProfile.openAddCard);
25596	    	
25597	    	GLO.UI.Form.beginProcessing($(btn));
25598	    }
25599	    
25600	    _cMemberClient.openMemberPayment = function(cid, iid, dt, btn) {
25601	    	var uri = GLO.Link.Object.Provider.Ajax + 'LookupTicketByProductDate?client=' + cid + '&inventory=' + iid + '&date=' + dt;
25602	    	
25603	    	if (btn) {
25604	    		GLO.UI.Form.beginProcessing($(btn));
25605	    	}
25606	    	
25607	    	var jpop = GLO.Popup.getTopCustomPopup();
25608			if (jpop && jpop.length > 0) { GLO.Popup.close(jpop); }
25609			
25610			$.modal.close();
25611			var ojpop = GLO.Popup.Processing.open('Looking up Payment on ' + new Date(dt).toSADate(true) + '...', 'Looking up Payment');
25612	    	
25613	    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
25614	            .success(function(data, textStatus, jqXHR) {
25615	                GLO.UI.Form.resetProcessing();
25616	                ojpop.close();
25617	                
25618	                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
25619	                	GLO.Popup.Warning.open(data, 'Payment Not Found');
25620	                	return;
25621	                }
25622	                
25623	                if (!UTIL.isEmpty($(data).attr('schedule_id'))) {
25624	                	UserPortal.Edit.getOpen(data, jqXHR, UserPortal.Edit.isCalendar, true);
25625	                } else {
25626	                	UserPortal.Price.getOpen(data, jqXHR);
25627	                }
25628	            })
25629	            .error(function(jqXHR, textStatus, errorThrown) {
25630	            	GLO.UI.Form.resetProcessing();
25631	            	ojpop.close();
25632	            });
25633	    }
25634	    
25635	    _cMemberClient.openMergeMembership = function(btn) {
25636	    	var jpopMember = $('#pop-member-view').closest('.glopop');
25637		    var clientName = jpopMember.find('.client-name-link').text();
25638		    var clientId = jpopMember.find('#Client_id').val();
25639		    
25640		    var currentMembershipName = UTIL.directTagOnly(jpopMember.find('#pop-member-view-name > b'));
25641		    var currentMembershipId = jpopMember.find('#Membership_id').val();
25642	    	
25643	    	var jNextMembership = jpopMember.find('.next-membership-name');
25644	    	var nextMembershipName = jNextMembership.text();
25645	    	var nextMembershipId = jNextMembership.attr('next_membership_id');
25646	    	
25647	    	var msg = '<p style="font-weight: bold;">Merging the current membership (' + currentMembershipName + ') and the next membership (' + nextMembershipName + ') on ' 
25648	    			+ clientName + ' member profile will then include the services for both memberships in the current member profile</p>';
25649	    	
25650	    	var msgNote = '<p style="margin: 24px; margin-right: 0; font-style: italic; font-size: smaller;">This will <b>NOT</b> affect the membership profile for any other client';
25651	    	
25652	    	var divStart = '<div id="pop-confirm-merge-membership" membership_id="' + currentMembershipId + '" next_membership_id="' + nextMembershipId + '" client_id="'+ clientId + '">';
25653	    	var htm = divStart + msg + msgNote + '</div>';
25654	    	
25655	    	var h1 ='Merge the current and next membership for ' + clientName + '?';
25656	    	var jpop = GLO.Popup.Confirm.open(htm, h1, GLO.Provider.Membership.Client.saveMergeMembership);
25657	    }
25658	    _cMemberClient.saveMergeMembership = function(btn) {
25659	    	var jpopMerge = $('#pop-confirm-merge-membership');			//.closest('.glopop');
25660	    	var currentMembershipId = jpopMerge.attr('membership_id'), nextMembershipId = jpopMerge.attr('next_membership_id'), clientId = jpopMerge.attr('client_id');
25661	    	
25662	    	var uri = GLO.Link.WebsiteDomain + 'membership/MergeMembership?membershipCurrent=' + currentMembershipId + '&membershipNext=' + nextMembershipId + '&client=' + clientId;
25663	    	
25664	    	var htm = '<div id="pop-merging-membership">Merging Memberships...</div>';
25665    		var ojprocessing = GLO.Popup.Processing.open(htm, 'Updating Member Profile');
25666	    	
25667	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: {} })
25668	            .success(function(data, textStatus, jqXHR) {
25669	                ojprocessing.close();
25670	                GLO.Popup.closeIfExist(jpopMerge);
25671	                
25672	            	_reloadMemberProfile(clientId, 'with merged memberships');
25673	            })
25674	            .error(function(jqXHR, textStatus, errorThrown) { });
25675	    }
25676	    
25677	    function _getCardOnFileButton(hasCardOnFile, cid) {
25678	    	if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 60) {
25679	    		return '';
25680	    	} else if (UTIL.parseBool(hasCardOnFile)) {
25681	    		var btn = '<span id="btnViewCardOnFile" class="btnAdd"><a onclick="GLO.ClientProfile.viewCardOnFile(this)">View Card On File</a></span>';
25682	    	} else {
25683	    		var btn = '<span id="btnAddCardOnFile" class="btnAdd"><a onclick="GLO.Provider.Membership.Client.addCardOnFile(this, ' + cid + ')">Add Card On File</a></span>';
25684	    	}
25685	    	
25686	    	return '<div id="pop-member-card-file">' + btn + '</div>';
25687	    }
25688	    function _getLastPayHtm(cid, cname, iid, payCount, lastPurchaseDate) {
25689	    	var htm = '';
25690	    	
25691	    	if (UTIL.isDate(lastPurchaseDate)) {
25692	    		var dt = new Date(lastPurchaseDate);
25693	    		var fn = 'GLO.Provider.Membership.Client.openMemberPayment(' + cid + ', ' + iid + ', \'' + dt.toGloDate() + ' ' + dt.toGloTime() + '\')';
25694	    		var lbl = '<label>last payment</label>';
25695	    		var link = '<a onclick="' + fn + '" id="last-membership-pay-date">' + dt.toPrettyDate() + '</a>';
25696	    		htm += '<span id="pop-member-summary-pay-last">' + lbl + link + '</span>';
25697	    	}
25698	    	
25699	    	if (payCount > 0) {
25700	    		if (GLO.Info.roleType > 209) {
25701		    		var fn = 'GLO.Provider.Membership.Client.openMemberPayHistory(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)';
25702		    		htm += '<a onclick="' + fn + '" id="membership-payment-history">' + UTIL.pluralLabel(payCount, 'membership payment') + '</a>';
25703	    		} else {
25704		    		htm += '<span id="membership-payment-history">' + UTIL.pluralLabel(payCount, 'membership payment') + '</span>';
25705	    		}
25706	    	}
25707	    	
25708	    	if (!UTIL.isEmpty(htm)) {
25709	    		return '<div id="pop-member-last-pay">' + htm + '</div>';
25710	    	} else {
25711	    		return '';
25712	    	}
25713	    }
25714	    function _getNextPayHtm(tr, membershipId, nextMembershipId, cid, cname, payFail, balance, nextBillDate, periodEndDate, status) {
25715	    	var msgCSS = '', msg = '';
25716	    	var btnPayNow = _getPayNowButton(membershipId, nextMembershipId, nextBillDate, periodEndDate, cid, cname);
25717	    	
25718	    	if (balance < 0 && !UTIL.isEmpty(payFail)) {
25719	    		msgCSS = 'font-weight: bold; color: rgb(255,0,0);';
25720	    		msg = '<i>Payment Failed</i>';
25721	    		
25722	    		if (payFail != 'Other Error') { msg += '<small style="letter-spacing: 0; margin-left: 8px;">' + payFail + '</small>'; }
25723	    	} else {
25724	    		//var membership = GLO.ClientProfile.getMembership(membershipId);
25725	    		var member = _getMember(tr);
25726	    		
25727	    		if (member.due_mn > 0) {
25728	    			var due = UTIL.displayMoney(member.due_mn, false, false, true);
25729	    			
25730	    			if (balance < 0 && !member.is_new_member_period) {
25731	    				msg = UTIL.displayMoney(-balance, false, false, true) + ' due';
25732	    			} else if (status != 50) {
25733	    				msg = due + ' due';
25734	    			} else if (member.bill_dt > new Date()) {
25735	    				msg = due + ' due ' + member.bill_dt.toSADate(true);
25736	    			} else {
25737	    				msg = due + ' due';
25738	    			}
25739	    		} else if (member.price_mn > 0) {
25740	    			msgCSS = 'color: rgb(20,200,40);';
25741	    			
25742	    			if (!UTIL.isEmpty(tr.attr('next_membership_id'))) {
25743	    				msg = 'next charge of ' + UTIL.displayMoney(member.price_mn, false, false, true) + ' on ' + member.bill_dt.toSADate(true) + ' is paid';
25744	    			} else {
25745	    				var period = UTIL.coalesceInt(tr.attr('billing_period_cd'), member.membership.period);
25746	    				msg = 'next ' + _cMembership.getPeriodNameCount(period, parseInt(balance/member.price_mn)) + ' paid';
25747	    			}
25748	    		}
25749	    	}
25750	    	
25751	    	return '<div id="pop-member-next-pay"> <span id="next-membership-payment" style="' + msgCSS + '">' + msg + '</span>' + btnPayNow + '</div>';
25752	    }
25753	    function _getPriceAndNextHtm(price_mn, custom_price_mn, billing_period_cd, next_bill_dt, period_end_dt, status, membership) {
25754	    	var htmDefaultPrice = '', htm = '<div id="pop-member-price-row" billing_period_cd="' + UTIL.cleanString(billing_period_cd) + '">';
25755	    	
25756	    	if (UTIL.coalesce(custom_price_mn, price_mn) == 0) {
25757	    		var price = 0;
25758	    	} else {
25759	    		var price = UTIL.displayMoney(UTIL.coalesceMoney(custom_price_mn, price_mn), true, false, true);
25760	    	}
25761	    	
25762	    	if (UTIL.coalesceMoney(custom_price_mn, price_mn) != membership.price) {
25763	    		htmDefaultPrice = '<small id="membership-default-price">(normal price: ' + UTIL.displayMoney(membership.price, false, false, true) + ')</small>';
25764	    	}
25765	    	
25766	    	if (UTIL.coalesceInt(status, 30) === 50) {
25767	    		var dt0 = UTIL.coalesceDate(next_bill_dt, new Date(period_end_dt).addDays(1));
25768	    		var dt = dt0.toGloDate(), dtString = dt0.toSADate(true);
25769	    	} else {
25770	    		var dt = new Date().toGloDate(), dtString = 'now';
25771	    	}
25772	    	
25773	    	if (GLO.Info.roleType > 209) {
25774	    		var htmBillDate = '<a next_bill_dt="' + dt + '" onclick="GLO.Provider.Membership.Client.changeBillDate()">' + dtString + '</a>';
25775	    	} else {
25776	    		var htmBillDate = '<b>' + dtString + '</b>';
25777	    	}
25778	    	
25779	    	var htmBillPrice = '<input id="Period_Price_mn" type="text" value="' + price + '" onchange="GLO.Provider.Membership.Client.changeBillPrice()" onkeyup="GLO.Provider.Membership.Client.changeBillPrice()"/>';
25780	    	htm += '<span id="pop-member-price"><label for="Period_Price_mn">Price</label><b class="dollar-sign">$</b>' + htmBillPrice + htmDefaultPrice + '</span>';
25781	    	htm += '<span id="pop-member-next-bill-date"><label for="Next_Bill_dt">Next Bill <i style="">Date</i></label>' + htmBillDate + '</span>';
25782	    	
25783	    	return htm + '</div>';
25784	    }
25785	    function _getPayNowButton(membershipId, nextMembershipId, dtNextBill, dtPeriodEnd, cid, cname) {
25786	    	if (!GLO.Data.Staff.canSellProducts) {
25787	    		return '';
25788	    	}
25789	    	
25790	    	var membership = GLO.ClientProfile.getMembership(membershipId);
25791	    	
25792	    	if (!UTIL.isEmpty(nextMembershipId)) {
25793	    		if (!UTIL.isDate(dtNextBill) || new Date(dtPeriodEnd) > new Date(dtNextBill)) {
25794	    			membership = GLO.ClientProfile.getMembership(nextMembershipId);
25795	    		}
25796	    	}
25797	    	
25798	    	var cname = UTIL.removeQuotes(cname);
25799	    	var onclickPayNow = 'GLO.Provider.Membership.openPayMembershipFromPopup(' + membership.id + ', ' + membership.inventory_id + ', ' + cid + ', \"' + cname + '\")';
25800	    	
25801	    	return '<span id="btnPayMembership" class="btnAdd"><a onclick=\'' + onclickPayNow + '\'>Pay Now</a></span>';
25802	    }
25803	    function _getNextPeriodHtm(balance_mn, auto_billing_fl, next_membership_id, isViewOnly, btnPayNow) {
25804	    	var htmChecked = '', cssBalance = '';
25805	    	var htm = '<div id="pop-member-view-next">';
25806	    	
25807	    	if (true || balance_mn != 0) {
25808	    		var disabledAttribute = '', balance = UTIL.displayMoney(balance_mn, true, false, true);
25809	    		
25810	    		if (UTIL.coalesceMoney(balance_mn) < 0) {
25811	    			cssBalance = 'has-negative-balance';
25812	    		} else if (UTIL.coalesceMoney(balance_mn) > 0) {
25813	    			cssBalance = 'has-positive-balance';
25814	    		}
25815	    		
25816	    		//if (GLO.Info.roleType < 220) { disabledAttribute = ' disabled="disabled"'; }
25817	    		
25818	    		if (isViewOnly) {
25819	    			var balanceInput = '<b class="dollar-sign">$</b> <span class="view-balance-amount">' + UTIL.coalesceString(balance, '0') + '</span>';
25820	    		} else {
25821	    			var balanceInput = '<b class="dollar-sign">$</b><input id="Balance_mn" type="text" value="' + balance + '"/>';
25822	    		}
25823	    		
25824	    		htm += '<span id="pop-member-view-balance" class="' + cssBalance + '"> <label for="Balance_mn">Balance</label>' + balanceInput + '</span>';
25825	    	}
25826	    	
25827	    	if (UTIL.parseBool(auto_billing_fl)) { htmChecked = ' checked="checked"'; }
25828	    	
25829	    	var htmAutoBill = '<input type="checkbox" id="Auto_Billing_fl"' + htmChecked + '>' + '<label for="Auto_Billing_fl">Auto Billing</label>';
25830	    	
25831	    	htm += '<span id="pop-member-auto-bill">' + htmAutoBill + UTIL.cleanString(btnPayNow) + '</span>';
25832	    	htm += '</div>';
25833	    	
25834	    	if (!UTIL.isEmpty(next_membership_id)) {
25835	    		var nextMembershipName = UTIL.coalesceString(GLO.ClientProfile.getMembership(next_membership_id).name, 'different type of memberhip');
25836	    		var nextHtm = '<b class="next-membership-name" next_membership_id="' + next_membership_id + '">' + nextMembershipName + '</b>';
25837	    		var msg = '<span style="display: inline-block; padding-right:12px;">Next period the membership will change to ' + nextHtm + '</span>';
25838	    		var btnMerge = '<span id="btnMergeMembership" class="btnAdd"><a onclick="GLO.Provider.Membership.Client.openMergeMembership(this)" style="background: black;">Merge</a></span>';
25839	    		htm += '<div id="next-membership-bar" next_membership_id="' + next_membership_id + '">' + msg + btnMerge + '</div>';
25840	    	}
25841	    	
25842	    	return htm;
25843	    }
25844	    function _getCurrentPeriodHtm(end_dt, period_start_dt, period_end_dt, cid, cname) {
25845	        var fnPeriodHistory = 'GLO.Provider.Membership.Client.openMemberPeriodHistory(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)';
25846		    var btnPeriodHistory = '<span id="btnPeriodHistory" class="btnAdd"><a onclick="' + fnPeriodHistory + '"><i>Period</i> History</a></span>';
25847	        
25848	        if (GLO.Info.roleType < 170) { btnPeriodHistory = ''; }
25849	        
25850	        if (UTIL.isDate(end_dt) && new Date() > new Date(end_dt)) {
25851	        	var htmCurrentPeriod = '<div id="pop-member-view-end"><label>Membership Ended</label><b>' + end_dt + '</b>' + btnPeriodHistory + '</div>';
25852	        } else {
25853	        	var htmCurrentPeriod = '<div id="pop-member-view-current"><label>Current <i>Membership</i> Period</label>';
25854	        	var pstart = UTIL.cleanString(period_start_dt);
25855	        	
25856	        	if (GLO.Info.roleType > 199) {
25857		        	htmCurrentPeriod += '<input type="text" id="Period_Start_dt" pattern="[0-9]*" value="' + pstart + '" onclick="GLO.UI.displayDatePicker(this)" original_dt="' + pstart + '"/>';
25858		        	htmCurrentPeriod += '<b style="font-size: 20px;"> - </b> <input type="text" id="Period_End_dt" pattern="[0-9]*" value="' + UTIL.cleanString(period_end_dt) + '"/>';
25859		        	htmCurrentPeriod += '<style> .ui-datepicker { z-index: 9999 !important; } </style>';
25860		        } else {
25861		        	htmCurrentPeriod += '<b>' + period_start_dt + ' - ' + period_end_dt + '</b>';
25862		        }
25863		        
25864		        htmCurrentPeriod += btnPeriodHistory + '</div>';
25865	        }
25866	        
25867	        return htmCurrentPeriod;
25868	    }
25869	    
25870	    function _getServiceListHtm(arrService, cid, cname) {
25871	    	var maxlen = 30, htm = '<ul id="membership-service-list">', rowCss = 'odd-row';
25872	    	if (innerWidth < 800) { maxlen = 20; }
25873	    	
25874	    	for (var i=0; i < arrService.length; i++) {
25875	    		var sgid = UTIL.cleanString(arrService[i].service_group_id), svcid = UTIL.cleanString(arrService[i].service_id);
25876	    		var msid = arrService[i].membership_service_id;
25877	    		var svcName = UTIL.maxString(UTIL.coalesce(arrService[i].service_vc, arrService[i].service_group_vc, 'any service'), maxlen);
25878	    		var svcLabelCount = '', svcLabel = '<span class="membership-service-label" title="' + svcName + '">' + svcName + '</span>';
25879	    		var discountLabel = _getDiscountLabel(arrService[i].discount_mn, arrService[i].discount_pct, true);
25880	    		var limit = arrService[i].limit_nr, limitAdjust = arrService[i].limit_adjust_nr;
25881	    		var limitPeriod = UTIL.coalesceInt(limitAdjust, limit);
25882	    		var removeCustomSvc = '', isCustomService = UTIL.parseBool(arrService[i].custom_service_fl);
25883	    		
25884	    		var apptLabel = _getLimitLabel(i + 1, arrService[i].remaining_nr, limit, limitAdjust, arrService[i].appointments.length, arrService[i].price_mn);
25885	    		
25886	    		if (isCustomService) {
25887	    			var icon = '<span class="ui-icon ui-icon-circle-close"></span>';
25888	    			removeCustomSvc = '<span class="membership-service-custom-remove" onclick="GLO.Provider.Membership.Client.removeCustomService(this)">' + icon + '</span>';
25889	    			rowCss += ' is-custom-service';
25890	    		}
25891	    		
25892	    		if (limit < 900) {
25893	    			svcLabelCount = '<span class="membership-service-label-count">' + limitPeriod + '</span>';
25894	    		}
25895	    		
25896	    		if (UTIL.isNumber(limitPeriod)) {
25897	    			limitPeriod -= arrService[i].appointments.length;
25898	    		} else {
25899	    			limitPeriod = '';
25900	    		}
25901	    		
25902	    		htm += '<li class="membership-service-row ' + rowCss + '" service_group_id="' + sgid + '" service_id="' + svcid + '" original_limit_nr="' + limitPeriod
25903	    				+ '" membership_service_id="' + msid + '">' + removeCustomSvc + svcLabelCount + svcLabel + discountLabel + apptLabel + '</li>';
25904	    		
25905	    		htm += _getApptListHtm(arrService[i].appointments, cid, rowCss);
25906	    		
25907	    		if (rowCss === 'odd-row') { rowCss ='even-row'; } else { rowCss ='odd-row'; }
25908        	}
25909        	
25910        	htm += '</ul>';
25911        	
25912        	if (GLO.Info.roleType > 219) {
25913        		var fnOpenAddCustomService = 'GLO.Provider.Membership.Client.openAddCustomService(' + cid + ', \'' + UTIL.replaceQuotesTitle(cname) + '\', this)';
25914        		htm += '<div id="member-service-add-custom"> <span id="btnAddCustomService" class="btnAdd btnAction2"><a onclick="' + fnOpenAddCustomService + '">Add Custom Service</a></span> </div>';
25915        	}
25916        	
25917        	return '<div id="">' + htm + '</div>';
25918	    }
25919	    
25920	    function _getApptListHtm(arrAppt, cid, rowCss) {
25921	    	var htm = '';
25922	    	
25923	    	for (var a=0; a < arrAppt.length; a++) {
25924	    		var scheduleId = arrAppt[a].schedule_id, smid = arrAppt[a].schedule_multi_id, svcid = arrAppt[a].service_id, sid = arrAppt[a].staff_id, apptStatus = arrAppt[a].appt_status_cd;
25925				var onclick = 'GLO.Provider.Membership.Client.openAppt(' + smid + ')';
25926				var dtAppt = new Date(arrAppt[a].start_dt);
25927				
25928				if (GLO.Info.isFirefox) {
25929					dtAppt = new Date(arrAppt[a].start_dt.replace(' am', ':00').replace(' pm', ':00'));
25930					
25931					if (arrAppt[a].start_dt.indexOf('pm') !== -1) {
25932						dtAppt = new Date(dtAppt.setHours(dtAppt.getHours() + 12));
25933					}
25934				}
25935				
25936				var lbl = '<a onclick="' + onclick + '">' + dtAppt.toPrettyDate() + '</a>';
25937	    		htm += '<li class="membership-appt-row ' + rowCss + '" schedule_id="' + scheduleId + '" schedule_multi_id="' + smid + '" service_id="' + svcid + '" staff_id="' + sid + '">' + lbl + '</li>';
25938	    	}
25939	    	
25940	    	return htm;
25941	    }
25942	    
25943	    function _getServiceTotalPrice(rowNumber, price) {
25944	    	var htm = '<span class="adjust-total-service-price">'
25945	    				+ '<label for="Service_Commission_Price_mn' + rowNumber + '">Comm. Price</label>'
25946	    				+ '<b class="dollar-sign">$</b>'
25947	    				+ '<input type="text" id="Service_Commission_Price_mn' + rowNumber + '" class="cost" value="' + UTIL.displayMoney(price, true, false, true) + '"/>'
25948	    				+ '<b class="help-icon4" onclick="GLO.Provider.Membership.openServicePriceHelp(this)">?</b>'
25949    				+ '</span>';
25950		    return htm;
25951	    }
25952	    function _getLimitLabel(rowNumber, remaining, limit, limitAdjust, apptCount, price) {
25953	    	var htm = '<span class="membership-remaining-label">';
25954    		
25955    		if (limit < 500) {
25956    			var fns = ' onchange="GLO.Provider.Membership.Client.adjustChange(this, event)" onkeyup="UI.verifyNumberInput(this, true)"';
25957    			htm += '<input type="number" id="Remaining_nr' + rowNumber + '" class="remaining" value="' + remaining + '" min="-500" max="500"' + fns + '/>';
25958    			htm += '<label for="Remaining_nr' + rowNumber + '" class="remaining-label">' + UTIL.makePlural('service', remaining) + ' remaining</label>';
25959    			
25960    			htm += _getServiceTotalPrice(rowNumber, price);
25961    			
25962    			htm += '<span class="each-period">'
25963	    				+ '<label for="Limit_nr' + rowNumber + '">Each Period</label>'
25964	    				+ '<input type="number" id="Limit_nr' + rowNumber + '" class="limit" value="' + limit + '" min="-500" max="500" onkeyup="UI.verifyNumberInput(this, true)"/>'
25965    				+ '</span>';
25966    		} else {
25967    			htm += '<small>Unlimited</small>';
25968    		}
25969    		
25970    		return htm + '</span>';
25971	    }
25972	    
25973	    function _getDiscountLabel(discountMoney, discountPercent, isHtm) {
25974	    	if (discountMoney > 0) {
25975	    		var lbl = UTIL.displayMoney(discountMoney) + ' off';
25976	    	} else if (discountPercent) {
25977	    		var lbl = discountPercent + '% off';
25978	    	} else {
25979	    		var lbl = 'Free';
25980	    	}
25981	    	
25982	    	return '<i class="membership-discount-label">' + lbl + '</i>';
25983	    }
25984	    
25985	    function _getHiddenHtm(membership_id, cid) {
25986	    	var htm = '<input type="hidden" id="Membership_id" value="' + membership_id + '"/>';
25987			htm += '<input type="hidden" id="Client_id" value="' + cid + '"/>';
25988			return htm;
25989	    }
25990	    
25991	    function _openAddMember(jclient, cid, cname) {
25992	    	var btnCardOnFile = UTIL.cleanString(jclient.find('#client-card-on-file').find('#btnViewCardOnFile, #btnAddCardOnFile').outerHTML());
25993	    	
25994	    	if (!UTIL.isEmpty(btnCardOnFile)) { btnCardOnFile = '<div id="pop-member-card-btn" style="padding-bottom: 16px;">' + btnCardOnFile + '</div>'; }
25995	    	
25996	    	var dd = _cMembership.getMembershipDropDown();
25997	    	var htm = '<div id="pop-member-add">' + btnCardOnFile
25998		    			+ '<div id="pop-member-add-name">'
25999		    				+ '<input type="hidden" id="Client_id" value="' + cid + '"/>'
26000		    				+ '<input type="hidden" id="Client_Name_vc" value="' + cname + '"/>'
26001		    				+ '<label for="Membership_id">Membership</label>' + dd
26002		    			+ '</div>'
26003		    			+ '<div id="pop-member-add-start">'
26004							+ '<label for="Member_Start_dt">Start Date</label>'
26005							+ '<input type="text" id="Member_Start_dt" pattern="[0-9]*"/> <style> .ui-datepicker { z-index: 9999 !important; } </style>'
26006						+ '</div>'
26007		    		+ '</div>';
26008	    	var h1 = 'Add Member';
26009	    	
26010	    	if (!UTIL.isEmpty(cname)) { h1 += ': ' + cname; }
26011	    	
26012	    	var jpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Provider.Membership.Client.saveCreateMember);
26013	    	var jbtns = jpop.find('.pop-buttons');
26014	    	jbtns.append('<span class="btnAdd"><a onclick="GLO.Provider.Membership.Client.openBuyMembership()">Pay Now</a></span>');
26015	    	
26016	    	jpop.find('#Member_Start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, minDate: "-9M", maxDate: "+6M" });
26017	    }
26018	    _cMemberClient.openBuyMembership = function() {
26019	    	var jpop = $('#pop-member-add').closest('.glopop');
26020	    	var mid = jpop.find('#Membership_id').val(), start = jpop.find('#Member_Start_dt').val();
26021	    	var cid = jpop.find('#Client_id').val(), cname = jpop.find('#Client_Name_vc').val();
26022	    	
26023	    	if (UTIL.isEmpty(mid)) {
26024	    		GLO.Popup.Warning.open('Please Select Membership', 'Membership Required');
26025	    		return;
26026	    	}
26027	    	
26028	    	GLO.Popup.close(jpop);
26029	    	GLO.Popup.Processing.open('<div id="pop-procesing-price-wait">Creating Membership Purchase Ticket...</div>', 'Creating Ticket');
26030	    	
26031			setTimeout(function() {							//= make async so UI closes popup (see above code) immediately
26032	    		GLO.Provider.Membership.openPayMembership2(mid, null, cid, cname, null, start);
26033	    	}, 90);
26034	    }
26035	    
26036	    function _getMonthByPeriod(periodCode) {
26037	    	if (periodCode == 30) {
26038	    		return 1;
26039	    	} else if (periodCode == 40) {
26040	    		return 2;
26041	    	} else if (periodCode == 50) {
26042	    		return 3;
26043	    	} else if (periodCode == 60) {
26044	    		return 6;
26045	    	} else if (periodCode == 70) {
26046	    		return 12;
26047	    	}
26048	    }
26049	    
26050	    function _allowChangeMemberBillingPeriod(memberPeriod, billPeriod) {
26051	    	if (memberPeriod == 20 && $('#pop-warn-weekly-membership-period').closest('.glopop').length === 0) {
26052	    		if (!UTIL.isEmpty(billPeriod)) {
26053		    		var msg1 = 'Cannot change billing period on weekly membership';
26054		    		var msg2 = 'When membership period is weekly, then billing period is always weekly';
26055		    		var htm = '<div id="pop-warn-weekly-membership-period"><div>' + msg1 + '</div><div style="letter-spacing: 0; font-size: smaller;">' + msg2 + '</div></div>';
26056		    		
26057		    		GLO.Popup.Warning.open(htm, 'Weekly Membership');
26058		    		return false;
26059		    	} else {
26060		    		$('#pop-member-change-bill-period').addClass('hide');
26061		    	}
26062	    	}
26063	    	
26064	    	return true;
26065	    }
26066	    
26067	    _cMemberClient.setPricePerPeriod = function() {
26068	    	var jpop = $('#pop-member-view').closest('.glopop');
26069	    	var periodPrice = _cMemberClient.getPricePerPeriod(jpop);
26070	    	
26071	    	var membershipId = jpop.find('#Membership_id').val();
26072	    	var membership = GLO.ClientProfile.getMembership(membershipId);
26073	    	var memberMonthCount = _cMembership.getPeriodMonthCount(membership.period);
26074	    	
26075	    	var billPeriod = jpop.find('#Billing_Period_cd').find('option:selected').attr('value');						//jpop.find('#Billing_Period_cd').val();
26076	    	var billMonthCount = _cMembership.getPeriodMonthCount(billPeriod);
26077	    	
26078	    	var memberPrice = UTIL.coalesceMoney(jpop.find('#Period_Price_mn').val(), membership.price);
26079	    	
26080	    	if (!_allowChangeMemberBillingPeriod(membership.period, billPeriod)) { return; }
26081	    	
26082	    	if (memberMonthCount == 0 || billMonthCount == 0 || memberPrice == 0 || billMonthCount >= memberMonthCount) {
26083	    		jpop.find('#pop-member-billing-period-price').addClass('hide').find('#Bill_Period_mn').text('');
26084	    	} else {
26085	    		var billPrice = UTIL.displayMoney(memberPrice * billMonthCount/memberMonthCount, true, false, true);
26086	    		jpop.find('#pop-member-billing-period-price').removeClass('hide').find('#Bill_Period_mn').text(billPrice);
26087	    	}
26088	    }
26089	    
26090	    _cMemberClient.getPricePerPeriod = function(jpop) {
26091	    	var membershipPrice = UTIL.coalesceMoney(jpop.find('#pop-member-price').find('input').val());
26092	    	var billPeriod = jpop.find('#Billing_Period_cd').val();
26093	    	var dtNext = jpop.find('#Next_Bill_dt').val(), dtEnd = jpop.find('#Period_End_dt').val();
26094	    	var mid = jpop.find('#Membership_id').val();
26095	    	
26096	    	return _cMemberClient.getPricePerPeriod2(mid, membershipPrice, billPeriod, dtNext, dtEnd);
26097	    }
26098	    
26099	    _cMemberClient.getPricePerPeriod2 = function(mid, membershipPrice, billPeriod, dtNext, dtEnd) {
26100	    	if (UTIL.isEmpty(mid) || UTIL.isEmpty(billPeriod) || !UTIL.isDate(dtNext) || !UTIL.isDate(dtEnd)) {
26101	    		var periodPrice = membershipPrice;
26102	    	} else {
26103	    		//var membershipPeriod = GLO.ClientProfile.getMembership(mid).period;
26104	    		//var membershipMonths = _getMonthByPeriod(membershipPeriod), billMonths = _getMonthByPeriod(billPeriod);
26105	    		var payPeriods = _getPayPeriods(billPeriod, dtNext, dtEnd);
26106	    		
26107	    		if (payPeriods > 0) {
26108	    			var periodPrice = membershipPrice / payPeriods;
26109	    		} else {
26110	    			var periodPrice = 0;
26111	    		}
26112	    	}
26113	    	
26114	    	return UTIL.displayMoney(periodPrice, false, false, true);
26115	    }
26116	    
26117	    function _getPayPeriods(billPeriod, dtNext, dtEnd) {
26118	    	dtNext = new Date(dtNext);
26119	    	dtEnd = new Date(dtEnd);
26120	    	
26121	    	var monthsInPeriod = _getMonthByPeriod(billPeriod);
26122	    	var monthDiff = dtNext.getMonthDiff(dtEnd);
26123	    	
26124	    	return Math.round(monthDiff/monthsInPeriod);
26125	    }
26126	    
26127	    _cMemberClient.changeBillDateToDefault = function() {
26128	    	var jpop = $('#pop-member-view').closest('.glopop');
26129	    	var dt = new Date(jpop.find('#Period_End_dt').val()).addDays(1).toGloDate();
26130	    	
26131	    	var jnext = jpop.find('#Next_Bill_dt');
26132	    	UI.highlight(jnext, 100, 6400, true);
26133	    	
26134	    	setTimeout(function() {
26135	    		jnext.val(dt).change();
26136	    		jpop.find('#hello-bar-change-next-bill').remove();
26137	    	}, 2400);
26138	    }
26139	    _cMemberClient.changeBillDate = function() {
26140	    	var jpop = $('#pop-member-view').closest('.glopop');
26141	    	var jdt = jpop.find('#pop-member-next-bill-date').find('a');
26142	    	var htmDateInput = '<input id="Next_Bill_dt" type="text" pattern="[0-9]*" value="' + jdt.attr('next_bill_dt') + '"/>';
26143	    	
26144	    	//var htmDate = '<span id="pop-member-next-bill-date"> <label for="Next_Bill_dt">Next Bill Date</label>' + htmDateInput + '</span>';
26145	    	var htmDollarSign = '<b class="dollar-sign">$</b>';
26146	    	var htmPeriodPrice = '<span id="pop-member-billing-period-price" title="Billing Period Price"> <label for="Bill_Period_mn">Bill Period</label> ' + htmDollarSign + '<b id="Bill_Period_mn"></b> </span>';
26147	    	var htmPeriodLength = '<span id="pop-member-period-length">
26147 <label for="Billing_Period_cd">Billing Period</label>' + _getPeriodDropDown('Billing_Period_cd') + '</span>';
26148	    	var htm = '<div id="pop-member-change-bill-period">' + htmPeriodPrice + htmPeriodLength + '</div>';
26149	    	
26150	    	jpop.find('#pop-member-change-bill-period').remove();
26151	    	jpop.find('#pop-member-price-row').before(htm);
26152	    	jpop.find('#Billing_Period_cd').change(GLO.Provider.Membership.Client.changeBillingPeriod);
26153	    	
26154	    	jdt.replaceWith(htmDateInput);
26155	    	jpop.find('#Next_Bill_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
26156	    	jpop.find('#Next_Bill_dt').change(GLO.Provider.Membership.Client.changeNextBillDate);
26157	    	_cMemberClient.setPricePerPeriod();
26158	    }
26159	    
26160	    _cMemberClient.changeMembership = function() {
26161	    	_cMemberClient.setPricePerPeriod();
26162	    }
26163	    _cMemberClient.changeNextBillDate = function() {
26164	    	//var jpop = $('#pop-member-view').closest('.glopop');
26165	    	_cMemberClient.setPricePerPeriod();
26166	    }
26167	    _cMemberClient.changeBillPrice = function() {
26168	    	_cMemberClient.setPricePerPeriod();
26169	    }
26170	    _cMemberClient.changeBillingPeriod = function() {
26171	    	_cMemberClient.setPricePerPeriod();
26172	    	return;
26173	    	/*
26174	    	var jpop = $('#pop-member-view').closest('.glopop');
26175	    	var bp = jpop.find('#Billing_Period_cd').val();
26176	    	var dt = jpop.find('#Period_Start_dt').val();
26177	    	var dt2 = new Date(jpop.find('#Period_End_dt').val());
26178	    	
26179	    	if (!UTIL.isDate(dt)) { return ''; }
26180	    	
26181	    	dt = new Date(dt);
26182	    	var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
26183	    	
26184	    	if (UTIL.isEmpty(bp)) {
26185	    		var dtNext = dt2;
26186	    	} else if (bp == 20) {			//weekly
26187	    		var dtTemp = new Date(dt.setMonth(dt.getMonth()+1));
26188	    		var halfAMonth = Math.round((dtTemp.getTime() - dt.getTime())/oneDay/2);
26189	    		var dtNext = new Date(dt.addDays(halfAMonth));
26190	    	} else if (bp == 30) {			//monthly
26191	    		var dtNext = new Date(dt.setMonth(dt.getMonth() + 1));
26192	    	} else if (bp == 40) {			//bi-monthly
26193	    		var dtNext = new Date(dt.setMonth(dt.getMonth() + 2));
26194	    	} else if (bp == 50) {			//quarterly
26195	    		var dtNext = new Date(dt.setMonth(dt.getMonth() + 3));
26196	    	} else if (bp == 60) {			//semi-annual
26197	    		var dtNext = new Date(dt.setMonth(dt.getMonth() + 6));
26198	    	} else if (bp == 70) {			//annual
26199	    		var dtNext = new Date(dt.setFullYear(dt.getFullYear() + 1));
26200	    	}
26201	    	
26202	    	if (dt2 > new Date() && dtNext > new Date()) {
26203	    		jpop.find('#Next_Bill_dt').val(dtNext.toGloDate());
26204	    	} else {
26205	    		jpop.find('#Next_Bill_dt').focus();
26206	    	}
26207	    	
26208	    	_cMemberClient.setPricePerPeriod();
26209	    	*/
26210	    }
26211	    
26212	    _cMemberClient.displayChangeMembership = function() {
26213	    	var jpop = $('#pop-member-view').closest('.glopop');
26214	    	var membershipId = jpop.find('#Membership_id').attr('id', 'Orig_Membership_id').val();
26215	    	
26216	    	var jname = jpop.find('#pop-member-view-name');
26217	    	var dd = _cMembership.getMembershipDropDown();
26218	    	jname.html(dd);
26219	    	jpop.find('#Membership_id').val(membershipId).change(GLO.Provider.Membership.Client.setPricePerPeriod).find('option[value=""]').remove();
26220	    }
26221	    
26222	    _cMemberClient.removeCustomService = function(icon) {
26223	    	var jpop = $('#pop-member-view').closest('.glopop');
26224	    	var membershipName = UTIL.coalesceString(jpop.find('#pop-member-view-name > b').text(), jpop.find('#pop-member-view-name #Membership_id option:selected').text());
26225	    	var clientName = jpop.find('.client-name-link').text();
26226	    	
26227	    	var msg1 = '<p>This service is not normally on this ' + membershipName + ' memberships</p>';
26228	    	var msg2 = '<p>Would you like to remove this service from ' + clientName + ' membership?</p>';
26229	    	var msg3 = '<p> </p>';
26230	    	var htm = '<div id="pop-confirm-member-service-remove">' + msg1 + msg2 + msg3 + '</div>';
26231	    	
26232	    	var msid = $(icon).closest('li').attr('membership_service_id');
26233	    	
26234	    	var fn = function() {
26235	    		GLO.Provider.Membership.Client.removeCustomServiceConfirmed(msid);
26236	    	}
26237	    	
26238	    	GLO.Popup.Confirm.open(htm, 'Remove Custom Member Service?', fn);
26239	    	
26240	    }
26241	    _cMemberClient.removeCustomServiceConfirmed = function(msid) {
26242	    	var jpop = $('#pop-member-view');
26243	    	var cid = jpop.find('#Client_id').val();
26244	    	var uri = GLO.Link.WebsiteDomain + 'membership/RemoveCustomService?cid=' + cid + '&msid=' + msid;
26245			
26246	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false })
26247	            .success(function(data, textStatus, jqXHR) {
26248	            	var jd = $(data);
26249	            	
26250	            	if (jd.hasClass('warning')) {
26251	            		GLO.Popup.Warning.open(data, 'Problem Remove Service');
26252	            	} else {
26253	            		jpop.find('li.membership-service-row.is-custom-service[membership_service_id="' + msid + '"]').remove();
26254	            		GLO.Popup.Success.open('Custom Service Removed', 'Change Successful');
26255	            	}
26256	            })
26257	            .error(function(jqXHR, textStatus, errorThrown) { });
26258	    }
26259	    
26260	    _cMemberClient.adjustChange = function(input, event) {
26261	    	var li = $(input).closest('li.membership-service-row');
26262	    	var jtotal = li.find('.membership-service-label-count');
26263    		var remaining = UTIL.coalesceInt(input.value, 0);					//var limit = UTIL.coalesceInt(li.attr('original_limit_nr'));
26264    		var apptCount = _getMemberServiceApptCount(li);
26265    		
26266    		jtotal.text(remaining + apptCount);
26267	    }
26268	    
26269	    function _getMemberServiceApptCount(li) {
26270	    	var apptCount = 0;
26271	    	
26272	    	while (li.next().hasClass('membership-appt-row')) {
26273    			li = li.next();
26274    			++apptCount;
26275    		}
26276    		
26277    		return apptCount;
26278	    }
26279	    
26280	    _cMemberClient.openAppt = function(smid) {
26281	    	GLO.Popup.close();
26282	    	UserPortal.Edit.get(null, smid, true, UserPortal.Edit.isCalendar, false);
26283	    }
26284	    
26285	    function _getUpdateMember(jpop, isVerify, isNextPeriod) {
26286    		var jPeriodStart = jpop.find('#Period_Start_dt');
26287    		var periodStart = UTIL.cleanString(jPeriodStart.val());
26288			var periodEnd = UTIL.cleanString(jpop.find('#Period_End_dt').val());
26289			
26290			if (UTIL.isDate(periodEnd)) { periodEnd = new Date(periodEnd).addDays(1).toGloDate(); }
26291			
26292			var start = new Date(jpop.find('#pop-member-view-start').attr('start_dt')).toGloDate();
26293    		
26294    		if (new Date(jPeriodStart.attr('original_dt')).toGloDate() == start) {					//= if start is same as current-period-start, changing period start also changes start date
26295    			start = periodStart;
26296    		}
26297    		
26298    		var membershipId = jpop.find('#Membership_id').val();
26299    		var autoBill = jpop.find('#Auto_Billing_fl').prop('checked');
26300    		var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val());
26301    		var jsonPost = { "membership": membershipId, "autobill": autoBill, "start": start, "periodstart": periodStart, "periodend": periodEnd, "balance": balance };
26302    		var origMembershipId = jpop.find('#Orig_Membership_id').val();
26303    		var jBillPeriod = jpop.find('#Billing_Period_cd');
26304    		
26305    		if (jBillPeriod.length > 0) {
26306    			var billPeriod = jBillPeriod.val();
26307    		} else {
26308    			var billPeriod = jpop.find('#pop-member-price-row').attr('billing_period_cd');
26309    		}
26310    		
26311    		var priceCustom = jpop.find('#pop-member-price').find('input').val();
26312    		var priceDefault = UTIL.coalesceMoney(GLO.ClientProfile.getMembership(membershipId).price);
26313    		var dtNextBill = jpop.find('#Next_Bill_dt').val();
26314    		var mstatus = jpop.find('#Member_Status_cd').val();
26315    		
26316    		if (UTIL.isDate(dtNextBill) && dtNextBill != periodEnd) { jsonPost.billdate = dtNextBill; }
26317    		if (!UTIL.isEmpty(priceCustom) && UTIL.coalesceMoney(priceCustom) != priceDefault) { jsonPost.price = UTIL.coalesceMoney(priceCustom); }
26318    		if (!UTIL.isEmpty(billPeriod)) { jsonPost.billperiod = billPeriod; }
26319    		if (!UTIL.isEmpty(mstatus)) { jsonPost.status = mstatus; }
26320    		
26321    		if (!UTIL.isEmpty(origMembershipId) && membershipId != origMembershipId) {
26322    			if (!isVerify || isNextPeriod) {
26323    				jsonPost.nextmembership = membershipId;
26324    				jsonPost.membership = origMembershipId;
26325    			}
26326    		} else if (jpop.find('select#Membership_id').length === 0) {			//= not changing membership so keep next-membership (if exists)
26327    			var nextMembershipId = jpop.find('#next-membership-bar').attr('next_membership_id');
26328    			
26329    			if (!UTIL.isEmpty(nextMembershipId)) {
26330    				jsonPost.nextmembership = nextMembershipId;
26331    			}
26332    		}
26333    		
26334    		return jsonPost;
26335	    }
26336	    
26337	    function _askInactiveOnMembershipChange(jpop, jsonPost) {
26338	    	if (jpop.find('.member-status-bubble').attr('member_status_cd') != 900) { return; }
26339	    	
26340	    	var msg1 = '<p>This member is In-Active</p>';
26341	    	var msg2 = '<p>Do you want to Activate this membership?</p>';
26342	    	var htm = '<div id="pop-confirm-keep-inactive">' + msg1 + msg2 + '</div>';
26343	    	
26344	    	var fnSave = function() { GLO.Provider.Membership.Client.save(true); }
26345	    	var fnActivate = function() {
26346	    		var jpop = $('#pop-member-view');
26347	    		jpop.find('.member-status-bubble').click();
26348	    		jpop.find('#Member_Status_cd').val(50);
26349	    		GLO.Provider.Membership.Client.save(true);
26350	    	}
26351	    	
26352	    	var jpop = GLO.Popup.Confirm.open(htm, 'Member Currently In-Active', fnActivate, fnSave).getPopup();
26353	    	var btnCancel = '<span class="btnCancel" onclick="GLO.Popup.close()" style="float: none; margin: 0; margin-left: -40px; padding: 0 12px;"><a>Close</a></span>';
26354	    	jpop.find('.pop-buttons').css({ "width": "100%", "max-width": "480px" });
26355	    	
26356	    	jpop.find('.btnNo').removeClass('btnNo').addClass('btnSave').find('>a').text('Keep In-Active').css({ "position": "absolute", "left": "8px" });
26357	    	jpop.find('.btnYes').before(btnCancel);
26358	    	jpop.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('>a').text('Make Active').css({ "position": "absolute", "right": "8px" });
26359	    	
26360	    	return true;
26361	    }
26362	    function _requireVerifyMembershipChange(jpop, jsonPost) {
26363	    	if (UTIL.isEmpty(jsonPost.nextmembership)) { return false; }
26364	    	
26365	    	var nm = jpop.find('#Membership_id').find('option[value="' + jsonPost.nextmembership + '"]').text();
26366	    	var msg = 'When do you want to change the membership to: ' + nm + '?';
26367	    	var lblChange = 'Change ';
26368	    	
26369	    	if (innerWidth < 400) { lblChange = ''; }
26370	    	
26371	    	var fnNow = function() { GLO.Provider.Membership.Client.save(true); }
26372	    	var fnNext = function() { GLO.Provider.Membership.Client.save(true, true); }
26373	    	
26374	    	var jpop = GLO.Popup.Confirm.open(msg, 'Confirm Membership Change', fnNext, fnNow).getPopup();
26375	    	var btnCancel = '<span class="btnCancel" onclick="GLO.Popup.close()" style="float: none; margin: 0; margin-left: -40px; padding: 0 12px;"><a>Cancel</a></span>';
26376	    	jpop.find('.pop-buttons').css({ "width": "100%", "max-width": "480px" });
26377	    	
26378	    	jpop.find('.btnNo').removeClass('btnNo').addClass('btnSave').find('>a').text(lblChange + 'Now').css({ "position": "absolute", "left"
26378: "8px" });
26379	    	jpop.find('.btnYes').before(btnCancel);
26380	    	jpop.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('>a').text(lblChange + 'Next Period').css({ "position": "absolute", "right": "8px" });
26381	    	
26382	    	return true;
26383	    }
26384	    
26385	    _cMemberClient.saveAutoBill = function() {
26386	    	var jpop = $('#pop-member-pay-summary').closest('.glopop');
26387	    	var mcid = jpop.find('#Membership_Client_id').val();
26388	    	var autoBill = jpop.find('#Auto_Billing_fl').prop('checked');
26389			
26390			var tr = $('#membership-report').find('tr[membership_client_id="' + mcid + '"]');
26391			var hasCardOnFile = tr.attr('card_on_file_fl');
26392			var tdAutoBill = tr.find('.membership-column-auto-bill');
26393			
26394			var uri = GLO.Link.WebsiteDomain + 'membership/AutoBilling?mcid=' + mcid + '&autobill=' + autoBill;
26395			
26396	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false })
26397	            .success(function(data, textStatus, jqXHR) {
26398	            	if (autoBill) {
26399	            		tdAutoBill.html('<i class="is-auto-bill" title="Auto-Billing enabled">&#10004;</i>');
26400	            	} else if (hasCardOnFile || UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 59) {
26401	            		tdAutoBill.html('<b>+</b>');
26402	            	} else {
26403	            		tdAutoBill.html('<b>-</b>');
26404	            	}
26405	            })
26406	            .error(function(jqXHR, textStatus, errorThrown) { });
26407	    }
26408	    _cMemberClient.saveCreateMember = function() {
26409	    	var jpop = $('#pop-member-add').closest('.glopop');
26410	    	var cid = jpop.find('#Client_id').val(), mid = jpop.find('#Membership_id').val(), start = jpop.find('#Member_Start_dt').val();
26411			var uri = GLO.Link.WebsiteDomain + 'membership/CreateMember?client=' + cid + '&membership=' + mid + '&start=' + start;
26412			var jbtn = jpop.find('.btnSave');
26413			
26414			GLO.UI.Form.beginProcessing(jbtn);
26415			
26416	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false })
26417	            .success(function(data, textStatus, jqXHR) {
26418	                GLO.Popup.close(jpop);
26419	                var jclient = $('form#client-form');
26420	                
26421	                if (jclient.find('#Client_id').val() === cid) {
26422		                jclient.find('#Membership_id').val(mid);
26423		                
26424		                GLO.ClientProfile.initMembershipButton(jclient, mid);
26425		                GLO.Provider.Membership.refreshReportOnEdit();
26426	                }
26427	            })
26428	            .error(function(jqXHR, textStatus, errorThrown) {
26429	                GLO.UI.Form.resetProcessing();
26430	            });
26431	    }
26432	    _cMemberClient.save = function(isVerify, isNextPeriod) {
26433	    	var jpop = $('#pop-member-add').closest('.glopop');
26434	    	
26435			if (jpop.length === 0) {
26436	    		jpop = $('#pop-member-view').closest('.glopop');
26437	    		
26438	    		var jsonPost = _getUpdateMember(jpop, isVerify, isNextPeriod);
26439	    		var membershipId = jsonPost.membership;
26440	    		
26441	    		if (!isVerify) {
26442	    			if (_requireVerifyMembershipChange(jpop, jsonPost)) { return; }
26443	    			if (_askInactiveOnMembershipChange(jpop, jsonPost)) { return; }
26444	    		}
26445	    	} else {
26446	    		var membershipId = jpop.find('#Membership_id').val();
26447	    		var start = UTIL.cleanString(jpop.find('#Member_Start_dt').val());
26448	    		var balance = UTIL.coalesceMoney(jpop.find('#Balance_mn').val());
26449	    		var jsonPost = { "membership": membershipId, "periodstart": start, "balance": balance };
26450	    	}
26451	    	
26452	    	var svcXml = '', jsvc = $('#membership-service-list').find('li.membership-service-row');
26453	    	
26454	    	for (var i=0; i < jsvc.length; i++) {
26455	    		var li = jsvc.eq(i);
26456	    		var msid = UTIL.cleanString(li.attr('membership_service_id'));
26457	    		
26458	    		if (li.find('.remaining').length) {						//= NOT unlimited
26459		    		var cost = li.find('.adjust-total-service-price .cost').val();
26460	    			var more = '', remaining = li.find('.remaining').val();
26461		    		var limitThisPeriod = UTIL.coalesceInt(li.find('.membership-service-label-count').text());
26462		    		var limitEachPeriod = li.find('.limit').val();
26463		    		
26464	    			var apptCount = _getMemberServiceApptCount(li);
26465	    			var defaultLimit = GLO.ClientProfile.getMembershipService(msid).limit_nr;
26466	    			
26467	    			if (UTIL.isEmpty(cost)) {
26468	    				cost = '';
26469	    			} else {
26470	    				cost = UTIL.coalesceMoney(cost);
26471	    			}
26472	    			
26473	    			if (UTIL.isEmpty(limitEachPeriod) || limitEachPeriod == defaultLimit) {			//= if different then default or limit is empty (setting field to empy = reset to default)
26474	    				limitEachPeriod = '';
26475	    			}
26476	    			
26477	    			if (UTIL.isEmpty(remaining) || limitThisPeriod == UTIL.coalesceInt(limitEachPeriod, defaultLimit)) {
26478	    				limitThisPeriod = '';
26479	    			} else if (remaining == 0 && remaining != UTIL.coalesceInt(limitEachPeriod, defaultLimit, 0) - UTIL.coalesceInt(apptCount, 0)) {
26480	    				more = ' adjust_to_zero_fl="1"';
26481	    			}
26482	    			
26483	    			if (cost > 0 || limitThisPeriod !== '' || limitEachPeriod !== '' || defaultLimit != li.attr('original_limit_nr')) {
26484	    				svcXml += '<li membership_service_id="' + msid + '" limit_adjust_nr="' + limitThisPeriod + '" limit_nr="' + limitEachPeriod + '" price_mn="' + cost + '"' + more + '/>';
26485	    			}
26486	    		}
26487	    	}
26488	    	
26489	    	if (!UTIL.isEmpty(svcXml)) {
26490	    		jsonPost.services = UTIL.htmlEncode('<ul>' + svcXml + '</ul>');
26491	    	}
26492	    	
26493	    	var cid = jpop.find('#Client_id').val();
26494			var uri = GLO.Link.WebsiteDomain + 'membership/EditClient?cid=' + cid;
26495			var jbtn = jpop.find('.btnSave');
26496			
26497			GLO.UI.Form.beginProcessing(jbtn);
26498			
26499	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonPost })
26500	            .success(function(data, textStatus, jqXHR) {
26501	                GLO.Popup.close(jpop);
26502	                var jclient = $('form#client-form');
26503	                jclient.find('#Membership_id').val(membershipId);
26504	                
26505	                GLO.ClientProfile.initMembershipButton(jclient, membershipId);
26506	                GLO.Provider.Membership.refreshReportOnEdit();
26507	            })
26508	            .error(function(jqXHR, textStatus, errorThrown) {
26509	                GLO.UI.Form.resetProcessing();
26510	            });
26511	    }
26512	    
26513	    _cMemberClient.remove = function() {
26514	    	//var jclient = $('#clientProfileGrid');
26515	    	//var cname = UTIL.coalesce(jclient.find('#Full_Name_vc').val(), jclient.find('#First_Name_vc').val() + ' ' + jclient.find('#Last_Name_vc').val());
26516	    	
26517	    	var jpop = $('#pop-member-view').closest('.glopop');
26518			var cname = UTIL.directTagOnly(jpop.find('h1 a.client-name-link'));
26519			var cid = jpop.find('#Client_id').val();
26520	    	
26521	    	var htm = '<div id="pop-confirm-cancel-member">' + 'Are you sure you want to cancel the membership for ' + cname + '?</div>';
26522	    	
26523	    	GLO.Popup.Warning.open(htm, 'Confirm Cancel Membership', GLO.Provider.Membership.Client.removeConfirmed);
26524	    }
26525	    
26526	    _cMemberClient.removeConfirmed = function() {
26527	    	var jpop = $('#pop-member-view').closest('.glopop');
26528			var membershipId = jpop.find('#Membership_id').val(), cid = jpop.find('#Client_id').val();
26529			var uri = GLO.Link.WebsiteDomain + 'membership/DeleteClient?membership=' + membershipId + '&cid=' + cid;
26530			
26531			jpop = jpop;
26532			var jbtn = jpop.find('.btnDelete');
26533			
26534			GLO.UI.Form.beginProcessing(jbtn);
26535			
26536	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: {} })
26537	            .success(function(data, textStatus, jqXHR) {
26538	                GLO.Popup.close(jpop);
26539	                var jclient = $('form#client-form');
26540	                jclient.find('#Membership_id').val('');
26541	                GLO.ClientProfile.initMembershipButton(jclient);
26542	                
26543	                GLO.Provider.Membership.refreshReportOnEdit();
26544	            })
26545	            .error(function(jqXHR, textStatus, errorThrown) {
26546	                GLO.UI.Form.resetProcessing();
26547	            });
26548	    }
26549	    
26550	    return _cMemberClient;
26551	})();
26552    
26553    _cMembership.Help = (function() {
26554	    function _cMemberHelp() {}
26555	    
26556	    _cMemberHelp.openHowToSetup = function(stepNumber) {
26557	    	SA.Help.openReportHelp('#pop-how-to-guide-membership', stepNumber, 'info/MembershipHelp');
26558	    }
26559	    _cMemberHelp.openHowToSetupLocal = function() {
26560	    	var isMembershipSetupScreen = $('#manage-membership #membership-list').length;
26561	    	var htm = _getHtmHowToSetup(isMembershipSetupScreen);
26562    	}
26563    	
26564    	_cMemberHelp.openPeriodInfo = function() {
26565	    	//var isMembershipSetupScreen = $('#manage-membership #membership-list').length;
26566	    	var htm = '<div id="pop-help-membership-period">' + $('#pop-membership-edit-help-period').html() + '</div>';
26567	    	GLO.Popup.Processing.open(htm, 'Membership Period + Billing Period');
26568    	}
26569    	
26570    	function _getHtmHowToSetup(isMembershipSetupScreen) {
26571    		if (isMembershipSetupScreen) {
26572    			var aNewMembership = '<a onclick="GLO.Provider.Membership.openEditType()">';
26573    		} else {
26574    			var aNewMembership = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'membership?create=membership\', this, event, true)">';
26575    		}
26576    		
26577    		var btnAddService = '<span class="btnAdd btnAddMembership"><a>Add Service to Membership</a></span>';
26578    		var btnAddMember = '<span class="btnMembership btnAdd"><a><b>+</b> Add Membership</a></span>';
26579    		var btnViewMember = '<span class="btnMembership btnAdd"><a>View Membership</a></span>';
26580    		var sellMembership = '<b style="white-space: nowrap; letter-spacing: 0;">Go to <a onclick="GLO.Provider.Membership.openSell()">Products <b class="arrow-right">&#10140;</b> Sell Membership</a></b>';
26581    		var rptMembership = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'membership/report\', this, event, true)">Membership Report</a>';
26582    		
26583    		var h0 = '<h2>Setup Membership</h2>';
26584    		var p0 = '<p></p>';
26585    		var h1 = '<h2>Create Membership</h2>';
26586    		var p1 = '<p>' + aNewMembership + 'Create a new membership</a> by entering the membership name and the normal membership price, period, and auto-bill setting</p>';
26587    		
26588    		var h2 = '<h2>Add Service(s) to Membership</h2>';
26589    		var p2 = '<p>The membership services can </p>';
26590    		var ul2 = '<ul>'
26591    					+ '<li>Be free or discounted</li>'
26592    					+ '<li>Can limit the number of appointments available to a member for each service per period</li>'
26593    				+ '</ul>';
26594    		
26595    		var h3 = '<h2>Add Client to Membership</h2>';
26596    		var p3 = '<p>Can make clients a member by </p>';
26597    		var ul3 = '<ul>'
26598    					+ '<li>Selling a membership to a client from the main menu ' + sellMembership + '</li>'
26599    					+ '<li>On a client\'s profile press the button ' + btnAddMember + '</li>'
26600    				+ '</ul>';
26601    		
26602    		var h4 = '<h2>Customize Membership for Client</h2>';
26603    		var p4 = '<p>When a client becomes a member, can view the client\'s member profile</p>';
26604    		var ul4 = '<ul>'
26605    					+ '<li>On the client\'s profile press the button ' + btnViewMember + '</li>'
26606    					+ '<li>Press the member profile on the ' + rptMembership + '</li>'
26607    				+ '</ul>';
26608    		var p4b = '<p>On the member profile can customize the membership for the specific client, such as change the</p>';
26609    		var ul4b = '<ul>'
26610    					+ '<li>Member price</li>'
26611    					+ '<li>Member period</li>'
26612    					+ '<li>Start date and/or end date</li>'
26613    					+ '<li>Member balance <i class="narrow-text">(for example, if pre-paying for membership)</i></li>'
26614    				+ '</ul>';
26615    		
26616    		var htm = '<div id="pop-help-membership-setup">' + h0 + p0 + h1 + p1 + h2 + p2 + ul2 + h3 + p3 + ul3 + h4 + p4 + ul4 + p4b + ul4b + '</div>';
26617    		var jpop = GLO.Popup.Custom.openSimple(htm);
26618    		GLO.Popup.Custom.singleButton(jpop, 'Close');
26619    	}
26620    	
26621    	return _cMemberHelp;
26622	})();
26623	
26624	
26625    return _cMembership;
26626})();
26627
26628
26629GLO.Provider.TagManager = (function() {
26630    function _cTagManager() { }
26631    
26632    _cTagManager.init = function() {
26633		GLO.Info.init();
26634		var tbl = $('#tag-manager-table');
26635		
26636		UI.initTableSorter(tbl, null, true);
26637		_initOrder(tbl);
26638		
26639		if (GLO.Uri.query('open') === 'help') {
26640			GLO.Provider.TagManager.openReportHelp()
26641		}
26642	}
26643    
26644    function _initOrder(tbl) {
26645    	var trs = tbl.find('tbody > tr');
26646    	
26647    	tbl.find('tbody').sortable({
26648			handle: '.wiz4-drag'
26649			, update: function(event, ui) {
26650				if (_isValidMove()) {
26651					var tbl = $('#tag-manager-table');
26652					var trs = tbl.find('tbody > tr');
26653					
26654					for (var i=0; i < trs.length; i++) {
26655						trs.eq(i).attr('order_sr', i+1);
26656						//trs.eq(i).find('td:first').attr('order_by', i+1);
26657					}
26658					
26659					_updateOrder();
26660				}
26661			}
26662			
26663			, stop: function (event, ui) {
26664				if (!_isValidMove()) {
26665					$(this).sortable('cancel');
26666				}
26667			}
26668			//, sort: function(event, ui) { }
26669		});
26670		
26671		//trs.find('.btnAdd').disableSelection();
26672    }
26673    
26674    function _isValidMove() {
26675    	return true;
26676    }
26677    
26678    _cTagManager.openClientReport = function(element, event) {
26679    	var tr = $(element).closest('tr');
26680    	var cttid = tr.attr('id');
26681    	var url = 'message/ClientList?tagrelationship=both&tagtype=' + cttid;
26682    	
26683    	GLO.Uri.gotoUriWithSpinner(url, element, event);
26684    }
26685    
26686    _cTagManager.openTagType = function(tagTypeId, element) {
26687    	if (!UTIL.isEmpty(tagTypeId)) {
26688			var h1 = 'Edit Tag Type';
26689			var tagName = UTIL.htmlEncode2($(element).text());
26690			var tr = $(element).closest('tr');
26691			var relationshipName = UTIL.htmlEncode2(UTIL.cleanString(tr.find('.column-relationship').text()));
26692			var clientCount = UTIL.coalesceInt(tr.find('.column-client-count').text());
26693			var tagPresetId = UTIL.coalesceInt(tr.attr('tag_preset_id'));
26694		} else {
26695			var h1 = 'Add Tag Type';
26696			var tagName = '', relationshipName = '', clientCount = 0, tagPresetId = '';
26697			var btnSave = $('.btnAddTagType');
26698		}
26699		
26700		var labelTag = '<label for="Tag_Name_vc">Tag Name</label>';
26701		var inputTag = '<input type="text" id="Tag_Name_vc" placeholder="required" value="' + tagName + '"/>';
26702		var divTag = '<div id="pop-tag-name">' + labelTag + inputTag + '</div>';
26703		
26704		var htmRelationshipAndPreset = _openTagType2(relationshipName, tagPresetId);
26705		var divMain = '<div id="pop-edit-tag-type" tag_type_id="' + UTIL.cleanString(tagTypeId) + '" clients="' + clientCount + '">';
26706		var htm = divMain + divTag + htmRelationshipAndPreset + '</div>';
26707		
26708		var jpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Provider.TagManager.saveTagType);
26709		var btnSave = jpop.find('.btnSave');
26710		
26711		jpop.find(':text').change(function() { UI.buttonDisplayChange(btnSave); });
26712    	//jpop.find(':text').keyup(function() { UI.buttonDisplayChange(btnSave); });
26713		
26714		if (!UTIL.isEmpty(tagTypeId)) {
26715        	var jbtns = jpop.find('.pop-buttons');
26716        	var btnDelete = '<a onclick="GLO.Provider.TagManager.deleteTagType()" style="padding: 3px 6px 1px 6px;">Delete</a>';
26717        	
26718        	btnSave.css({ "position": "relative", "right": "inherit", "margin": 0 });
26719        	jbtns.append('<span class="btnDelete" style="position: absolute; right: 6px; margin: 0;">' + btnDelete + '</span>');
26720        }
26721        
26722        jpop.find('#Tag_Name_vc').focus();
26723    }
26724    function _openTagType2(relationshipName, tagPresetId) {
26725    	var rlabel = 'Relationship Name', hasRelationship = '', hasPreset = '', labelPreset = '', btnPresetLabel = 'Create Preset List';
26726    	
26727    	if (innerWidth < 500) { rlabel = 'Relationship'; }
26728    	if (!UTIL.isEmpty(relationshipName)) { hasRelationship =' checked="checked"'; }
26729    	
26730    	if (!UTIL.isEmpty(tagPresetId)) {
26731    		hasPreset =' checked="checked"';
26732    		btnPresetLabel = 'Edit Preset List';
26733    		labelPreset = '<label for="Tag_Preset_id" title="List of values for this tag">Preset List</label>';
26734    	}
26735		
26736		var labelRelationshipName = '<label for="Relationship_Name_vc">' + rlabel + '</label>';
26737		var inputRelationshipName = '<input type="text" id="Relationship_Name_vc" value="' + relationshipName + '" placeholder="optional"/>';
26738		var divRelationship = '<div id="pop-relationship-name">' + labelRelationshipName + inputRelationshipName + '</div>';
26739		
26740		var rdo = '<input type="radio" name="tag-type-type" id="Tag_Is_Relationship_fl"' + hasRelationship + '/>
26740';
26741		var small = '<small>(for example, tag name = "mom", relationship name = "son")</small>';
26742		var lbl = '<label for="Tag_Is_Relationship_fl" class="tag-type-type">This tag is a type of relationship' + small + '</label>';
26743		var htm1 = '<div id="tag-type-relationship" class="tag-type-type"><div>' + rdo + lbl + '</div>' + divRelationship + '</div>';
26744		
26745		var ddPreset = _cTagManager.getPresetDropDown(tagPresetId);
26746		var btnPreset = '<span id="btnEditPreset" class="btnAdd"><a onclick="GLO.Provider.TagManager.openEditPreset(' + tagPresetId + ')">' + btnPresetLabel + '</a></span>';
26747		var divPreset = '<div id="pop-tag-preset">' + labelPreset + ddPreset + btnPreset + '</div>';
26748		
26749		var rdo = '<input type="radio" name="tag-type-type" id="Tag_Is_Preset_fl"' + hasPreset + '/>';
26750		var small = '<small>(for example, tag name = "grade", preset values = "9th", "10th", "11th", "12th")</small>';
26751		var lbl = '<label for="Tag_Is_Preset_fl" class="tag-type-type">This tag has a preset list of values' + small + '</label>';
26752		var htm2 = '<div id="tag-type-preset" class="tag-type-type"><div>' + rdo + lbl + '</div>' + divPreset + '</div>';
26753		
26754		return htm1 + htm2;
26755    }
26756    
26757    _cTagManager.getPresetDropDown = function(tagPresetId) {
26758    	if (UTIL.isEmpty(tagPresetId)) {  return ''; }
26759    }
26760    
26761    function _spinRefreshIcon(jicon) {
26762    	if (jicon.length > 0) {
26763    		if (jicon.hasClass('simple-spin')) {
26764    			return;
26765    		} else {
26766    			jicon.addClass('simple-spin');
26767    		}
26768    	}
26769    }
26770    
26771    function _stopRefreshIcon(jicon, spinWait) {
26772    	if (jicon.length > 0) {
26773	   		setTimeout(function() {
26774	   			jicon.removeClass('simple-spin');
26775	   		}, UTIL.coalesceInt(spinWait, 10));
26776	   	}
26777   	}
26778    
26779    _cTagManager.refresh = function(tagTypeId) {
26780    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/tag?ispartial=1';
26781    	var jicon = $('#tag-manager-table .refresh-icon');
26782    	_spinRefreshIcon(jicon);
26783    	
26784    	var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
26785            .success(function(data, textStatus, jqXHR) {
26786                var tbl = $(data).find('#tag-manager-table');
26787                $('#tag-manager-table').replaceWith(tbl);
26788                tbl = $('#tag-manager-table');
26789                
26790                UI.initTableSorter(tbl, null, true);
26791				_initOrder(tbl);
26792            })
26793            .error(function(jqXHR, textStatus, errorThrown) {
26794            	_stopRefreshIcon(jicon);
26795            });
26796    }
26797    
26798    function _updateOrder() {
26799    	var tbl = $('#tag-manager-table');
26800		var trs = tbl.find('tbody > tr');
26801		var xml = '<ol>';
26802		
26803		for (var i=0; i < trs.length; i++) {
26804			trs.eq(i).attr('order_sr', i+1);
26805			xml += '<li id="' + trs.eq(i).attr('id') + '" order_sr="' + (i+1) + '"/>';
26806		}
26807		
26808		xml = UTIL.htmlEncode(xml + '</ol>');
26809		var uri = GLO.Link.WebsiteDomain + 'provider/manage/TagTypeOrder';
26810		
26811        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": xml } })
26812            .success(function(data, textStatus, jqXHR) {
26813                var htm = '<div id="pop-sucess-tag-type-order">Tag Order Updated</div>';
26814                
26815                GLO.Popup.close($('#pop-sucess-tag-type-order').closest('.glopop'));
26816                GLO.Popup.Success.open(htm, 'Tag Order Updated');
26817            })
26818            .error(function(jqXHR, textStatus, errorThrown) {
26819                //GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
26820                //new GLO.Popup.Error('Unable to order the calendars staff');
26821            });
26822    }
26823    
26824    _cTagManager.saveTagType = function() {
26825    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/tagtype';
26826		var jpop = $('#pop-edit-tag-type');
26827		var tagTypeId = UTIL.cleanString(jpop.attr('tag_type_id')), clients = jpop.attr('clients');
26828		
26829		jpop = jpop.closest('.glopop');
26830		
26831		var tagName = jpop.find('#Tag_Name_vc').val(), relationship = jpop.find('#Relationship_Name_vc').val();
26832		var jd = { "tag_type_id": tagTypeId, "tag_name_vc": tagName, "relationship_name_vc": relationship };
26833		var jsave = jpop.find('.btnSave');
26834		
26835		if (UTIL.isEmpty(tagName)) {
26836			GLO.Popup.Warning.open('Please Enter a tag name', 'Tag Name Missing');
26837			return;
26838		}
26839		
26840		GLO.UI.Form.beginProcessing(jsave);
26841		
26842        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
26843            .success(function(data, textStatus, jqXHR) {
26844                GLO.Popup.close(jpop);
26845            	var trnew = $(data);
26846            	
26847            	if (UTIL.isNumber(tagTypeId)) {
26848            		var trold = $('#tag-manager-table').find('tbody > tr[id="' + tagTypeId + '"]');
26849            		trold.find('.btnTagType').replaceWith(trnew.find('.btnTagType'));
26850            		trold.find('.column-relationship').text(trnew.find('.column-relationship').text());
26851            	} else {
26852            		$('#tag-manager-table').find('tbody').prepend(trnew);
26853            	}
26854            	
26855            	var htm = '<b style="white-space: nowrap; font-size: larger; color: black;">' + tagName + '</b> Saved';
26856            	GLO.Popup.Success.open(htm, 'Tag Type Saved');
26857            })
26858            .error(function(jqXHR, textStatus, errorThrown) {
26859                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
26860                GLO.Popup.Error.open('<div><div style="margin-bottom: 12px;">Unable to save tag type at this time</div><div>Please try again</div></div>', 'Save Tag');
26861            });
26862    }
26863    
26864    _cTagManager.openReportHelp = function(isRequireGoldPackage) {
26865    	var linkTagManager = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/tag\', this, event, true)">Tag Manager</a>';
26866    	var linkClientList = '<a onclick="GLO.Report.Template2.goToReport(\'Client List\', \'message/ClientList\', event)">Client List Report</a>';
26867    	var linkTicketHistory = '<a onclick="GLO.Report.Template2.goToReport(\'' + SA.Resource.TicketHistory + '\', \'reports/TicketHistory\', event)">' + SA.Resource.TicketHistory + ' ' + SA.Resource.Report + '</a>';
26868    	var linkReminderView = '<a onclick="GLO.Report.Template2.goToReport(\'Reminder View\', \'provider/reminders\', event)">Reminder View</a>';
26869    	
26870    	var ul1 = '<li>Tags help group, categorize, and add notes to client profiles</li>';
26871    	var ul2 = '<li>Create relationships between clients like <b style="letter-spacing: 0;">friends, teacher/student, parent/child, referer, etc..</b></li>';
26872    	var ul3 = '<li>If related clients have appointment on the same day <b style="letter-spacing: 0;">top of appointment displays those client name(s)</b></li>';
26873    	var ul4 = '<li>Can use tags to filter both the ' + linkClientList + ' and ' + linkTicketHistory + '</li>';
26874    	var ul5 = '<li>Automatically apply discounts based on tags, for example tags like <b style="letter-spacing: 0;">College Student, Club Member,..</b></li>';
26875    	var ul = '<ul id="tags-why-use">' + ul1 + ul2 + ul3 + ul4 + ul5 + '</ul>';
26876    	
26877    	var h4 = '<h4 style="margin-top: 32px;">How to Add Tag to a Client Profile</h4>';
26878		var ol1 = '<li>Go to client\'s profile <small style="letter-spacing: 0;">by clicking client\'s name or enter client in search box <i>(in upper left corner)</i></small></li>';
26879		var ol2 = '<li>Press the <b style="letter-spacing: 0; color: rgb(0, 160, 220);">+ Add Tag / Relationship</b> button</li>';
26880		var ol3 = '<li>Select Tag Name or enter new tag name</li>';
26881		var ol4 = '<li>If is a relationship <small style="letter-spacing: 0;">(like mother/daughter, friend, or co-worker)</small> enter related client name</li>';
26882		var ol5 = '<li>Enter a tag note (when helpful)</li>';
26883		var ol6 = '<li>Press Save</li>';
26884    	var ol = h4 + '<ol id="tags-how-to">' + ol1 + ol2 + ol3 + ol4 + ol5 + ol6 + '</ol>';
26885    	
26886    	var tip1 = '<li>Client\'s tags displayed on the ' + linkReminderView + '</li>';
26887    	var tip2 = '<li>Use the ' + linkTagManager + ' to create, change, and remove tags</li>';
26888    	var ulTips = '<h4>Tips</h4>' + '<ul id="tags-tips">' + tip1 + tip2 + '</ul>';
26889    	
26890    	if (isRequireGoldPackage) {
26891    		ul = '<div class="gold-package-only-header"><span class="gold-package-link"><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/6\', this, event, true)">Gold Package Only</a></span></div>' + ul;
26892    	}
26893    	
26894    	var htm = '<div id="pop-info-tags" style="padding-bottom: 12px; line-height: 1.6; font-size: initial;">' + ul + ol + ulTips + '</div>';
26895    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Client Tags');
26896    	GLO.Popup.Custom.singleButton(jpop, 'Close');
26897    	
26898    	if (document.location.pathname.toLowerCase().indexOf('provider/manage/tag') === -1) {
26899    		var jbtns = jpop.find('.pop-buttons2');
26900    		var aGoTo = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/tag\', this, event, true)">Setup Cient Tags</a>';
26901    		var btnGoTo = '<span id="btnGoToTagManager" class="btnAdd" style="margin-right: 80px;">' + aGoTo + '</span>';
26902    		jbtns.prepend(btnGoTo);
26903    	}
26904    }
26905    
26906    _cTagManager.deleteTagType = function() {
26907    	var jpop = $('#pop-edit-tag-type');
26908    	var clients = jpop.attr('clients');
26909    	var tagName = jpop.find('#Tag_Name_vc').val(), relationship = jpop.find('#Relationship_Name_vc').val();
26910		
26911		var div1 = '<div>Are you sure you want to delete the tag: <b style="white-space: nowrap; font-size: larger; color: black;">
26911' + tagName + '</b></div>';
26912		var div2 = '<div>' + UTIL.pluralLabel(clients, 'client') + ' have this tag</div>';
26913		var htm = '<div id="pop-confirm-tag-type-delete">' + div1 + div2 + '</div>';
26914		
26915		GLO.Popup.Confirm.open(htm, 'Confirm Delete Tag', GLO.Provider.TagManager.deleteTagTypeConfirmed);
26916    }
26917    
26918    _cTagManager.deleteTagTypeConfirmed = function() {
26919    	var uri = GLO.Link.WebsiteDomain + 'provider/manage/TagTypeDelete';
26920		var jpop = $('#pop-edit-tag-type');
26921		var jbtn = jpop.find('.btnDelete');
26922		
26923		var tagTypeId = UTIL.cleanString(jpop.attr('tag_type_id')), clients = jpop.attr('clients');
26924		var tagName = jpop.find('#Tag_Name_vc').val(), relationship = jpop.find('#Relationship_Name_vc').val();
26925		var jd = { "tag_type_id": tagTypeId, "tag_name_vc": tagName };
26926		
26927		GLO.UI.Form.beginProcessing(jbtn);
26928		
26929        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
26930            .success(function(data, textStatus, jqXHR) {
26931                GLO.Popup.close(jpop.closest('.glopop'));
26932            	
26933            	var jdata = $(data);
26934            	var tagDeleteCount = jdata.attr('client_tag_delete_count_nr');
26935            	
26936            	var div1 = '<div>Tag Type: <b style="white-space: nowrap; font-size: larger; color: black;">' + tagName + '</b> Deleted<div>';
26937            	var div2 = '<div>Removed ' + tagDeleteCount + ' ' + UTIL.makePlural('tag', tagDeleteCount) + ' on client profiles</div>';
26938            	var htm = '<div id="pop-delete-tag-type-success">' + div1 + div2 + '</div>';
26939            	GLO.Popup.Success.open(htm, 'Tag Type Saved');
26940            	
26941            	$('#tag-manager-table').find('tbody').find('tr[id="' + tagTypeId + '"]').remove();
26942            })
26943            .error(function(jqXHR, textStatus, errorThrown) {
26944                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
26945                GLO.Popup.Error.open('<div><div style="margin-bottom: 12px;">Unable to delete tag type at this time</div><div>Please try again</div></div>', 'Delete Tag');
26946            });
26947    }
26948    
26949    return _cTagManager;
26950})();
26951
26952
26953GLO.Inventory = (function() {
26954    var _MAX_DEFAULT_ROWS, _filterInProgress = false, _morphPopup = null;
26955    
26956    function _conInventory() { }
26957    
26958    _conInventory.filterIndent = "&nbsp;&nbsp;&nbsp;&nbsp;";
26959    _conInventory.docWidth = 1275;
26960    _conInventory.doNotTrackStock = false;
26961    _conInventory.prevHash = '', _conInventory.prevHashId = null, _conInventory.prevIsItem = false, _conInventory.prevItemId = null;
26962    _conInventory.isProductList = false;
26963    
26964    _conInventory.init = function(doNotTrackStock) {
26965        if ( $('#col-cost').length === 1) { _conInventory.docWidth = 1350; }
26966        if (GLO.Info.isMobile(true)) { _conInventory.docWidth -= 280; }
26967        
26968        _conInventory.isProductList = true;
26969        _conInventory.doNotTrackStock = UTIL.parseBool(doNotTrackStock);
26970        UI.initTableSorter( $('#inventory-table.tablesorter'), null, true);
26971        var queryStringHash = document.location.hash;
26972        
26973        $('#inventory-item-form:visible').on('click', '#ba-Save', GLO.Inventory.Item.save);
26974
26975        $('#inventory-location-list').on('click', 'li', function() {
26976            var li = $(this);
26977            GLO.Inventory.updateHash('edit-location', li.attr('location_id'));
26978        });
26979        
26980        $('#inventory-vendor-list').on('click', 'li', function() {
26981            var li = $(this);
26982            //GLO.Inventory.Vendor.openEdit(li.attr('vendor_id'), li.text(), UTIL.cleanString(li.attr('distributor_id')));
26983            GLO.Inventory.updateHash('edit-vendor', li.attr('vendor_id'));
26984        });
26985
26986        $('#inventory-distributor-list').on('click', 'li', function() {
26987            var li = $(this);
26988            //GLO.Inventory.Vendor.openDistributorEdit(li.attr('distributor_id'), li.text());
26989            GLO.Inventory.updateHash('edit-distributor', li.attr('distributor_id'));
26990        });
26991
26992        $('#inventory-product-line-list').on('click', 'li', function() {
26993            var li = $(this);
26994            GLO.Inventory.updateHash('edit-product-line', li.attr('product_line_id'));
26995        });
26996        
26997        $('#inventory-unit-list').on('click', 'li', function() {
26998            var li = $(this);
26999            //GLO.Inventory.Unit.openEdit(li.attr('unit_id'), li.text(), UTIL.cleanString(li.attr('title')));
27000            GLO.Inventory.updateHash('edit-unit', li.attr('unit_id'));
27001        });
27002
27003        $('#inventory-type-list').on('click', 'li', function() {
27004            var li = $(this);
27005            //GLO.Inventory.Type.openEdit(li.attr('inventory_type_id'), li.text(), UTIL.cleanString(li.attr('type_category_id')));
27006            GLO.Inventory.updateHash('edit-type', li.attr('inventory_type_id'));
27007        });
27008
27009        $('#inventory-type-category-list').on('click', 'li', function() {
27010            var li = $(this);
27011            //GLO.Inventory.Type.openCategoryEdit(li.attr('type_category_id'), li.text());
27012            GLO.Inventory.updateHash('edit-type-category', li.attr('type_category_id'));
27013        });
27014
27015
27016        $(window).hashchange(function() {			//Bind the event.
27017            var jMainProcessing = _openInventoryProcessing();		//GLO.Popup.Processing.open('Loading...', 'Manage Inventory').getPopup().addClass('pop-stick-to-top');
27018            
27019            setTimeout(function() {
27020            	GLO.Inventory.hashOnChange();
27021            	GLO.Popup.closeIfExist(jMainProcessing);
27022            }, 100);
27023        });
27024        
27025        var shipmentId = GLO.Uri.query('EditShipmentId');
27026        var filterId = GLO.Uri.hash('filterid');
27027        
27028        if (!UTIL.isEmpty(shipmentId)) {
27029        	GLO.Inventory.updateHash('order', shipmentId);
27030        } else if (GLO.Uri.hash('action') === 'product-list' && UTIL.isEmpty(filterId)) {
27031        	_conInventory.updateHash('product-list-intro');
27032        } else {
27033        	_initFilter(filterId);
27034        	setTimeout(function() { GLO.Inventory.hashOnChange(); }, 10);                //setTimeout(function() { $(window).hashchange(); }, 10);
27035        }
27036
27037        $('#manage-inventory').on('change', 'input:visible, select:visible, textarea:visible', function() { 
27038            if ($(this).closest('#inventory-automatic-ordering').length == 0) {
27039                $('#inventory-header-action-container .btnSave a').css({ "border": "3px solid Red" });
27040            }
27041        });
27042
27043        $('#inventory-item-form').on('change', 'input:visible, select:visible, textarea:visible', function() {
27044            $('#inventory-item-form .btnSave a').css({ "border": "3px solid Red" });
27045        });
27046
27047        $('#inventory-type-category-edit').on('change', 'input:visible, select:visible, textarea:visible', function() {
27048            $('#inventory-type-category-edit .btnSave a').css({ "border": "3px solid Red" });
27049        });
27050
27051        $('#inventory-type-edit').on('change', 'input:visible, select:visible, textarea:visible', function() {
27052            $('#inventory-type-edit .btnSave a').css({ "border": "3px solid Red" });
27053        });
27054
27055        $('#inventory-unit-edit').on('change', 'input:visible, select:visible, textarea:visible', function() {
27056            $('#inventory-unit-edit .btnSave a').css({ "border": "3px solid Red" });
27057        });
27058
27059        $('#inventory-vendor-edit').on('change', 'input:visible, select:visible, textarea:visible', function() {
27060            $('#inventory-vendor-edit .btnSave a').css({ "border": "3px solid Red" });
27061        });
27062
27063        $('#inventory-distributor-edit').on('change', 'input:visible, select:visible, textarea:visible', function() {
27064            $('#inventory-distributor-edit .btnSave a').css({ "border": "3px solid Red" });
27065        });
27066
27067        $('#inventory-product-line-edit').on('change', 'input:visible, select:visible, textarea:visible', function() {
27068            $('#inventory-product-line-edit .btnSave a').css({ "border": "3px solid Red" });
27069        });
27070
27071        $('#inventory-options').on('change', 'input:visible, select:visible, textarea:visible', function() {
27072            $('#inventory-options .btnSave a').css({ "border": "3px solid Red" });
27073        });
27074        
27075        $('#product-list-intro').on('click', 'li', GLO.Inventory.filterIntro);
27076        
27077        var arrProducts = [];
27078        $('#manage-inventory tbody').find('.item-name').each(function() {
27079            var me = $(this);
27080            var nm = UTIL.coalesce(me.attr('title'), me.text());
27081            arrProducts.push({ "id": me.closest('tr').attr('id'), "label": nm, "value": nm });
27082        });
27083
27084        $("#inventory-restock-buttons #Existing_Inventory_id").autocomplete({ source: arrProducts, select: function(event, ui) {
27085                var rowId = ui.item.id;
27086                var row = $('#manage-inventory tbody tr#' + rowId);
27087                
27088                if (row.hasClass('hide')) {
27089                    row.removeClass('hide').css({ "background-color": "Yellow" });
27090                } else {
27091                    row.css({ "background-color": "Pink" });
27092                }
27093
27094                window.setTimeout(function() {
27095                    $("#inventory-restock-buttons #Existing_Inventory_id").val('');
27096                }, 900);
27097
27098                window.setTimeout(function() {
27099                    $('#manage-inventory tbody tr#' + rowId).css({ "background-color": "" });
27100                    //$('#Existing_Inventory_id').val('');
27101                }, 4500);
27102            } });
27103        
27104        var jOrderHeader = $('#inventory-order-header');
27105        jOrderHeader.find('.btnSave, .btnDelete').hover(function() {
27106                var me = $(this);
27107                if (me.hasClass('btnSave')) { 
27108                    var color = 'Green';
27109                } else {
27110                    var color = 'Red';
27111                }
27112                
27113                var fontSize = "100%";
27114                if (GLO.Info.isMobile()) { fontSize = "85%"; }
27115                
27116                $('#inventory-order-disclaimer').css({ "color": color, "font-size": fontSize });
27117            },
27118            function() {
27119                $('#inventory-order-disclaimer').css({ "font-weight": "", "color": "", "font-size": "" });
27120            });
27121
27122        jOrderHeader.find('#auto_start_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
27123        jOrderHeader.find('#auto_end_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
27124
27125        var jOrderDates = jOrderHeader.find('#inventory-order-dates');
27126        jOrderDates.find('#Order_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
27127        jOrderDates.find('#Order_Received_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek });
27128        
27129        jOrderHeader.find('#auto_ordering_dates_fl').click(function() { UI.changeFocus(this, 'auto_start_dt'); });
27130        jOrderHeader.find('#auto_ordering_minimum_fl').click(function() { UI.changeFocus(this, 'minimum_pct'); });
27131        
27132        jOrderHeader.find('#auto_start_dt').change(function() { UI.markCheckbox(this, 'auto_ordering_dates_fl'); }).change();
27133        jOrderHeader.find('#minimum_pct').change(function() { UI.markCheckbox(this, 'auto_ordering_minimum_fl'); }).change();
27134
27135        UTIL.DefaultText.init( $('#Existing_Inventory_id') );
27136        
27137        GLO.Inventory.setMaximumProductListRows(false);
27138        _init_Mobile();
27139        _init_iPad();
27140        GLO.Info.init();
27141        _initBasicPackage();
27142        _initNoBrand();
27143        
27144        if (UTIL.parseBool(doNotTrackStock)) {
27145        	var jitem = $('#inventory-item-edit');
27146        	jitem.find('.track-stock-level').removeClass('track-stock-level');
27147        	
27148        	var toHide = 'label[for="Track_Stock_fl"], label[for="In_Stock_dr"], label[for="Minimum_Stock_dr"], #Track_Stock_fl, #In_Stock_dr, #Minimum_Stock_dr, #Avg_Cost_mn, #In_Stock_link';
27149        	jitem.find(toHide).addClass('hideX');
27150        	
27151        	var jmanage = $('#manage-inventory');
27152        	jmanage.find('.item-minimum-stock, .item-in-stock-parent').addClass('hideX');
27153        	jmanage.find('#inventory-product-list-header-center').css({ "margin-right": "50px" });
27154        	//jmanage.find('#inventory-audit-button').addClass('hideX');
27155        	
27156        	if (GLO.Info.isIPad) {
27157        		_conInventory.docWidth = _conInventory.docWidth - 70;
27158        	} else if (!GLO.Info.isMobile()) {
27159        		_conInventory.docWidth = _conInventory.docWidth - 115;			// -140;				//$('#doc3').width(_conInventory.docWidth);
27160        	}
27161        } else {
27162        	$('#manage-inventory').addClass('track-stock');
27163        }
27164        
27165        _conInventory.initEnterTax();
27166        $('#header-navigation-links').find('#hd-report-product-list > a, #hd-report-link-create-order, #hd-report-receive-order > a').addClass('ignore-animate');
27167        
27168        _initLanguage();
27169        _conInventory.initHeaderHelpIcon();
27170        _initUrl(queryStringHash);
27171        _initFooterPopup();
27172        UserPortal.Lookup.initMonitorQRScan();
27173    }
27174    
27175    function _openInventoryProcessing(msg, header) {
27176    	if ($('#pop-processing-manage-inventory').length > 0) {
27177    		return;
27178    	}
27179    	
27180    	if (UTIL.isEmpty(msg)) {
27181    		msg = 'Loading...';
27182    	}
27183    	
27184    	header = UTIL.coalesceString(header, 'Manage Inventory');
27185    	var htm = '<div id="pop-processing-manage-inventory">' + msg + '</div>';
27186    	return GLO.Popup.Processing.open(htm, header).getPopup().addClass('pop-stick-to-top');
27187    }
27188    function _initFilter(filterId) {
27189    	if (UTIL.isEmpty(filterId)) { return; }
27190    	
27191    	var jhead = $('#inventory-header-filter');
27192    	jhead.find('#Filter_Company').val(filterId);
27193    	jhead.find('#Filter_Category').val(filterId);
27194    	jhead.find('#Filter_Stock_Level').val(filterId);
27195    	
27196    	GLO.Uri.removeHashKey('filterid');
27197    }
27198    
27199    function _initFooterPopup() {
27200    	var tfoot = $('#inventory-table').find('tfoot');
27201    	var backbarCost = UTIL.coalesceMoney(tfoot.attr('backbar_cost_mn')), backbarPrice = UTIL.coalesceMoney(tfoot.attr('backbar_price_mn')), backbarCount = UTIL.coalesceInt(tfoot.attr('backbar_nr'));
27202    	var retailCost = UTIL.coalesceMoney(tfoot.attr('retail_cost_mn')), retailPrice = UTIL.coalesceMoney(tfoot.attr('retail_price_mn')), retailCount = UTIL.coalesceInt(tfoot.attr('retail_nr'));
27203    	
27204    	if (retailCount > 0) {
27205    		if (backbarCount > 0) {
27206    			var caption = 'Retail & Backbar';
27207    		} else {
27208    			var caption = 'Retail';
27209    		}
27210    		
27211    		var ihtm = '<span class="info-icon" onclick="GLO.Info.openInfoIcon(this)" info="' + tfoot.attr('info') + '" header="' + caption + '"><b>i</b></span>';
27212    		
27213    		var r1 = '<label class="ft-retail-count">Count</label><b class="ft-retail-count">' + retailCount + ' <small>products</small></b>';
27214    		var r2 = '<label class="ft-retail-cost">Cost</label><b class="ft-retail-cost">' + UTIL.displayMoney(retailCost, false, false, true) + '</b>';
27215    		var r3 = '<label class="ft-retail-price">Price</label><b class="ft-retail-price">' + UTIL.displayMoney(retailPrice, false, false, true) + '</b>';
27216    		var rhtm = '<div id="product-list-intro-retail"><h6>Retail</h6>' + r1 + r2 + r3 + ihtm + '</div>';
27217    		
27218    		if (backbarCount > 0) {
27219	    		var b1 = '<label class="ft-backbar-count">Count</label><b class="ft-backbar-count">' + backbarCount + ' <small>products</small></b>';
27220	    		var b2 = '<label class="ft-backbar-cost">Cost</label><b class="ft-backbar-cost">' + UTIL.displayMoney(backbarCost, false, false, true) + '</b>';
27221	    		var b3 = '<label class="ft-backbar-price">Price</label><b class="ft-backbar-price">' + UTIL.displayMoney(backbarPrice, false, false, true) + '</b>';
27222	    		var bhtm = '<div id="product-list-intro-backbar"><h6>Backbar</h6>' + b1 + b2 + b3 + ihtm + '</div>';
27223    		} else {
27224    			var bhtm = '';
27225    		}
27226    		
27227    		var htm = '<div id="product-list-intro-info">' + rhtm + bhtm + '</div>';
27228    		$('#product-list-intro').append(htm);
27229    	}
27230    }
27231    
27232    function _initUrl(queryString) {
27233    	var open = GLO.Uri.getQueryStringValue('open', queryString).toLowerCase();					//UTIL.cleanString(GLO.Uri.hash('open')).toLowerCase();
27234    	var highlight = GLO.Uri.getQueryStringValue('highlight', queryString).toLowerCase();		//UTIL.cleanString(GLO.Uri.hash('highlight'));
27235    	var ifilter = GLO.Uri.getQueryStringValue('inventoryfilter', queryString).toLowerCase();	//UTIL.cleanString(GLO.Uri.hash('inventoryfilter')).toLowerCase();
27236    	var help = GLO.Uri.getQueryStringValue('help', queryString).toLowerCase();					//UTIL.cleanString(GLO.Uri.hash('help')).toLowerCase();
27237    	var isClick = UTIL.parseBool(GLO.Uri.getQueryStringValue('isclick', queryString));			//UTIL.parseBool(GLO.Uri.hash('isclick'));
27238    	
27239    	if (!UTIL.isEmpty(open)) {
27240	    	if (open === 'edit-product') {
27241	    		$('#inventory-table').find('tbody tr:first').find('.item-name').click();
27242	    	} else if (open === 'help-order') {
27243	    		setTimeout(function() {
27244	    			$('#inventory-header-help-icon').click();
27245	    		}, 400);
27246	    	} else if (open === 'usage-invoice') {
27247	    		//GLO.Inventory.Invoice.createUsageInvoice();
27248	    		
27249	    		//open menu just so user can see it
27250	    		setTimeout(function() {
27251	    			$('#inventory-header-action-container #btnAddCreate .btnCreate > a').click();
27252	    			
27253	    			setTimeout(function() {
27254	    				var jlink = $('#inventory-create-menu .inventory-usage-link').css({ "background-color": "deeppink" });
27255	    				
27256	    				setTimeout(function() {
27257		    				jlink.find('>a').click();
27258		    				
27259		    				setTimeout(function() {
27260			    				jlink.css({ "background-color": "" });
27261			    			}, 800);
27262		    			}, 800);
27263	    			}, 1200);
27264	    		}, 1200);
27265	    	} else if (open === 'create-menu') {
27266	    		_openCreateMenu(highlight, isClick);
27267	    	} else if (open === 'edit-menu') {
27268	    		_openEditMenu(highlight, isClick);
27269	    	}
27270    	} else if (!UTIL.isEmpty(ifilter)) {
27271    		var co = $('#Filter_Company option[value="' + ifilter + '"]').text();
27272    		var cat = $('#Filter_Category option[value="' + ifilter + '"]').text();
27273    		var h1 = '', msg = 'Filtering product list to display';
27274    		
27275    		if (!UTIL.isEmpty(co)) {
27276    			h1 = co;
27277    		}
27278    		
27279    		if (!UTIL.isEmpty(cat)) {
27280    			if (h1 !== '') {
27281    				h1 = h1 + ' and ' + cat;
27282    			} else {
27283    				h1 = cat;
27284    			}
27285    		}
27286    		
27287    		var ojprocessing = GLO.Popup.Processing.open(msg += ' ' + h1 + '...', h1);
27288    		
27289    		setTimeout(function() {
27290    			$('#Filter_Company').val(ifilter);
27291    			$('#Filter_Category').val(ifilter);
27292    			
27293    			ojprocessing.close();
27294    			GLO.Inventory.filter();
27295    		}, 1500);
27296    	}
27297    	
27298    	if (!UTIL.isEmpty(highlight)) {
27299    		setTimeout(function() { _initHighlight(highlight); }, 2400);
27300    	}
27301    	
27302    	if (!UTIL.isEmpty(help)) {
27303    		setTimeout(function() {
27304    			$('#inventory-header-help-icon').click()
27305    		}, 100);
27306    	}
27307    }
27308    
27309    function _openCreateMenu(highlight, isClick) {		//open menu so user can see it
27310		setTimeout(function() {
27311			$('#inventory-header-action-container #btnAddCreate .btnCreate > a').click();
27312			_highlightInventoryHeaderMenuItem('inventory-create-menu', highlight, isClick);
27313		}, 1200);
27314    }
27315    function _openEditMenu(highlight, isClick) {
27316    	setTimeout(function() {
27317			$('#inventory-header-action-container #btnAddCreate .btnEdit > a').click();
27318			_highlightInventoryHeaderMenuItem('inventory-edit-menu', highlight, isClick);
27319		}, 1200);
27320    }
27321    function _highlightInventoryHeaderMenuItem(menuId, highlight, isClick) {
27322    	if (UTIL.isEmpty(highlight)) { return; }
27323    	
27324    	setTimeout(function() {
27325			var jlink = $('#' + menuId + ' .' + highlight).css({ "background-color": "deeppink" });
27326			
27327			setTimeout(function() {
27328				if (UTIL.parseBool(isClick)) {
27329					jlink.find('>a').click();
27330				}
27331				
27332				setTimeout(function() {
27333    				jlink.css({ "background-color": "" });
27334    			}, 2800);
27335			}, 1200);
27336		}, 1200);
27337    }
27338    
27339    function _initHighlight(highlight) {
27340    	if (highlight === 'override-commission') {
27341    		var jcommission = $('#inventory-item-override-row');
27342    		jcommission.find('label').click();
27343    		UI.highlight(jcommission, 300, 6000, true);
27344    	}
27345    }
27346    
27347    function _initLanguage() {
27348    	if ($.cookies.get('language') === 'vi') {
27349    		var j = $('#manage-inventory');
27350    		var jselect = j.find('#Filter_Category');
27351    		
27352    		jselect.css({ "padding-right": "1px", "letter-spacing": "1px", "text-transform": "lowercase" });
27353    		jselect.find('option:first').text('(' + SA.Resource.AllCategories + ')');
27354    	}
27355    }
27356    
27357    _conInventory.initEnterTax = function(mustLaunch) {
27358    	if (!mustLaunch && (GLO.inventoryTax != 0 || $('#inventory-table > tbody > tr').length > 1) ) { return; }
27359    	
27360    	if (GLO.inventoryTax > 0) {
27361    		var taxRate = GLO.inventoryTax;
27362    	} else {
27363    		var taxRate = '';
27364    	}
27365    	
27366    	var numberInputType = "text";
27367        if (GLO.Info.isAndroid) { numberInputType = "number"; }
27368    	
27369    	var jmsg = $('<div id="pop-inventory-tax-rate" style="max-width: 500px;"> <h2 class="friendly-msg2">' + SA.Resource.ProductSalesTax + '</h2> <div class="friendly-msg2">'
27370    				+ '<div style="padding: 8px 16px;"> <label for="Edit_Inventory_Tax_Rate_pct" style="white-space: normal;">' + SA.Resource.EnterProductSalesTaxHelp + '</label> </div>'
27371    				+ '<div> <input id="Edit_Inventory_Tax_Rate_pct" type="' + numberInputType + '" value="' + taxR
27371ate + '" onkeypress="UI.numberOnly(event)" maxlength="5" style="width: 60px;"/> <b>%</b> </div>'
27372    			+ '</div> </div>');
27373    	
27374    	var jpop = new GLO.Popup.Custom(jmsg, GLO.Inventory.editTaxRate).getPopup().addClass('no-persist');
27375    	jpop.find('.pop-buttons').addClass('pop-buttons2');
27376    }
27377    
27378    function _initNoBrand() {
27379    	var rowCount = 0;
27380		var tbl = $('#inventory-table').addClass('hide');
27381		var jrows = tbl.find('tbody tr');
27382		
27383		jrows.each(function() {
27384	        if (UTIL.isEmpty($(this).find('.item-vendor').attr('vendor_id'))) { ++rowCount; }
27385	    });
27386	    
27387	    if (rowCount > 0) {
27388	    	var dd = '<dd onclick="GLO.Inventory.filterNoBrand()">( ' + SA.Resource.NoBrand + ' )</dd>';
27389	    	
27390	    	$('.intro-block-brands').find('dt').after(dd);
27391	    }
27392    }
27393    
27394    function _initBasicPackage() {
27395    	if (GLO.Info.providerPackage != 4 && GLO.Provider.isPaidAccount(true)) { return; }
27396    	
27397    	var jHeaderBtns = $('#inventory-product-list-buttons');
27398    	var btnAddCreate = jHeaderBtns.find('#btnAddCreate');
27399    	var btnAddCreateParent = btnAddCreate.closest('tr');
27400    	
27401    	jHeaderBtns.find('.btnDelete').css({ "margin-top": "8px" });
27402    	
27403    	var productList = $('#inventory-table').find('tbody tr');
27404    	
27405    	if (productList.length === 1 && productList.hasClass('no-items')) { var productListCount = 0; } else { var productListCount = productList.length; }
27406    	
27407    	var htmCount = '<span id="inventory-product-list-count" style="letter-spacing: 1px;">' + productListCount + ' ' + SA.Resource.Products.toLowerCase() + '</span>'
27408    	jHeaderBtns.find('#inventory-product-list-header-right').replaceWith(htmCount).parent()
27409    	
27410    	jHeaderBtns.find('#inventory-product-list-header-left').css({ "height": "32px", "margin-top": "8px" });
27411    	
27412    	var tds = jHeaderBtns.find('> table').css({ "width": "100%" }).find('> tbody > tr > td').css({ "width": "30%" });
27413    	tds.eq(1).css({ "text-align": "center" });
27414    	tds.eq(2).css({ "text-align": "center" });
27415    }
27416    
27417    function _init_Mobile() {
27418    	if (GLO.Info.isMobile(true)) {
27419        	setTimeout(function() { GLO.Info.setupFastClick($('#inventory-product-list-buttons')[0]); }, 900);
27420        }
27421    }
27422    
27423    function _init_iPad() {
27424    	if (!GLO.Info.isIPad) { return; }
27425    	
27426    	var j = $('#inventory-product-list-header-center');
27427    	
27428    	if (j.length === 1) {
27429    		$('#inventory-product-list-header-left').css({ "margin-right": "75px" });
27430    		j.css({ "margin-right": "20px" });
27431    	}
27432    }
27433    
27434    _conInventory.openHelp = function(helpLabel) {
27435    	_morphPopup.onBeforeOpen(helpLabel);
27436    }
27437    
27438    _conInventory.initHeaderHelpIcon = function() {
27439    	_morphPopup = new UI.MorphPopup('#inventory-header-help.help-container', '#inventory-header-help-icon.helpIcon2');		//, '#inventory-help.help-content .x-close-img, #inventory-help.help-content .btnClose'
27440    	
27441    	_morphPopup.onBeforeOpen = function(helpLabel) {
27442    		var jicon = _morphPopup.getOpenButton();				// $('#inventory-header-help-icon');
27443    		var helpLabel = UTIL.coalesce(helpLabel, jicon.attr('help_label_vc'));
27444    		
27445    		if (!UTIL.isEmpty(helpLabel)) {
27446    			jicon.removeAttr('help_label_vc');
27447    		} else {
27448    			var orderType = _conInventory.getOrderType();
27449    			var shipmentId = _conInventory.getShipmentId();
27450    			helpLabel = SA.Help.Inventory.getHelpLabel(orderType, shipmentId);
27451    		}
27452    		
27453    		if (helpLabel === 'create-order') {
27454    			SA.Help.loadStep(0);
27455    		} else if (helpLabel === 'send-order') {
27456    			SA.Help.loadStep(2);
27457    		} else if (helpLabel === 'receive-order') {
27458    			SA.Help.loadStep(3);
27459    		} else if (helpLabel === 'fill-order') {
27460    			SA.Help.loadStep(3, 2);
27461    		} else if (helpLabel === 'stock-order') {
27462    			SA.Help.loadStep(3, 3);
27463    		} else if (helpLabel === 'complete-order') {
27464    			SA.Help.loadStep(3, 4);
27465    		} else {						//if (helpLabel === 'audit' || helpLabel === 'restock') {
27466    			SA.Help.load(helpLabel);
27467    		}
27468    	}
27469    	
27470    	//mp.onBeforeClose = function() { setTimeout(function() { $('.help-content').find('.wizard-step, .help-card').css({ "display": "none" }); }, 1200); }
27471    }
27472    
27473    _conInventory.toggleAutoOrdering = function(element) {
27474    	var jfieldset = $(element).closest('fieldset');
27475    	jfieldset.toggleClass('minimize');
27476    }
27477    
27478    _conInventory.setMaximumProductListRows = function(enable) {
27479    	var productList = $('#inventory-table').find('tbody tr');
27480    	
27481    	if (!enable) {
27482    		_MAX_DEFAULT_ROWS = productList.length;
27483    	} else if (GLO.Info.isMobile(false)) {
27484        	if (productList.length > 50) {
27485        		_MAX_DEFAULT_ROWS = 25;
27486        	} else {
27487        		_MAX_DEFAULT_ROWS = productList.length;
27488        	}
27489        } else {
27490        	if (productList.length > 100) {
27491        		_MAX_DEFAULT_ROWS = 50;
27492        	} else {
27493        		_MAX_DEFAULT_ROWS = productList.length;
27494        	}
27495        }
27496        
27497        if (_MAX_DEFAULT_ROWS !== productList.length) { _setInfiniteScroll(); }
27498        
27499        $('#inventory-product-list-count').text(productList.length + ' products');
27500    }
27501	
27502	function _setInfiniteScroll() {
27503		$(window).scroll(function() {
27504			if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) {
27505				var productList = $('#inventory-table').find('tbody tr.hideTemp');
27506				
27507				if (productList.length) {
27508					var rowCount = 0, max = _MAX_DEFAULT_ROWS;
27509					if (_MAX_DEFAULT_ROWS > productList.length) { max = productList.length; }
27510					
27511					for (var i=0; i < max; i++) {
27512    					productList.eq(i).removeClass('hideTemp');
27513					}
27514				}
27515			}
27516		});
27517	}
27518	
27519    _conInventory.editTaxRate = function() {
27520        var uri = GLO.Link.Object.Provider.Ajax + 'Tax';
27521        var jpop = $('#pop-inventory-tax-rate').closest('.glopop');
27522        
27523        var inventoryTaxRate = jpop.find('#Edit_Inventory_Tax_Rate_pct').val();				//var serviceTaxRate = $('#Service_Tax_Rate_pct').val();
27524        
27525        if (jpop.length > 0) {
27526        	var isSilent = true;
27527        	GLO.Popup.close(jpop);
27528        } else {
27529        	var isSilent = false;
27530        }
27531        
27532        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Inventory_Tax_Rate_pct": inventoryTaxRate } })			//, "Service_Tax_Rate_pct": serviceTaxRate
27533            .success(function(data, textStatus, jqXHR) {
27534                if (UTIL.Validate.hasPermissionError(data)) { return; }
27535                
27536                GLO.inventoryTax = UTIL.coalesceFloat(inventoryTaxRate, 0);
27537                
27538                if (!isSilent) {
27539                	new GLO.Popup.Success(SA.Resource.TaxRateUpdated);
27540                }
27541            })
27542            .error(function(jqXHR, textStatus, errorThrown) {
27543                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
27544            });
27545    }
27546	
27547	_conInventory.goHome = function() {
27548        GLO.Inventory.updateHash('');
27549    }
27550	
27551    _conInventory.gotoList = function() {
27552        _conInventory.updateHash('product-list');
27553    }
27554    
27555    _conInventory.isProductListView = function(action) {
27556    	if (action === 'restock' || action === 'audit' || action === 'order' || action === 'order-create' || action === 'order-list' || action === 'product-list-detail' || action === 'product-list') {
27557    		return true;
27558    	} else {
27559    		return false;
27560    	}
27561    }
27562    
27563    function _setPrevHash() {
27564    	var action = UTIL.cleanString(GLO.Uri.hash('action')).toLowerCase();
27565    	_conInventory.prevHash = action;
27566        _conInventory.prevHashId = UTIL.cleanString(GLO.Uri.hash('id'));
27567    	
27568    	if (action === 'restock' || action === 'audit' || action === 'order' || action === 'order-create' || action === 'order-list' || action === 'product-list-detail' || action === 'product-list') {
27569			_conInventory.prevIsItem = false;
27570			_conInventory.prevItemId = null;
27571		} else if (action === 'inventory-options') {
27572			_conInventory.prevHash = '';
27573			_conInventory.prevHashId = null;
27574			
27575			_conInventory.prevIsItem = false;
27576			_conInventory.prevItemId = null;
27577		} else if (action === 'view-product' || action === 'edit-product' || action === 'new-product') {
27578			_conInventory.prevIsItem = true;
27579			_conInventory.prevItemId = _conInventory.prevHashId;
27580		}
27581    }
27582    
27583    _conInventory.updateHash = function(action, id, back, subAction) {
27584        _setPrevHash();
27585        
27586        if (document.location.search.toLowerCase().indexOf('editshipmentid') !== -1) {
27587            try {
27588                var origin = window.location.protocol + "//" + window.location.host;            //document.location.origin <-- doesn't work in non-Webkit browsers.
27589                var uri = origin + document.location.pathname + document.location.hash;
27590                window.history.replaceState("", "Report", uri);
27591                back = 'order-report';
27592            } catch (e) { }
27593        }
27594        
27595        if (UTIL.isEmpty(action)) {
27596        	if (UTIL.cleanString(GLO.Uri.hash('action').toLowerCase()) === "product-list-intro") {
27597        		_listProductIntro();
27598        	} else {
27599        		action = 'product-list-intro';
27600        	}
27601        }
27602        
27603        action = action.replace(' ', '-').toLowerCase();
27604        
27605        if (!UTIL.isEmpty(back)) { back = '&back=' + back; }
27606        if (!UTIL.isEmpty(subAction)) { subAction = '&and=' + subAction; }
27607        
27608        if (!UTIL.isEmpty(id)) {
27609            document.location.hash = 'action=' + action + '&id=' + id + UTIL.cleanString(back) + UTIL.cleanString(subAction);
27610        } else {
27611            document.location.hash = 'action=' + action + UTIL.cleanString(back) + UTIL.cleanString(subAction);
27612        }
27613    }
27614
27615    function _hide() {
27616        $('#inventory-vendor-edit:visible, #inventory-distributor-edit:visible, #inventory-unit-edit:visible, #inventory-type-edit:visible, #inventory-type-category-edit:visible').addClass('hide');
27617        $('#inventory-vendor-list:visible, #inventory-distributor-list:visible, #inventory-unit-list:visible, #inventory-type-list:visible, #inventory-type-category-list:visible').addClass('hide');
27618        $('#inventory-location-edit:visible, #inventory-location-list:visible').addClass('hide');
27619        $('#inventory-product-list-buttons:visible, #inventory-restock-buttons:visible, #inventory-item-form:visible, #inventory-item-view:visible').addClass('hide');
27620        $('#inventory-product-line-list:visible, #inventory-product-line-edit:visible').addClass('hide');
27621        $('#inventory-options:visible, #inventory-order-list-buttons:visible, #no-rows-found, #inventory-header-help-icon').addClass('hide');
27622        $('#order-detail-header:visible, #inventory-order-header:visible, #inventory-search-results:visible').addClass('hide');
27623        $('.inventory-header .btnBuyNow:visible, .inventory-header .btnReturnProduct:visible, #product-list-intro:visible').addClass('hide');     //#inventory-item-edit-cost:visible, 
27624        
27625        $('#inventory-table').removeClass('detail-view');
27626        $('#manage-inventory:visible').addClass('hide').removeClass('order-body').removeClass('audit-body');
27627        
27628        $('#inventory-table.hide, #inventory-header-filter.hide, #inventory-header-options-link.hide, #inventory-header-reports-link.hide').removeClass('hide');
27629        $('#bd-page > .shadow-content0').css({ "background-color": "" });
27630    }
27631    
27632    function _getFriendlyActionLabel(action) {
27633    	action = UTIL.replaceAll(action, '-', ' ');
27634    	
27635    	if (action === 'type list') {
27636    		action = 'sub-category list';
27637    	} else if (action === 'type category list') {
27638    		action = 'category list';
27639    	} else if (action === 'edit type') {
27640    		action = 'edit sub-category';
27641    	} else if (action === 'edit type category') {
27642    		action = 'edit category';
27643    	} else if (action === 'new type') {
27644    		action = 'new sub-category';
27645    	} else if (action === 'new type category') {
27646    		action = 'new category';
27647    	}
27648    	
27649    	return action.replace('vendor', 'brand');
27650    }
27651    
27652    _conInventory.hashOnChange = function() {
27653        var action = GLO.Uri.hash('action');
27654        var id = GLO.Uri.hash('id');
27655        
27656        _hide();
27657        
27658        /*
27659        if (document.location.search.toLowerCase().indexOf('editshipmentid') !== -1) {
27660            try {
27661                var uri = document.location.origin + document.location.pathname + document.location.hash;
27662                window.history.replaceState("", "Report", uri);
27663            } catch (e) { }
27664        }*/
27665        
27666        var actionLabel = _getFriendlyActionLabel(action);
27667        
27668        var h2 = $('h2.inventory-header');
27669        h2.find('.quietest-left').removeClass('hide');
27670        h2.find('#inventory-header-text').text(actionLabel);
27671        //$('#doc3').css({ "width": "875px" });
27672
27673        if (action === 'restock') {                             //if (location.pathname.indexOf('/inventory/shipment') !== -1) {
27674            GLO.Inventory.Restock.openEdit(id, 1);
27675        } else if (action === 'audit') {
27676	        GLO.Inventory.Audit.openEdit(id, 200);
27677        } else if (action === 'order') {
27678            GLO.Inventory.Order.openEdit(id);
27679        } else if (action === 'order-create') {
27680            GLO.Inventory.Order.openEdit();
27681        } else if (action === 'order-list') {
27682            GLO.Inventory.Order.openList();
27683            
27684		} else if (action === 'location-list') {
27685            GLO.Inventory.Location.openList();
27686        
27687        } else if (action === 'vendor-list') {
27688            GLO.Inventory.Vendor.openList();
27689        } else if (action === 'distributor-list') {
27690            GLO.Inventory.Vendor.openDistributorList();
27691        } else if (action === 'product-line-list') {
27692            GLO.Inventory.Vendor.openProductLineList();
27693        
27694        } else if (action === 'unit-list') {
27695            GLO.Inventory.Unit.openList();
27696        } else if (action === 'type-list') {
27697
27698            GLO.Inventory.Type.openList();
27699        } else if (action === 'type-category-list') {
27700            GLO.Inventory.Type.openCategoryList();
27701        
27702        } else if (action === 'view-product') {
27703            GLO.Inventory.Item.openView(id);
27704        } else if (action === 'edit-product' || action === 'new-product') {
27705            GLO.Inventory.Item.openEdit(id);
27706        
27707        } else if (action === 'new-location') { 
27708            GLO.Inventory.Location.openEdit();
27709        } else if (action === 'edit-location') {
27710            _editLocation(id);
27711        
27712        } else if (action === 'new-vendor') { 
27713            GLO.Inventory.Vendor.openEdit();
27714        } else if (action === 'edit-vendor') {
27715            _editVendor(id);
27716        } else if (action === 'new-distributor') {
27717            GLO.Inventory.Vendor.openDistributorEdit();
27718        } else if (action === 'edit-distributor') {
27719            _editDistributor(id);
27720        } else if (action === 'new-product-line') {
27721            GLO.Inventory.Vendor.openProductLineEdit();
27722        } else if (action === 'edit-product-line') {
27723            _editProductLine(id);
27724
27725        } else if (action === 'new-unit') {
27726            GLO.Inventory.Unit.openEdit();
27727        } else if (action === 'edit-unit') {
27728            _editUnit(id);
27729        
27730        } else if (action === 'new-type') {
27731            GLO.Inventory.Type.openEdit();
27732        } else if (action === 'edit-type') {
27733            _editType(id);
27734        } else if (action === 'new-type-category') {
27735            GLO.Inventory.Type.openCategoryEdit();
27736        } else if (action === 'edit-type-category') {
27737            _editTypeCategory(id);
27738        } else if (action === 'inventory-options') {
27739            _gotoStaffSetup();
27740        } else if (action === 'product-list-detail') {
27741            GLO.Inventory.displayAllColumns();
27742        } else if (action === 'product-list') {
27743	        _listProduct();
27744        } else {
27745        	h2.find('.quietest-left').addClass('hide');
27746        	_listProductIntro();
27747        }
27748    }
27749    
27750    function _gotoStaffSetup() {
27751    	if (GLO.Info.roleType > 219) {
27752    		$('#inventory-options').removeClass('hide');
27753        	$('h2.inventory-header #inventory-header-text').text(SA.Resource.InventoryOptions);
27754        } else {
27755        	var msg = '<div><b>Please Login as a Manager or Admin to setup</b> <ul style="text-align: left;">'
27756		        		+ '<li style="list-style: disc outside;">Staff Product Sales Commission</li>'
27757		        		+ '<li style="list-style: disc outside;">Employee Product Price Discounts</li>'
27758	        		+ '</ul>';
27759        	
27760        	var jpop = GLO.Popup.Warning.open(msg, 'Admin or Manager Only').getPopup();
27761        	jpop.find('.msg').css({ "padding-top": "0", "padding-bottom": "0" });
27762        	
27763        	GLO.Inventory.updateHash('product-list-intro');
27764        }
27765    }
27766	
27767	function _listProductIntro() {
27768		if (_MAX_DEFAULT_ROWS < 50) { _listProduct(); return; }
27769		
27770		var jManageInventory = $('#manage-inventory');
27771		jManageInventory.find('#inventory-table').addClass('hide');
27772		jManageInventory.removeClass('hide');							//do after hide inventory-table so do NOT require browser to render complete product list.
27773		
27774		$('#product-list-intro').removeClass('hide');
27775		$('h2.inventory-header #inventory-header-text').text(SA.Resource.ProductList);
27776		
27777		if (!GLO.Info.isMobile()) {
27778			var w = GLO.Inventory.docWidth + 'px';
27779        	//$('#doc3').css({ "width": w });
27780        	
27781			$('#inventory-product-list-buttons .btnDelete').addClass('hide');
27782		}
27783		
27784		_conInventory.filterClear();
27785		GLO.Inventory.displayColumns(0, jManageInventory);
27786	}
27787	
27788	function _listProduct() {
27789        var w = GLO.Inventory.docWidth + 'px';
27790        //$('#doc3').css({ "width": w });
27791        
27792	    $('h2.inventory-header #inventory-header-text').text(SA.Resource.ProductList);
27793	    $('#inventory-product-list-buttons .btnDelete').removeClass('hide');
27794	    $('body').removeClass('display-all-columns');
27795	    
27796        var jProductList = $('#manage-inventory').removeClass('hide').removeClass('display-all-columns');
27797        jProductList.find('#item-row-box-all, .item-row-box input').removeClass('hide');
27798        jProductList.find('.item-row-box .ui-icon-circle-close').addClass('hide');
27799        
27800        GLO.Inventory.displayColumns(0, jProductList);
27801        GLO.Inventory.filter(0);                //calls: _conInventory.setFooter(0);        //GLO.Inventory.filterReset();
27802    }
27803	
27804	function _listDisplayHeader(orderType, jManageInventory, id) {
27805		jManageInventory.find('.unfilled').removeClass('unfilled');
27806		
27807		if (orderType === 0) {
27808			jManageInventory.find('#inventory-product-list-buttons').removeClass('hide');
27809		} else {
27810			jManageInventory.find('#inventory-product-list-buttons').addClass('hide');
27811		}
27812		
27813		if (orderType === 2 && UTIL.isEmpty(id)) {
27814			jManageInventory.find('#inventory-order-header').removeClass('hide');
27815		} else {
27816			jManageInventory.find('#inventory-order-header').addClass('hide');
27817		}
27818	}
27819	
27820	_conInventory.clickCreateEdit = function(element) {
27821		var jbtn = $(element).parent();
27822		var isCreate = jbtn.hasClass('btnCreate');
27823		var jmenu = _conInventory.closeCreateEditMenu(isCreate, false);
27824		
27825		setTimeout(function() {
27826			jbtn.toggleClass('is-active');
27827			jmenu.toggleClass('is-active');
27828		}, 100);
27829	}
27830	_conInventory.closeCreateEditMenu = function(isCreate, isCloseOnly) {
27831		if (isCreate) {
27832			var jmenu = $('#inventory-create-menu');
27833			var jbtn = $('.fade-menu-container .btnCreate');
27834			
27835			//close the other menu (if open)
27836			$('#btnAddCreate .btnEdit.is-active').removeClass('is-active');
27837			$('#inventory-edit-menu.is-active').removeClass('is-active').addClass('hide');
27838		} else {
27839			var jmenu = $('#inventory-edit-menu');
27840			var jbtn = $('.fade-menu-container .btnEdit');
27841			
27842			//close the other menu (if open)
27843			$('#btnAddCreate .btnCreate.is-active').removeClass('is-active');
27844			$('#inventory-create-menu.is-active').removeClass('is-active').addClass('hide');
27845		}
27846		
27847		if (jmenu.hasClass('is-active')) {
27848			setTimeout(function() { jmenu.addClass('hide'); }, 900);
27849		} else {
27850			jmenu.removeClass('hide');
27851		}
27852		
27853		if (isCloseOnly) {
27854			setTimeout(function() {
27855				jbtn.removeClass('is-active');
27856				jmenu.removeClass('is-active');
27857			}, 100);
27858		}
27859		
27860		return jmenu;
27861	}
27862	
27863	_conInventory.gotoHash = function(hashUrl) {
27864		GLO.Inventory.updateHash(hashUrl);
27865	}
27866	
27867	_conInventory.displayColumns = function(orderType, jManageInventory, id) {
27868		_listDisplayHeader(orderType, jManageInventory, id);
27869		
27870		var hide = '.item-staff-price,', display = '';
27871        
27872        if (orderType === 0) {
27873        	//jManageInventory.find('#item-in-stock-th-text').text('Current');
27874        	display += '.item-row-box, .item-row-box input, #displayAllLink, #header-stock-levels1, #header-stock-levels2,';
27875        	hide += '#displaySummaryView,';
27876        } else {		// = 1, 2, 4, 200.
27877        	hide += '.item-row-box input, #displayAllLink, #displaySummaryView, #header-stock-levels1, #header-stock-levels2,';
27878		}
27879		
27880		if (orderType === 0 || orderType === 4) {
27881			hide += '.item-row-box .ui-icon-circle-close,';
27882		} else {
27883			display += '.item-row-box .ui-icon-circle-close,';
27884		}
27885		
27886		if (orderType === 0 || orderType === 200) {
27887			display += '.item-in-stock, .item-cost,';
27888			hide += '.item-cost-edit, .item-in-stock-edit,';
27889		} else {
27890			display += '.item-cost-edit, .item-in-stock-edit,';
27891			hide += '.item-cost, .item-in-stock,';
27892			
27893			jManageInventory.find('#inventory-table tbody tr').find('.item-in-stock-edit').each(function() {
27894				var me = $(this);		//.removeClass('hide');
27895				me.find('.new-in-stock-total').text('');
27896				me.find('input').val('');
27897			});
27898		}
27899		
27900		if (orderType === 4) {
27901			display += '.item-order-count,';
27902		} else {
27903			hide += '.item-order-count,';
27904		}
27905		
27906		if (orderType === 4 || orderType == 200) {
27907			hide += '.item-type,';
27908		} else {
27909			display += '.item-type,';
27910		}
27911		
27912		if (UTIL.isEmpty(id) && orderType !== 200) {
27913    		display += '.item-type-category,';
27914    	} else {
27915    		hide += '.item-type-category,';
27916    	}
27917		
27918		if (orderType === 200) {
27919        	display += '.item-upc, .item-sku, .item-audit, .item-audit-diff,';
27920        	hide += '.item-price, .item-shelf, .item-internal-only, .item-override-tax, .item-override-commission';
27921        } else {
27922        	display += '.item-price,';
27923        	hide += '.item-upc, .item-sku, .item-shelf, .item-internal-only, .item-override-tax, .item-override-commission, .item-audit, .item-audit-diff,';
27924        }
27925        
27926        display = display.substring(0, display.length - 1);
27927        hide = hide.substring(0, hide.length - 1);
27928        
27929        jManageInventory.find(display).removeClass('hide');
27930		jManageInventory.find(hide).addClass('hide');
27931	}
27932	
27933	function _editLocation(id) {
27934        var li = $('#inventory-location-list li[location_id="' + id + '"]');
27935
27936        if (li.length > 0) {
27937            var nm = li.text();
27938            GLO.Inventory.Location.openEdit(id, nm);
27939        } else {
27940            var jl = $('select#Location_id option[value="' + id + '"]');
27941            
27942            if (jl.length > 0) {
27943            	var nm = jl.text();
27944            	GLO.Inventory.Location.openEdit(id, nm);
27945            } else {
27946            	_conInventory.updateHash('location-list');
27947            }
27948        }
27949    }
27950
27951    function _editVendor(id) {
27952        var li = $('#inventory-vendor-list li[vendor_id="' + id + '"]');
27953
27954        if (li.length > 0) {
27955            var nm = UTIL.directTagOnly(li);
27956            var did = UTIL.cleanString(li.attr('distributor_id'));
27957            GLO.Inventory.Vendor.openEdit(id, nm, did);
27958        } else {
27959            var jv = $('select#Vendor_id option[value="' + id + '"]');
27960            
27961            if (jv.length > 0) {
27962            	var did = jv.attr('distributor_id');
27963            	var nm = jv.text();
27964            	GLO.Inventory.Vendor.openEdit(id, nm, did);
27965            } else {
27966            	_conInventory.updateHash('vendor-list');
27967            }
27968        }
27969    }
27970
27971    function _editDistributor(id) {
27972        var li = $('#inventory-distributor-list li[distributor_id="' + id + '"]');
27973
27974        if (li.length > 0) {
27975            GLO.Inventory.Vendor.openDistributorEdit(id, li.text());
27976        } else {
27977            var jd = $('select#Distributor_id option[value="' + id + '"]');
27978            
27979            if (jd.length > 0) {
27980            	GLO.Inventory.Vendor.openDistributorEdit(id, jd.text());
27981            } else {
27982            	_conInventory.updateHash('distributor-list');
27983            }
27984        }
27985    }
27986
27987    function _editProductLine(id) {
27988        var li = $('#inventory-product-line-list li[product_line_id="' + id + '"]');
27989        
27990        if (li.length > 0) {
27991            var vid = UTIL.cleanString(li.attr('vendor_id'));
27992            GLO.Inventory.Vendor.openProductLineEdit(id, li.text(), vid);
27993        } else {
27994            var jpl = $('select#Product_Line_id option[value="' + id + '"]');
27995            
27996            if (jpl.length > 0) {
27997            	var vid = jpl.attr('vendor_id');
27998            	GLO.Inventory.Vendor.openProductLineEdit(id, jpl.text(), vid);
27999            } else {
28000            	_conInventory.updateHash('product-line-list');
28001            }
28002        }
28003    }
28004    
28005    function _editUnit(id) {
28006        var li = $('#inventory-unit-list li[unit_id="' + id + '"]');
28007
28008        if (li.length > 0) {
28009            GLO.Inventory.Unit.openEdit(id, li.text(), UTIL.cleanString(li.attr('title')));
28010        } else {
28011            _conInventory.updateHash('unit-list');
28012            return;
28013        }
28014    }
28015
28016    function _editType(id) {
28017        var li = $('#inventory-type-list li[inventory_type_id="' + id + '"]');
28018
28019        if (li.length > 0) {
28020            var nm = li.text();
28021            var tcid = UTIL.cleanString(li.attr('type_category_id'));
28022            GLO.Inventory.Type.openEdit(id, nm, tcid);
28023        } else {
28024            var jt = $('select#Inventory_Type_id option[value="' + id + '"]');
28025            
28026            if (jt.length > 0) {
28027            	var tcid = jt.attr('type_category_id');
28028            	var nm = jt.text();
28029            	GLO.Inventory.Type.openEdit(id, nm, tcid);
28030            } else {
28031            	_conInventory.updateHash('type-list');
28032            }
28033        }
28034    }
28035
28036    function _editTypeCategory(id) {
28037        var li = $('#inventory-type-category-list li[type_category_id="' + id + '"]');
28038
28039        if (li.length > 0) {
28040            GLO.Inventory.Type.openCategoryEdit(id, li.text());
28041        } else {
28042            var jt = $('select#Type_Category_id option[value="' + id + '"]');
28043            
28044            if (jt.length > 0) {
28045            	GLO.Inventory.Type.openCategoryEdit(id, jt.text());
28046            } else {
28047            	_conInventory.updateHash('type-category-list');
28048            }
28049        }
28050    }
28051
28052    _conInventory.filterHide = function() {
28053        var jhead = $('#inventory-header-filter');
28054        
28055        var vendorId = jhead.find('#Filter_Company').val('');
28056        var distributorId = jhead.find('#Filter_Category').val('');
28057        var typeId = jhead.find('#Filter_Stock_Level').val('hide');
28058        
28059        var orderType = _conInventory.getOrderType();
28060        _conInventory.filter(orderType, true);
28061    }
28062	
28063	_conInventory.filterClear = function() {
28064		var jhead = $('#inventory-header-filter');
28065        
28066        var vendorId = jhead.find('#Filter_Company').val('');
28067        var distributorId = jhead.find('#Filter_Category').val('');
28068        var typeId = jhead.find('#Filter_Stock_Level').val('');
28069        
28070        _conInventory.filterOnChange(jhead);
28071	}
28072	
28073    _conInventory.filterReset = function() {
28074        var orderType = _conInventory.getOrderType();
28075        
28076        if (orderType == 200) {
28077        	_conInventory.filterClear();
28078        	_conInventory.updateHash('');			//_listProductIntro();
28079        } else if (orderType > 1) {
28080        	_conInventory.filterClear();
28081        	_conInventory.filter(orderType);
28082        } else {
28083        	_conInventory.filterClear();
28084        	_conInventory.updateHash('');			//_listProductIntro();
28085        }
28086        
28087        $('#inventory-product-list-buttons-table .fade-menu-container .btnAdd.is-active > a').click();
28088    }
28089
28090    _conInventory.getOrderType = function() {
28091        var orderName = $('h2.inventory-header').find('#inventory-header-text').text().toLowerCase();
28092        var orderType = 0;
28093
28094        if (orderName === 're-stock') {
28095            orderType = 1;
28096        } else if (orderName.indexOf('order') !== -1) {
28097            orderType = 2;
28098            var jDTs = $('#inventory-order-dates');
28099            
28100            if (!UTIL.isEmpty(jDTs.find('#Order_Received_dt:visible').val()) || !UTIL.isEmpty(jDTs.find('#Stock_dt:visible').text()) ) {
28101                orderType = 4;
28102            }
28103        } else if (orderName.indexOf('inventory check') !== -1 || orderName.indexOf('audit') !== -1) {
28104        	orderType = 200;
28105        }
28106        
28107        return orderType;
28108    }
28109	
28110	_conInventory.filterIntro = function() {
28111		var me = $(this);
28112		var val = me.attr('vid');
28113		
28114		if (!UTIL.isEmpty(val)) {
28115			$('#Filter_Company').val('v' + val);
28116		} else {
28117			val = me.attr('val');
28118			$('#Filter_Stock_Level').val(val);
28119		}
28120		
28121		var currText = me.text();
28122		
28123		me.html('<span style="text-transform: lowercase; color: #275264; background-color: Yellow; display: block; height: 100%; width: 100%; border-radius: 8px; padding: 7px 0; font-weight: bold;">loading...</span>');			//var throbber = $('.loadingDiv').find('img').css({ "margin": "0" }).outerHTML();
28124		window.setTimeout(function() { me.text(currText); }, 2500);
28125		
28126		window.setTimeout(function() {
28127			GLO.Inventory.updateHash('product-list');
28128			//GLO.Inventory.filter(0);
28129		}, 50);
28130		
28131		_conInventory.filterOnChange();
28132	}
28133	
28134	_conInventory.filterNoBrand = function() {
28135		_filterInProgress = true;
28136		
28137		var rowCount = 0;
28138		var orderType = _conInventory.getOrderType();
28139		
28140		$('#product-list-intro').addClass('hide');
28141		
28142		var tbl = $('#inventory-table').addClass('hide');
28143	    var jrows = tbl.find('tbody tr');
28144	    
28145	    jrows.each(function() {
28146	        var me = $(this);
28147	        
28148	        if (UTIL.isEmpty(me.find('.item-vendor').attr('vendor_id'))) {
28149	        	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28150	        } else {
28151	        	_conInventory.hideRow(me);
28152	        }
28153	    });
28154	    
28155	    tbl.removeClass('hide');
28156	    $('#inventory-table.hide, #inventory-product-list-buttons .btnDelete').removeClass('hide');
28157	    
28158	    _conInventory.setFooter(orderType);
28159	    _filterInProgress = false;
28160	}
28161	
28162    _conInventory.filter = function(orderType, isHide) {
28163    	//console.log('Inventory Filter Start: ' + new Date());
28164    	
28165    	if (document.location.hash.indexOf('action=product-list-intro') !== -1) {
28166    		document.location.hash = document.location.hash.replace('product-list-intro', 'product-list');
28167    		return;
28168    	}
28169    	
28170    	//var jMainProcessing = GLO.Popup.Processing.open('Filtering Products...', 'Manage Inventory').getPopup().addClass('pop-stick-to-top');
28171    	
28172    	if (UTIL.isEmpty(orderType)) { orderType = _conInventory.getOrderType(); }
28173        $('#product-list-intro').addClass('hide');
28174        
28175        var tbl = $('#inventory-table').addClass('hide');
28176        var jrows = tbl.find('tbody tr');
28177        var jhead = $('#inventory-header-action-container');
28178        
28179        var company = jhead.find('#Filter_Company').val();
28180        var category = jhead.find('#Filter_Category').val();
28181        
28182        if (isHide) {
28183            var stockLevel = 'hide';
28184            jhead.find('#Filter_Company').prepend('<option value="hide"></option>');
28185        } else {
28186            var stockLevel = jhead.find('#Filter_Stock_Level').val();
28187            jhead.find('#Filter_Company option[value="hide"]').remove();
28188        }
28189        
28190        GLO.UI.Form.beginProcessing( jhead.find('.btnFilterHide') );
28191        GLO.UI.Form.beginProcessing( jhead.find('.btnFilterAll') );
28192        
28193        var prefix, id, rowCount = 0, hasPreviousFilter = false;
28194        var action = GLO.Uri.hash('action').toLowerCase();
28195        //console.log('Inventory Pre-Filter: ' + new Date());
28196        
28197        if (action === 'product-list' || action === 'product-list-intro' || action === '') { _filterInProgress = true; }
28198        
28199        if (company || category || stockLevel) {
28200	        jrows.addClass('hide');
28201	        /* jrows.each(function() {			//= this was really slow (sometimes took 90 seconds if > 1,000 products) so just calling addClass
28202	            var me = $(this);
28203	            
28204	            if (!me.hasClass('hide')) {
28205	            	_conInventory.hideRow(me);
28206	            }
28207	        }); */
28208	        
28209	        //console.log('Inventory Filter Hide Complete: ' + new Date());
28210	        
28211	        if (!UTIL.isEmpty(company)) {
28212	        	//console.log('Inventory Filter Company: ' + new Date());
28213	        	prefix = company.substring(0, 1);
28214	            id = company.substring(1);
28215	
28216	            if (prefix == 'd') {
28217	                jrows.each(function() {
28218	                    var me = $(this);
28219	                    
28220	                    if (me.attr('distributor_id') == id) {
28221	                    	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28222	                    }
28223	                });
28224	            } else if (prefix == 'v') {
28225	                jrows.each(function() {
28226	                    var me = $(this);
28227	                    
28228	                    if (me.find('.item-vendor').attr('vendor_id') == id) {
28229	                    	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28230	                    }
28231	                });
28232	            } else if (prefix == 'p') {
28233	                jrows.each(function() {
28234	                    var me = $(this);
28235	                    
28236	                    if (me.find('.item-product-line').attr('product_line_id') == id) {
28237	                    	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28238	                    }
28239	                });
28240	            }
28241	            
28242	            if (company !== 'hide') { hasPreviousFilter = true; }
28243	        }
28244	
28245	        if (!UTIL.isEmpty(category)) {
28246	            //console.log('Inventory Filter Category: ' + new Date());
28247	            prefix = category.substring(0, 1);
28248	            id = category.substring(1);
28249	
28250	            if (prefix == 'c') {
28251	                jrows.each(function() {
28252	                    var me = $(this);
28253	                    if (me.find('.item-type-category').attr('type_category_id') == id) {
28254	                    	if (!hasPreviousFilter) {
28255	                    		rowCount = _conInventory.displayRow(me, rowCount, orderType);
28256	                    	}
28257	                    } else if (hasPreviousFilter) {
28258	                    	_conInventory.hideRow(me);
28259	                    }
28260	                });
28261	            } else if (prefix == 't') {
28262	                jrows.each(function() {
28263	                    var me = $(this);
28264	                    if (me.find('.item-type').attr('type_id') == id) {
28265	                    	if (!hasPreviousFilter) {
28266	                    		rowCount = _conInventory.displayRow(me, rowCount, orderType);
28267	                    	}
28268	                    } else if (hasPreviousFilter) {
28269	                    	_conInventory.hideRow(me);
28270	                    }
28271	                });
28272	            }
28273	            
28274	            hasPreviousFilter = true;
28275	        }
28276	
28277	        if (!UTIL.isEmpty(stockLevel) && stockLevel !== 'hide') {
28278	            //console.log('Inventory Filter Stock Level: ' + new Date());
28279	            stock = jrows.eq(i).find('.item-in-stock').text();
28280	            
28281	            jrows.each(function() {
28282	                var me = $(this);
28283	
28284	                var desired = me.find('.item-minimum-stock').text();
28285	                var stock = me.find('.item-in-stock-edit input:visible');
28286	                
28287	                if (stock.length === 1) { 
28288	                    stock = stock.val();
28289	                } else {
28290	                    stock = me.find('.item-in-stock').text();
28291	                }
28292	                
28293	                stock = UTIL.coalesceInt(stock, 0);
28294	                
28295	                if (stockLevel === 'in' && stock > 0) {
28296	                    if (!hasPreviousFilter) {
28297	                    	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28298	                    }
28299	                } else if (stockLevel === 'out' && stock <= 0) {
28300	                    if (!hasPreviousFilter) {
28301	                    	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28302	                    }
28303	                } else if (UTIL.isNumber(desired)) {
28304	                    desired = parseFloat(desired);
28305	                    
28306	                    if (stockLevel === 'low' && desired > stock) {
28307	                        if (!hasPreviousFilter) {
28308	                        	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28309	                        }
28310	                    } else if (stockLevel === 'high' && stock > desired) {
28311	                        if (!hasPreviousFilter) {
28312	                        	rowCount = _conInventory.displayRow(me, rowCount, orderType);
28313	                        }
28314	                    } else if (hasPreviousFilter) {
28315	                    	_conInventory.hideRow(me);
28316	                    }
28317	                } else if (hasPreviousFilter) {
28318	                	_conInventory.hideRow(me);
28319	                }
28320	            });
28321	        }
28322        } else {
28323        	//console.log('Inventory Filter Display: ' + new Date());
28324        	
28325        	for (var i=0; i < jrows.length; i++) {
28326        		rowCount = _conInventory.displayRow(jrows.eq(i), rowCount, orderType);
28327        	}
28328        }
28329        
28330        //console.log('Inventory Filter Almost Complete: ' + new Date());
28331        
28332        $('h2.inventory-header .quietest-left').removeClass('hide');
28333        _displayNoRows();
28334        _filterInProgress = false;
28335        tbl.removeClass('hide');
28336        $('#inventory-table.hide').removeClass('hide');
28337        
28338        _conInventory.filterOnChange(jhead);
28339        _conInventory.setFooter(orderType);
28340        GLO.UI.Form.resetProcessing();
28341        //GLO.Popup.close(jMainProcessing);
28342        //GLO.Popup.Info.open('Filter Finished', 'Complete');
28343        //console.log('Inventory Filter Finished: ' + new Date());
28344    }
28345    
28346    _conInventory.filterOnChange = function(jfilter) {
28347    	if (jfilter === undefined) { jfilter = $('#inventory-header-filter'); }
28348    	
28349    	var jco = jfilter.find('#Filter_Company');
28350		var jcategory = jfilter.find('#Filter_Category');
28351		var jlevel = jfilter.find('#Filter_Stock_Level');
28352		
28353		var tr = jfilter.find('tr:first');
28354		
28355		if (_filterOnChange2(jco) || _filterOnChange2(jcategory) || _filterOnChange2(jlevel)) {
28356			tr.addClass('filter-on');
28357		} else {
28358			tr.removeClass('filter-on');
28359		}
28360    }
28361    
28362    function _filterOnChange2(jdd) {
28363    	var td = jdd.closest('td');
28364    	
28365    	if (!UTIL.isEmpty(jdd.val())) {
28366    		td.css({ "background-color": "springgreen" });
28367    		return true;
28368    	} else {
28369    		td.css({ "background-color": "" });
28370    		return false;
28371    	}
28372    }
28373    
28374    function _displayNoRows() {
28375    	var j = $('#manage-inventory');
28376    	var jhead = j.find('#inventory-header-filter');
28377    	var rowCount = j.find('#inventory-table').find('tbody > tr:not(.hide)').length;
28378    	
28379    	if (rowCount > 0 || !UTIL.isEmpty(jhead.find('#Filter_Stock_Level').val())) {
28380    		_displayNoRowInfo(false, j);
28381    		return;
28382    	}
28383    	
28384    	var fcat = jhead.find('#Filter_Category').val();
28385    	var fco = jhead.find('#Filter_Company').val();
28386    	
28387    	var jco = jhead.find('#Filter_Company');
28388    	var jco2 = jco.find('option:selected');
28389    	var jco3 = jco2.text();
28390    	
28391    	if ((!UTIL.isEmpty(fcat) && !UTIL.isEmpty(fco)) || (UTIL.isEmpty(fcat) && UTIL.isEmpty(fco))) {
28392    		_displayNoRowInfo(false, j);
28393    		return;
28394    	} else if (!UTIL.isEmpty(fcat)) {
28395    		var name = jhead.find('#Filter_Category :selected').text();
28396    	} else {
28397    		var name = jhead.find('#Filter_Company :selected').text();
28398    	}
28399    	
28400    	name = $.trim(name);
28401    	_displayNoRowInfo(true, j, fcat, fco, name);
28402    }
28403    
28404    function _displayNoRowInfo(mustDisplay, j, fcat, fco, name) {
28405    	var jNoRows = j.find('#no-rows-found');
28406    	jNoRows.find('#no-rows-found-info').remove();
28407    	
28408    	if (mustDisplay) {
28409    		var filter = UTIL.coalesce(fcat, fco);
28410    		var f1 = filter.substring(0,1);
28411    		var id = filter.substring(1);
28412    		
28413    		if (f1 === 'v') {
28414    			var label = 'vendor';
28415    		} else if (f1 === 'p') {
28416    			var label = 'product-line';
28417    		} else if (f1 === 'c') {
28418    			var label = 'type-category';
28419    		} else if (f1 === 't') {
28420    			var label = 'type';
28421    		} else if (f1 === 'd') {
28422    			var label = 'distributor';
28423    		}
28424    		
28425    		var onclick = 'GLO.Inventory.updateHash(\'edit-' + label + '\', ' + id + ')';
28426    		var btn = '<span class="btnAdd" onclick="' + onclick + '"> <a style="text-transform: capitalize;">Edit / Delete ' + name + '</a> </span>';			//label.replace('-', ' ').replace('vendor', 'brand')
28427    		
28428    		jNoRows.find('#create-new-product-for').text(name);
28429    		jNoRows.append('<div id="no-rows-found-info">' + btn + '</div>');
28430    		jNoRows.removeClass('hide');
28431    	} else {
28432    		jNoRows.addClass('hide');
28433    	}
28434    }
28435    
28436    _conInventory.hideRow = function(tr) {
28437        tr.addClass('hide');
28438        
28439        if (!_filterInProgress) {
28440            tr.find('.item-cost-edit input').val( tr.find('.item-cost').text().replace('$', '') );
28441
28442            var cntEdit = tr.find('.item-in-stock-edit');
28443            cntEdit.find('input').val('');
28444            cntEdit.find('.new-in-stock-total').text('');
28445
28446            $('#inventory-restock-buttons-row:visible, #inventory-order-dates-buttons:visible').find('.btnSave a:visible').css({ "border": "3px solid Red" });
28447        }
28448    }
28449	
28450    _conInventory.displayRow = function(tr, rowNumber, orderType) {
28451        if (orderType === 200) {
28452        	if (tr.attr('track_stock_fl') === '0') { return rowNumber; }
28453        }
28454        
28455        if (rowNumber < _MAX_DEFAULT_ROWS) {
28456        	tr.removeClass('hide hideTemp');
28457        } else {
28458        	tr.addClass('hideTemp');
28459        	tr.removeClass('hide');
28460        }
28461        
28462        return ++rowNumber;
28463    }
28464
28465    _conInventory.setFooter = function(orderType) {     // = Order_Type_cd: 1 = Restock, 2 = Order, 3 = Product List (but here orderType = 0), 200 = Audit.
28466        if (UTIL.isEmpty(orderType)) { orderType = GLO.Inventory.getOrderType(); }
28467        
28468        var jtbl = $('#inventory-table');
28469        var tfoot = jtbl.find('tfoot');
28470        var jrows = jtbl.find('tbody tr:visible');
28471        var cost, price, stock, actual, diff, sdiff, torder = 0, tcost = 0, tprice = 0, tstock = 0, tActual = 0, tdiff = 0;
28472        
28473        for (var i=0; i < jrows.length; i++) {
28474            price = jrows.eq(i).find('.item-price').text().replace('$', '');
28475            
28476            cost = jrows.eq(i).find('.item-cost:visible').text().replace('$', '');
28477            if (cost === "") { cost = jrows.eq(i).find('.item-cost-edit input:visible').val(); }
28478            
28479            if (orderType === 0 || orderType === 200) {
28480                stock = jrows.eq(i).find('.item-in-stock').text();
28481            } else {
28482                stock = jrows.eq(i).find('.item-in-stock-edit input').val();
28483                torder += UTIL.coalesceInt(jrows.eq(i).find('.item-order-count input').val(), 0);
28484            }
28485            
28486            if (UTIL.isNumber(stock)) {
28487                stock = parseFloat(stock);
28488                
28489                if (stock > 0) {
28490                    tstock += stock;
28491
28492                    if (UTIL.isNumber(cost, true)) {
28493                        tcost += UTIL.coalesceMoney(cost) * stock;
28494                    }
28495
28496                    if (UTIL.isNumber(price, true)) {
28497                        tprice += UTIL.coalesceMoney(price) * stock;
28498                    }
28499                }
28500            }
28501            
28502            if (orderType === 200) {
28503            	actual = jrows.eq(i).find('.item-audit input').val();
28504            	
28505            	if (UTIL.isNumber(actual)) {
28506            		actual = Number(actual);
28507            		diff = actual - stock;
28508            		tdiff += diff;
28509            		tActual += actual;
28510            		
28511            		if (diff === 0) {
28512            			sdiff = '';
28513            		} else if (diff > 0) {
28514            			sdiff = '<span style="color: Black;">+' + diff + '</span>';
28515            		} else {
28516            			sdiff = '<span style="color: Red;">' + diff + '</span>';
28517            		}
28518            	} else {
28519            		sdiff = ''; diff = 0;
28520            	}
28521            	
28522            	jrows.eq(i).find('.item-audit-diff').html(sdiff).attr('order_by', diff);
28523            }
28524        }
28525
28526        if (UTIL.isNumber(tcost, true)) { tcost = '$' + UTIL.numberWithCommas(UTIL.roundMoney(tcost)); }
28527        if (UTIL.isNumber(tprice, true)) { tprice = '$' + UTIL.numberWithCommas(UTIL.roundMoney(tprice)); }
28528        
28529        if (UTIL.isNumber(tstock)) {
28530            tstock = UTIL.numberWithCommas(UTIL.roundMoney(tstock));
28531
28532            if (tstock.substring(tstock.length - 3) === '.00') { tstock = tstock.substring(0, tstock.length - 3); }
28533        }
28534        
28535        if (orderType === 200) {
28536        	tcost = '';
28537        	tfoot.find('.item-audit').text(tActual);
28538        	tfoot.find('.item-audit-diff').text(tdiff);
28539        }
28540        
28541        tfoot.find('.item-cost-parent').text(tcost);
28542        tfoot.find('.item-price').text(tprice);
28543        tfoot.find('.item-in-stock-parent').text(tstock);
28544        tfoot.find('.item-order-count').text(torder);
28545    }
28546
28547    _conInventory.closeSummary = function() {
28548        var jsummarypop = $('#inventory-item-summary');
28549        var jpop = jsummarypop.closest('.glopop');
28550
28551        if (jpop.length > 0) {
28552            GLO.Popup.close(jpop);
28553        } else {
28554            $.modal.close();
28555        }
28556    }
28557    _conInventory.openSummary = function(id) {
28558        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemSummary?id=' + id + '&dt=' + UTIL.getDateString();
28559
28560        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "150px auto"});
28561        var pop = $('#pop-temp');
28562        
28563        pop.html(throbber).load(uri, GLO.Inventory.openSummary2);
28564        pop.modal();
28565        
28566        if (GLO.Info.isMobile()) {
28567        	$.modal.update(300, 300);
28568        } else {
28569        	$.modal.update(300, 720);
28570        }
28571    }
28572    _conInventory.openSummaryAdjust = function(isAdjustHeight) {
28573    	var maxHeight = parseInt(innerHeight * .9);
28574    	var pop2 = $('#simplemodal-container').css({ "padding": "0", "max-height": maxHeight + "px" });
28575    	var pop = pop2.find('#pop-temp').css('padding', '0');
28576        
28577    	/*
28578    	if (GLO.Info.isMobile()) {
28579        	pop2.css({ "min-width": "300px", "max-width": "720px", "max-height": "inherit", "margin": "auto", "padding": "0" });
28580        }
28581        
28582        if (outerHeight > 980) {
28583        	pop2.css({ "max-height": "900px" });
28584        } else if (outerHeight > 860) {
28585        	pop2.css({ "max-height": "800px" });
28586        } 
28587        
28588        pop2.find('#product-summary-buttons-parent').removeClass('hide');
28589        */
28590        
28591        if (isAdjustHeight) {
28592        	var hsummary = pop2.find('#inventory-item-summary').height();					//+ 50
28593	        
28594	        if (hsummary > pop2.height()) {
28595	        	$.modal.update(hsummary, null);
28596	        }
28597        }
28598        
28599        var hpop = pop2.height();
28600        var hbody = pop2.find('#inventory-item-summary-body').height();
28601        
28602        if (hbody > hpop) {
28603        	var hBody = hpop - pop2.find('h1').height();
28604        	
28605        	pop2.find('#inventory-item-summary-body').addClass('friendly-mini-scroll').css({ "max-height": hBody + 'px' });
28606        }
28607        
28608        if (pop2.width() > innerWidth) {
28609        	$.modal.update(null, innerWidth - 20);
28610        }
28611
28612        pop2.draggable({ "handle": "h1" }).find('h1').css({ "cursor": "move" });
28613        GLO.UI.initAnimateNewLink(pop2, 'h1 > a');
28614        GLO.Inventory.Location.initProductSummary(pop2);
28615    }
28616    _conInventory.openSummary2 = function(responseText, textStatus, XMLHttpRequest) {
28617    	var pop2 = $('#simplemodal-container').css('padding', '0');
28618        var pop = pop2.find('#pop-temp').css('padding', '0');
28619        
28620    	if (GLO.Log.processesSecurityException(pop, responseText, textStatus, XMLHttpRequest)) { return; }
28621        
28622        pop2.html(responseText);
28623        _conInventory.openSummaryAdjust(true);
28624    }
28625    _conInventory.openSummaryFromItem = function() {
28626    	var id = $('#inventory-item-form').find('#Inventory_id').val();
28627    	_conInventory.openSummary(id);
28628    }
28629    
28630    _conInventory.gotoReports = function() {
28631        document.location = GLO.Link.Page.Provider.Home + 'reports/inventory';
28632    }
28633
28634    _conInventory.gotoOptions = function() {
28635        _conInventory.updateHash('inventory-options');
28636    }
28637
28638    _conInventory.saveOptions = function() {
28639        var j = $('#inventory-options');
28640        
28641        var epriceMoney = j.find('#Employee_Price_Default_mn');
28642        var epricePercent = j.find('#Employee_Price_Default_pct');
28643        var epriceBelow = j.find('#Employee_Price_Default_Below_pct');
28644
28645        if (epriceMoney.val() !== epriceMoney.attr('original') || epricePercent.val() !== epricePercent.attr('original')) {
28646            _conInventory.openStaffPricesBulkUpdate();
28647            
28648            var jpop = $('#inventory-options-mass-update');
28649            jpop.find('#Bulk_Update_Employee_Price_mn').val(epriceMoney.val());
28650            jpop.find('#Bulk_Update_Employee_Price_pct').val(epricePercent.val());
28651            jpop.find('#Bulk_Update_Employee_Price_Below_pct').val(epriceBelow.val());
28652            jpop.find('#Employee_Price_Update_cd').val('new');
28653        } else {
28654            _conInventory.saveOptionsConfirmed();
28655        }
28656    }
28657
28658    _conInventory.openStaffPricesBulkUpdate = function() {
28659        var dd = $('#Filter_Company').clone().attr('id', 'Employee_Price_Update_cd');
28660        var opt1 = dd.find('option:first').attr('value', 'all');
28661        var inputCSS = 'letter-spacing: 1px; font-size: 16px;';
28662        var labelCSS = 'letter-spacing: 1px; font-size: 16px;';
28663        
28664        var joptions = $('#inventory-options');
28665        var dollarAboveCost = UTIL.displayMoney(joptions.find('#Employee_Price_Default_mn').val(), true);
28666        var percentAboveCost = UTIL.displayMoney(joptions.find('#Employee_Price_Default_pct').val(), true);
28667        var percentBelowPrice = UTIL.displayMoney(joptions.find('#Employee_Price_Default_Below_pct').val(), true);
28668        
28669        var divEdit = '<div id="inventory-options-mass-update-input" style="margin-bottom: 35px;">'
28670	                	+ '<div style="letter-spacing: 2px; text-align: center; text-transform: capitalize; font-size: 20px; font-weight: bold;">' + SA.Resource.UpdateStaffPriceTo + '</div>'
28671	                	+ '<div style="max-width: 280px; margin: auto; margin-top: 12px; text-align: left; letter-spacing: 1px;">'
28672		                	+ '<div>'
28673		                		+ '<label for="Bulk_Update_Employee_Price_mn" style="' + labelCSS + 'margin-right: 2px; font-weight: bold;">$</label>'
28674	                    		+ '<input id="Bulk_Update_Employee_Price_mn" type="text" value="' + dollarAboveCost + '" maxlength="6" pattern="[.0-9]+" onkeypress="UI.numberOnly(event)" style="width: 60px;' + inputCSS + 'margin-right: 12px;"/>'
28675	                    		+ '<label for="Bulk_Update_Employee_Price_mn" style="' + labelCSS + '">' + SA.Resource.above_cost + '</label>'
28676	                    	+ '</div>'
28677	                    	+ '<div style="margin-top: 10px; margin-bottom: 10px; margin-left: 2px;">'
28678	                    		+ '<label style="' + labelCSS + '"> ' + SA.Resource.or_text + ' </label>'
28679	                    		+ '<input id="Bulk_Update_Employee_Price_pct" type="text" value="' + percentAboveCost + '" maxlength="4" pattern="[.0-9]+" onkeypress="UI.numberOnly(event)" style="width: 40px;' + inputCSS + 'margin-left: 4px;"/>'
28680	                    		+ '<label for="Bulk_Update_Employee_Price_pct" style="font-size: 16px; font-weight: bold; margin-left: 2px; margin-right: 9px;">%</label>'
28681	                    		+ '<label for="Bulk_Update_Employee_Price_pct" style="' + labelCSS + '">' + SA.Resource.above_cost + '</label>'
28682	                    	+ '</div>'
28683	                    	+ '<div style="margin-left: 2px; white-space: nowrap;">'
28684	                    		+ '<label style="' + labelCSS + '"> ' + SA.Resource.or_text + ' </label>'
28685	                    		+ '<input id="Bulk_Update_Employee_Price_Below_pct" type="text" value="' + percentBelowPrice + '" maxlength="4" pattern="[.0-9]+" onkeypress="UI.numberOnly(event)" style="width: 40px;' + inputCSS + 'margin-left: 4px;"/>'
28686	                    		+ '<label for="Bulk_Update_Employee_Price_Below_pct" style="' + labelCSS + 'font-weight: bold; margin-left: 2px; margin-right: 8px;">%</label>'
28687	                    		+ '<label for="Bulk_Update_Employee_Price_Below_pct" style="' + labelCSS + '">' + SA.Resource.below_regular_price + '</label>'
28688	                    	+ '</div>'
28689	                    + '</div>'
28690                	+ '</div>';
28691
28692        opt1.text(SA.Resource.AllProducts);
28693        opt1.after('<optgroup></optgroup>');
28694        opt1.after('<option value="empty">' + SA.Resource.ProductNoStaffPrice + '</option>');
28695        opt1.after('<option value="new" title="' + SA.Resource.NewProductStaffPriceHelp + '">' + SA.Resource.OnlyNewProducts + '</option>')
28696        
28697        var div = $('<div id="inventory-options-mass-update">'
28698                    + '<h1 style="letter-spacing: 2px; text-transform: capitalize; font-size: 20px;">' + SA.Resource.ChangeCurrentStaffPrices + '?</h1>'
28699                    + '<div id="inventory-options-mass-update-body" style="text-align: center;">'
28700                    	+ divEdit
28701                    	+ '<label for="Employee_Price_Update_cd" style="display: block; margin: 10px; margin-top: 50px; text-align: center; letter-spacing: 1px; white-space: inherit;">' + SA.Resource.ProductUpdateStaffPrice + '</label>'
28702                    	+ dd.outerHTML()
28703                	+ '</div></div>');
28704        
28705        var jpop = GLO.Popup.Custom(div, GLO.Inventory.saveOptionsConfirmed);
28706        jpop = jpop.getPopup();
28707        jpop.find('.pop-buttons').css({ "width": "300px", "white-space": "nowrap", "margin-top": "35px" });
28708    }
28709
28710    _conInventory.saveOptionsConfirmed = function() {
28711        var jpop = $('#inventory-options-mass-update');
28712        
28713        if (jpop.length === 1) {
28714            var epriceUpdateId = jpop.find('#Employee_Price_Update_cd:visible').val();
28715            var epriceMoney = jpop.find('#Bulk_Update_Employee_Price_mn').val();
28716            var epricePercent = jpop.find('#Bulk_Update_Employee_Price_pct').val();
28717            var ePriceBelowPercent = jpop.find('#Bulk_Update_Employee_Price_Below_pct').val();
28718        } else {
28719            var epriceUpdateId = '';
28720            var jdoc = $('#inventory-options');
28721            var epriceMoney = jdoc.find('#Employee_Price_Default_mn').val();
28722            var epricePercent = jdoc.find('#Employee_Price_Default_pct').val();
28723            var ePriceBelowPercent = jdoc.find('#Employee_Price_Default_Below_pct').val();
28724        }
28725        
28726        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Options';
28727        var j = $('#inventory-options');
28728        
28729        var inventoryTax = j.find('#Inventory_Tax_Rate_pct').val();
28730        var serviceTax = j.find('#Service_Tax_Rate_pct').val();
28731        var commission = j.find('#Inventory_Staff_Commission_pct').val();
28732        
28733        var jd = { "inventoryTaxRate": inventoryTax, "serviceTaxRate": serviceTax, "employeeCommission": commission
28734                    , "employeePriceDefaultMoney": epriceMoney, "employeePriceDefaultPercent": epricePercent, "employeePriceDefaultBelowPercent": ePriceBelowPercent
28735                    , "employeePriceUpdateId": epriceUpdateId };
28736
28737        GLO.Popup.close( $('#inventory-options-mass-update').closest('.glopop') );
28738        
28739        var saveBtn = j.find('.btnSave');
28740        saveBtn.find('a').css({ "border": "3px solid transparent" });
28741        GLO.UI.Form.beginProcessing( saveBtn );
28742
28743        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
28744            .success(function(data, textStatus, jqXHR) {
28745                if (UTIL.Validate.hasPermissionError(data)) { return; }
28746
28747                GLO.inventoryTax = inventoryTax;
28748                GLO.serviceTax = serviceTax;
28749                
28750                new GLO.Popup.Success(SA.Resource.SuccessfullySaved);
28751                location.reload();          //_conInventory.updateHash('product-list');
28752            })
28753            .error(function(jqXHR, textStatus, errorThrown) {
28754                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
28755                GLO.UI.Form.resetProcessing();
28756            });
28757    }
28758
28759    _conInventory.confirmCommission = function(element) { }     //called on Inventory Options (can delete call + this function).
28760
28761    _conInventory.confirmTaxRate = function(element) {           //called on Inventory Options (can delete call + this function).
28762        return;
28763        /*
28764        var j = $(element);
28765        var tax0 = UTIL.coalesceInt(j.attr('original'), 0);
28766        var tax1 = UTIL.coalesceInt(j.val(), 0);
28767
28768        new GLO.Popup.Confirm(SA.Resource.ChangeTaxRateQuestion + ' ' + tax0 + '% ' + SA.Resource.to_text + ' ' + tax1 + '%?', GLO.Inventory.editTaxRate, function() {
28769            j.val(j.attr('original'));
28770        });
28771        */
28772    }
28773
28774    _conInventory.displayAllColumns = function() {
28775        _listProduct();
28776        $('#doc3').css({ "width": "" });
28777        $('body').addClass('display-all-columns');
28778        
28779        var j = $('#manage-inventory').addClass('display-all-columns');
28780        var jtbl = j.find('#inventory-table').addClass('detail-view');
28781        //jtbl.find('.item-product-line, .item-type-category').addClass('hide');
28782        jtbl.find('.item-staff-price, .item-upc, .item-sku, .item-product-line, .item-type-category, .item-shelf, .item-internal-only, .item-override-tax, .item-override-commission').removeClass('hide');
28783        jtbl.find('.item-row-box').addClass('hide');
28784        jtbl.find('#displayAllLink').addClass('hide');
28785        jtbl.find('#displaySummaryView').removeClass('hide');
28786    }
28787    
28788    _conInventory.filterIsEmpty = function() {
28789    	var jhead = $('#inventory-header-filter');
28790        
28791        var co = jhead.find('#Filter_Company').val();
28792        var distributorId = jhead.find('#Filter_Category').val();
28793        var typeId = jhead.find('#Filter_Stock_Level').val();
28794        
28795        if ( (co === '' || co === 'hide') && distributorId === '' && (typeId === '' || typeId === 'hide')) {
28796        	return true;
28797        } else {
28798        	return false;
28799        }
28800    }
28801    
28802    _conInventory.backViaUri = function() {
28803    	var back = GLO.Uri.hash('back').toLowerCase();
28804    	
28805    	if (!UTIL.isEmpty(back)) {
28806    		if (back === 'order-report') {
28807        		document.location = document.location.protocol + '//' + document.location.host + '/reports/inventory/#tab=order-and-restock';
28808        	} else {
28809        		GLO.Inventory.updateHash(back);
28810        	}
28811        	
28812    		return true;
28813    	}
28814    	
28815    	return false;
28816    }
28817    
28818    _conInventory.getShipmentId = function() {
28819    	var shipmentId = GLO.Uri.url('id');
28820		
28821		if (!UTIL.isNumber(shipmentId)) {
28822			shipmentId = $('#shipment-detail-header').attr('shipment_id');
28823		}
28824    	
28825    	if (!UTIL.isNumber(shipmentId)) {
28826    		shipmentId = $('#order-detail-header').attr('shipment_id');
28827    	}
28828		
28829		if (!UTIL.isNumber(shipmentId)) {
28830    		shipmentId = $('#inventory-restock-buttons #Shipment_id').val();
28831    	}
28832		
28833		return shipmentId;
28834    }
28835    
28836    _conInventory.gotoGiftCardList = function(isVoucher) {
28837    	var categoryId = 'c' + GLO.Inventory.Type.getGiftCardCategory();
28838    	//GLO.Inventory.updateHash('product-list', categoryId);			//GLO.Uri.gotoUriWithSpinner('/provider/inventory#action=product-list&filterid=c52535', this, event, true)
28839    	//document.location.hash = 'action=product-list&filterid=' + categoryId;
28840    	_conInventory.closeCreateEditMenu(false, true);
28841    	
28842    	$('#inventory-header-filter #Filter_Category').val(categoryId).change();
28843    }
28844    
28845    return _conInventory;
28846})();
28847
28848
28849GLO.Inventory.Restock = (function() {
28850    function _conIRestock() { }
28851    
28852    _conIRestock.openList = function() {
28853        $('#bd-page > .shadow-content0').css({ "background-color": "#FFE4E1" });
28854    }
28855
28856    _conIRestock.back = function() {
28857        if (!GLO.Inventory.backViaUri()) {
28858        	GLO.Inventory.updateHash('product-list');
28859        }
28860    }
28861    
28862    function _listRestockandAuditButtons(orderType, note) {
28863    	var jHead = $('#inventory-restock-buttons').removeClass('hide');
28864        jHead.find('#inventory-restock-edit-buttons').removeClass('hide');
28865        jHead.find('#Order_id').val('');
28866        
28867        note = UTIL.coalesce(note, $('#shipment-detail-header').find('#edit-shipment-note').text())
28868        jHead.find('#Shipment_Note_vc').val(note);
28869        jHead.find('.btnDelete').addClass('hide');
28870        
28871        $('#order-editable-fields').addClass('hide');
28872    }
28873    
28874    function _listOrderButtions(orderType, id, note) {
28875    	var jHead = $('#inventory-order-header').removeClass('hide');
28876        jHead.find('#Order_id').val( UTIL.cleanString(id) );
28877        
28878        var jOrderBtns = $('#inventory-order-buttons');
28879        var jStockBtns = $('#inventory-restock-buttons').removeClass('hide');
28880        
28881        jStockBtns.find('#inventory-restock-edit-buttons').addClass('hide');
28882        $('#order-editable-fields').removeClass('hide');
28883        
28884        if (!UTIL.isEmpty(id)) {
28885            $('#inventory-automatic-ordering').addClass('hide').find('#last_order_date').text('');
28886            
28887            /*
28888            if (orderType === 4) {
28889                jOrderBtns.find('.btnDelete').addClass('hide');          //jHead.find('#inventory-order-dates-buttons .btnDelete').removeClass('hide');
28890            } else {
28891                jOrderBtns.find('.btnDelete').removeClass('hide');          //jHead.find('#inventory-order-dates-buttons .btnDelete').removeClass('hide');
28892            }
28893            
28894            jOrderBtns.find('#inventory-order-dates-buttons').css({ "width": "90%" });
28895            */
28896            
28897            jOrderBtns.find('#inventory-order-dates').removeClass('hide');
28898            jOrderBtns.find('.btnDelete').removeClass('hide');
28899            
28900            var jtbl = $('#order-detail-header');
28901            jStockBtns.find('#Shipment_Note_vc').val( UTIL.coalesce(note, jtbl.find('#edit-order-note').text(), '') );
28902        } else {
28903            $('#inventory-automatic-ordering').removeClass('hide');
28904            
28905            jOrderBtns.find('#inventory-order-dates').addClass('hide');
28906            
28907            //jOrderBtns.find('#inventory-order-dates-buttons').css({ "width": "75%" });
28908            jOrderBtns.find('.btnDelete').addClass('hide');
28909            
28910            jStockBtns.find('#Shipment_Note_vc').val(UTIL.cleanString(note));
28911        }
28912    }
28913    
28914    function _listSetCSSandLabels(orderType, jProductList, id) {
28915    	var backColor, w, itemCountLabel = SA.Resource.Count, h2Text;
28916    	
28917    	if (orderType == 200) {
28918        	backColor = 'PaleGreen';			//#98FB98
28919        	w = GLO.Inventory.docWidth + 'px';
28920        	
28921        	itemCountLabel = SA.Resource.Expected;
28922        	h2Text = SA.Resource.InventoryCheck;
28923        	
28924        	jProductList.find('th.item-in-stock-parent').css({ "border-top-right-radius": "" });
28925        } else if (orderType > 0 && orderType < 200) {
28926        	backColor = '';
28927        	w = GLO.Inventory.docWidth + 'px';
28928        	
28929        	if (orderType === 1) {
28930        		h2Text = SA.Resource.ReStock;
28931        	} else {
28932        		if (!UTIL.isEmpty(id)) {
28933	        		h2Text = '<b>' + SA.Resource.Edit + '</b> ' + SA.Resource.Order;
28934	        		
28935	        		if (!UTIL.isEmpty(GLO.Inventory.shipment.shipment_number_vc)) { h2Text += ' #' + GLO.Inventory.shipment.shipment_number_vc; }
28936	        	} else {
28937	        		h2Text = SA.Resource.OrderForm;
28938	        	}
28939        		
28940        		if (orderType === 4) { itemCountLabel = SA.Resource.Received; }
28941        	}
28942        	
28943        	jProductList.find('th.item-in-stock-parent').css({ "border-top-right-radius": "15px" });
28944        } else {
28945        	backColor = '#FFE4E1';            //#FFE1FF, #FFFACD
28946        	w = (GLO.Inventory.docWidth + 50) + 'px';
28947        	
28948        	h2Text = SA.Resource.ProductList;
28949        }
28950        
28951        $('#bd-page > .shadow-content0').css({ "background-color": backColor });
28952        //$('#doc3').css({ "width": w });
28953        
28954        $('h2.inventory-header #inventory-header-text').html(h2Text);
28955        jProductList.find('#item-in-stock-th-text').text(itemCountLabel);
28956    }
28957    
28958    function _hasFilter(id) {
28959    	if (UTIL.isEmpty(id)) {
28960            var jhead = $('#inventory-header-action-container');
28961            var company = jhead.find('#Filter_Company').val();
28962            var category = jhead.find('#Filter_Category').val();
28963            var stockLevel = jhead.find('#Filter_Stock_Level').val();
28964            
28965            if (UTIL.isEmpty(company) && UTIL.isEmpty(category) && UTIL.isEmpty(stockLevel)) {
28966                jhead.find('#Filter_Company').prepend('<option value="hide"></option>').val('hide');
28967                return false;
28968            }
28969        }
28970        
28971        return true;
28972    }
28973    
28974    function _listPopulate(orderType, tbody, id) {
28975    	var arr = GLO.Inventory.shipment;
28976        
28977		if (!UTIL.isEmpty(id) && arr !== undefined) {
28978            var jEditInput, inventoryIds = '';
28979            
28980            for (var i=0; i < arr.length; i++) { inventoryIds += arr[i]["inventory_id"] + ','; }
28981            
28982            if (arr.length > 0) { inventoryIds = inventoryIds.substring(0, inventoryIds.length - 1); }
28983            if (!UTIL.isEmpty(inventoryIds)) { inventoryIds = inventoryIds.split(','); }
28984            
28985            tbody.each(function() {
28986                var me = $(this);
28987                var ocount, cnt, totalCnt, cost, rowId = me.attr('id');
28988                
28989                if (inventoryIds.length === 0) {
28990                	me.addClass('hide');
28991                } else if (!inventoryIds.has(rowId)) {
28992                    me.addClass('hide');
28993                } else {
28994                    for (var j=0; j < arr.length; j++) {
28995                        if (arr[j]["inventory_id"] == rowId) { break; }
28996                    }
28997                    
28998                    for (var s=0; s < inventoryIds.length; s++) {
28999                        if (inventoryIds[s] == rowId) { 
29000                        	inventoryIds.remove(s);
29001                        	break;
29002                        }
29003                    }
29004                    
29005                    if (orderType === 200) {
29006                    	me.find('.item-audit input').val(arr[j]["actual_dr"]);
29007                    } else {
29008	                    cnt = arr[j]["count_dr"];
29009	                    totalCnt = me.find('.item-in-stock').text();
29010	                    
29011	                    cost = arr[j]["cost_mn"];
29012	                    if (UTIL.isNumber(cost, true)) { cost = UTIL.roundMoney(cost); }
29013	                    
29014	                    if (orderType === 4) {
29015	                        totalCnt = UTIL.roundMoney(totalCnt) - UTIL.roundMoney(cnt);
29016	                        me.find('.current-in-stock').text(totalCnt);
29017	                        
29018	                        ocount = arr[j]["order_count_nr"];
29019	                        jEditInput = me.find('.item-in-stock-edit input').val(cnt);
29020	                    } else {
29021	                    	me.find('.current-in-stock').text(totalCnt);
29022	                        ocount = '';
29023	                        
29024	                        if (orderType === 2) {
29025	                    		jEditInput = me.find('.item-in-stock-edit input').val( arr[j]["order_count_nr"] );
29026	                    	} else {
29027	                    		jEditInput = me.find('.item-in-stock-edit input').val(cnt);
29028	                    	}
29029	                    }
29030	                    
29031	                    me.find('.item-cost-edit input').val(cost);
29032	                    me.find('.item-order-count input').val(ocount);
29033	                    jEditInput.change();
29034                    }
29035                    
29036                    me.removeClass('hide');
29037                }
29038            });
29039            
29040            _displayDeletedProducts(inventoryIds);
29041            
29042            var jOrderHeader = $('#order-detail-header');
29043            var vid = jOrderHeader.attr('vendor_id');
29044            var did = jOrderHeader.attr('distributor_id');
29045            
29046            if (!UTIL.isEmpty(vid)) {
29047                $('#Filter_Company').val('v' + vid);
29048                GLO.Inventory.filterOnChange();
29049            } else if (!UTIL.isEmpty(did)) {
29050                $('#Filter_Company').val('d' + did);
29051                GLO.Inventory.filterOnChange();
29052            }
29053            
29054            $('#inventory-table').before( jOrderHeader.removeClass('hide') );
29055            
29056            if (orderType !== 200) {
29057            	$('#inventory-header-filter').addClass('hide');
29058            	$('#inventory-header-action-container').find('#Order_Received_dt').change();
29059            }
29060        } else {
29061            $('#inventory-header-filter, #inventory-order-dates-buttons, #inventory-order-disclaimer').removeClass('hide');
29062            
29063            tbody.find('tr').each(function() {
29064            	var me = $(this);
29065            	me.find('.item-order-count input').val('');
29066            	
29067            	if (orderType !== 200) {
29068            		me.find('.current-in-stock').text(me.find('.item-in-stock').text());
29069            	}
29070            });
29071        }
29072    }
29073    
29074    _conIRestock.openEdit = function(id, orderType, note) {
29075        var jProductList = $('#manage-inventory');
29076        var tbody = jProductList.find('#inventory-table tbody tr');
29077        var selectedRows = tbody.find('.item-row-box input:checked');
29078        
29079        GLO.Inventory.displayColumns(orderType, jProductList, id);
29080        _listSetCSSandLabels(orderType, jProductList, id);
29081        
29082        if (selectedRows.length === 0) { var hasFilter = _hasFilter(id); } else { var hasFilter = false; }
29083        
29084        if (selectedRows.length > 0 || !hasFilter) {
29085            tbody.find('.item-row-box input:not(:checked)').closest('tr').addClass('hide');
29086        }
29087        
29088        if (orderType === 2 || orderType === 4) {
29089            jProductList.addClass('order-body');
29090    		
29091    		_listOrderButtions(orderType, id, note);
29092        } else {
29093        	// jProductList.removeClass('order-body');
29094            if (orderType === 200) { jProductList.addClass('audit-body'); }
29095            
29096            _listRestockandAuditButtons(orderType, note)
29097            
29098            if (orderType !== 200 && !UTIL.isEmpty(id) && GLO.Inventory.shipment === undefined) {
29099	            _conIRestock.back();
29100	            return;
29101	        }
29102        }
29103        
29104        _listPopulate(orderType, tbody, id);
29105        jProductList.removeClass('hide');
29106        GLO.Inventory.setFooter(orderType);
29107        
29108        $('#inventory-header-help-icon').removeClass('hide');
29109        $('.btnSave:visible a').css({ "border": "3px solid transparent" });
29110        
29111        if (!hasFilter) { $('#Filter_Company').focus(); }
29112        
29113        if (!UTIL.isEmpty(id) && GLO.Uri.hash('and').toLowerCase() === 'email') {
29114        	GLO.Inventory.Order.email(true);
29115        } else {
29116        	var helpLabel = SA.Help.Inventory.getHelpLabel(orderType, id);
29117        	SA.Help.display(helpLabel);
29118        }
29119    }
29120    
29121    function _displayDeletedProducts(inventoryIds) {
29122    	if (inventoryIds && inventoryIds.length) {
29123    		var arr = GLO.Inventory.shipment;
29124			var deleteCount = 0;
29125			var delHtml = '<fieldset> <legend style="color: Red;">' + SA.Resource.DeletedProducts + '</legend> <table style="width: 100%;">'
29126							+ '<tr> <th class="del-col-n
29126ame">' + SA.Resource.ProductName + '</th> <th class="del-col-size">Size</th> <th class="del-col-brand">' + SA.Resource.Brand + '</th> <th class="del-col-category">' + SA.Resource.Category + '</th> <th class="del-col-cost">' + SA.Resource.Cost + '</th> <th class="del-col-ordered">' + SA.Resource.Ordered + '</th> <th class="del-col-received">' + SA.Resource.Received + '</th> </tr>';
29127			
29128			for (var s=0; s < arr.length; s++) {
29129				if (!UTIL.isEmpty(arr[s].name_vc)) {
29130					delHtml += '<tr> <td class="del-col-name">' + arr[s].name_vc + '</td>'
29131								+ '<td class="del-col-size">' + arr[s].size_dr + ' ' + arr[s].unit_abbreviation + '</td>'
29132								+ '<td class="del-col-brand">' + arr[s].vendor_name_vc + '</td>'
29133								+ '<td class="del-col-category">' + arr[s].type_category_name_vc + '<br/>' + arr[s].type_name_vc + '</td>'
29134								+ '<td class="del-col-cost">$' + UTIL.roundMoney(arr[s].cost_mn) + '</td>'
29135								+ '<td class="del-col-ordered">' + arr[s].order_count_nr + '</td>'
29136								+ '<td class="del-col-received">' + UTIL.roundMoney(arr[s].count_dr) + '</td>'
29137							+ '</tr>';
29138					++deleteCount;
29139				}
29140			}
29141			
29142			if (deleteCount == 0) {
29143				return;
29144			} else if (deleteCount == 1) {
29145				var lbl = SA.Resource.OrderItemDeleted + ':';
29146			} else {
29147				var lbl = SA.Resource.OrderIncludes + ' ' + deleteCount + ' ' + SA.Resource.ItemsDeletedHelp + ':';
29148			}
29149			
29150			delHtml = '<div id="deleted-items-table"><div style="margin-left: -32px; margin-right: 28px; margin-bottom: 20px;">' + lbl + '</div>' + delHtml + '</table> </fieldset> </div>';
29151			
29152			var ojpop = new GLO.Popup.Warning(delHtml);
29153			
29154			if (GLO.Info.isMobile()) {
29155				var jpop = ojpop.getPopup().css({ "width": "98%", "max-width": "100%" });
29156				jpop.find('.msg').css({ "padding-right": "2px" });
29157				ojpop.realign();
29158			}
29159    	}
29160    	
29161    	GLO.Inventory.shipment = undefined;
29162    }
29163
29164    _conIRestock.newProduct = function() {
29165        var url = document.location.protocol + '//' + document.location.host + '/provider/inventory/#action=new-product';
29166        var childWindow = UI.openChildWindow(url, '', true);
29167    }
29168    
29169    _conIRestock.hideRow = function(me) {
29170        GLO.Inventory.hideRow( $(me).closest('tr') );
29171        $('#inventory-restock-edit-buttons:visible').find('.btnSave a:visible').css({ "border": "3px solid Red" });
29172        GLO.Inventory.setFooter(1);
29173    }
29174
29175    /*
29176    _conIRestock.reload = function() {
29177        $('#inventory-table tbody tr').each(function() {
29178            $(this).removeClass('hide');
29179        });
29180    }
29181    
29182    _conIRestock.addProduct = function() {             // => pops up simple modal w/ inventory auto-complete box (containing all hiden products).
29183        
29184    }
29185    */
29186
29187    _conIRestock.editCost = function(element, event) {
29188        GLO.Inventory.setFooter(1);
29189    }
29190
29191    _conIRestock.editCount = function(element, event) {
29192        var me = $(element);
29193        var nr = parseFloat(me.val());
29194        var jtd = me.closest('td');
29195        var jtr = jtd.closest('tr');
29196        var jocnt = jtr.find('.item-order-count input');
29197        var ocnt = UTIL.coalesceInt(jocnt.val());
29198        
29199        if (jocnt.is(":visible") || !isNaN(ocnt)) {
29200        	if (ocnt > nr) {
29201        		jtr.addClass('unfilled');
29202        	} else {
29203        		jtr.removeClass('unfilled');
29204        	}
29205        }
29206        
29207        if (nr < 0) {
29208            jtd.find('.inventory-in-stock-plus').text('-');
29209        } else {
29210            jtd.find('.inventory-in-stock-plus').text('+');
29211        }
29212
29213        nr = UTIL.coalesceFloat(jtd.find('.current-in-stock').text(), 0) + UTIL.coalesceFloat(nr, 0);
29214        nr = UTIL.roundMoney(nr);
29215        var orderType = GLO.Inventory.getOrderType();
29216        
29217        if (orderType === 2) { nr = '[ ' + nr + ' ]'; }
29218        jtd.find('.new-in-stock-total').text(nr);
29219        
29220        GLO.Inventory.setFooter(orderType);
29221    }
29222
29223    /*
29224    _conIRestock.addNote = function() {
29225        var jnote = $('#shipment-detail-header:visible').find('#edit-shipment-note');
29226        
29227        if (jnote.length === 1) {
29228            var note = jnote.text();
29229        } else {
29230            var note = $('#inventory-header-action-container').find('#Shipment_Note_vc').text();
29231        }
29232
29233        GLO.Popup.Prompt('Shipment Note', GLO.Inventory.Restock.saveNote, null, note);
29234    }
29235
29236    _conIRestock.saveNote = function(note) {
29237        var jnote = $('#shipment-detail-header:visible').find('#edit-shipment-note');
29238
29239        if (jnote.length === 1) {
29240            jnote.text(note);
29241        }
29242
29243        $('#inventory-header-action-container').find('#Shipment_Note_vc').text(note);
29244        return true;
29245    }
29246    */
29247
29248    _conIRestock.getShipmentId = function() {
29249        //var shipmentId = $('#inventory-header-action-container').find('#Shipment_id').val();
29250        //if (UTIL.isEmpty(shipmentId)) { shipmentId = GLO.Uri.url('id'); }
29251
29252        return GLO.Uri.url('id');
29253    }
29254
29255    _conIRestock.remove = function(deleteButton) {
29256        var shipmentId = _conIRestock.getShipmentId();
29257        var msg = SA.Resource.DeleteShipmentConfirm;
29258
29259        GLO.Popup.Confirm(msg, function() {
29260            GLO.Inventory.Restock.removeConfirmed(deleteButton, shipmentId);
29261        });
29262    }
29263
29264    _conIRestock.removeConfirmed = function(deleteButton, shipmentId) {
29265        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ShipmentDelete';
29266        GLO.UI.Form.beginProcessing( $(deleteButton).parent() );
29267
29268        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Shipment_id": shipmentId } })
29269            .success(function(data, textStatus, jqXHR) {
29270                if (UTIL.Validate.hasPermissionError(data)) { return; }
29271                
29272                GLO.Inventory.Restock.back();
29273            })
29274            .error(function(jqXHR, textStatus, errorThrown) {
29275                new GLO.Popup.Error('Unable to delete the order at this time.  Please try again later.');
29276                GLO.UI.Form.resetProcessing();
29277            });
29278    }
29279
29280    _conIRestock.save = function(isPrinting, isOrder, isDelete, isEmail) {
29281        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Restock';
29282        var jrows = $('#inventory-table tbody tr:visible');
29283        var ocount, updStock, updCount = 0, restockXml = '', totalCount, useCount = false;
29284        
29285        var otype = GLO.Inventory.getOrderType();
29286        
29287        if (otype < 3 && jrows.eq(0).find('.item-order-count:visible').length == 0) {
29288        	useCount =  true;
29289        } else if (otype === 200) {
29290        	GLO.Inventory.Audit.save(jrows);
29291        	return;
29292        }
29293        
29294        for (var i=0; i < jrows.length; i++) {
29295            updStock = coalesceStringNumber(jrows.eq(i).find('.item-in-stock-edit input').val());
29296            
29297            if (useCount) {
29298            	ocount = updStock;
29299            } else {
29300            	ocount = coalesceStringNumber(jrows.eq(i).find('.item-order-count input').val());
29301            }
29302            
29303            if (updStock != 0 || ocount != 0) {
29304                totalCount = coalesceStringNumber(jrows.eq(i).find('.new-in-stock-total').text()).replace('(', '').replace(')', '');
29305
29306                restockXml += '<tr inventory_id="' + jrows.eq(i).attr('id') + '" track_stock_fl="' + jrows.eq(i).attr('track_stock_fl') 
29307                			+ '" cost_mn="' + coalesceStringNumber(jrows.eq(i).find('.item-cost-edit input').val())
29308                            + '" order_count_nr="' + ocount + '" count_dr="' + updStock + '" total_dr="' + totalCount + '"/>';
29309                ++updCount;
29310            }
29311        }
29312        
29313        if (jrows.length === 0) {
29314        	GLO.Popup.Warning(SA.Resource.EmptyOrderWarning);
29315            return;
29316        } else if (restockXml === '') {
29317        	GLO.Popup.Warning(SA.Resource.EmptyOrderWarning2);
29318            return;
29319        }
29320        
29321        var restockEncodedXml = UTIL.htmlEncode(restockXml);
29322        var jHead = $('#inventory-header-action-container');
29323        var shipmentId = _conIRestock.getShipmentId();
29324        var shipmentName = jHead.find('#Shipment_Name_vc').val();
29325        var note = UTIL.htmlEncode(jHead.find('#Shipment_Note_vc:visible').val());          //, #Order_Note_vc:visible
29326        
29327        var jlocation = jHead.find('#order-editable-fields');
29328        var locationId = jlocation.find('#Location_id').val(), isle = jlocation.find('#Isle_vc').val(), shelf = jlocation.find('#Shelf_vc').val(), rack = jlocation.find('#Rack_vc').val();
29329        
29330        var vid = '', did = '', co = jHead.find('#Filter_Company').val();
29331        
29332        if (!UTIL.isEmpty(co)) {
29333            if (co.substring(0, 1) === 'v') {
29334                vid = co.substring(1);
29335            } else if (co.substring(0, 1) === 'd') {
29336                did = co.substring(1);
29337            } else if (co.substring(0, 1) === 'p') {
29338                vid = $('select#Product_Line_id option[value="' + co.substring(1) + '"]').attr('vendor_id');
29339            }
29340        }
29341
29342        var saveBtn = jHead.find('.btnSave:visible');
29343        GLO.UI.Form.beginProcessing( saveBtn );
29344
29345        var jsdata = {
29346        	"Shipment_id": shipmentId, "Shipment_Name_vc": shipmentName, "Note_vc": note, "Vendor_id": vid, "Distributor_id": did
29347        		, "Location_id": locationId, "Isle_vc": isle, "Shelf_vc": shelf, "Rack_vc": rack
29348        		, "Restock_xml": restockEncodedXml
29349        };
29350        
29351        var orderType = 1;
29352        var jAutoOrdering = jHead.find('#inventory-automatic-ordering:visible');
29353        var jOrderDates = jHead.find('#inventory-order-dates:visible');
29354
29355        if (jAutoOrdering.length === 1) {
29356            orderType = 10;
29357
29358            if (jAutoOrdering.find('#auto_ordering_last_order_fl').prop('checked')) {
29359                orderType = 11;
29360            }
29361
29362            if (jAutoOrdering.find('#auto_ordering_dates_fl').prop('checked')) {
29363                if (orderType === 11) {
29364                    orderType = 21;
29365                } else {
29366                    orderType = 12;
29367                }
29368
29369                jsdata["Order_Auto_Start_dt"] = jAutoOrdering.find('#auto_start_dt').val();
29370                jsdata["Order_Auto_End_dt"] = jAutoOrdering.find('#auto_end_dt').val();
29371            }
29372
29373            if (jAutoOrdering.find('#auto_ordering_minimum_fl').prop('checked')) {
29374                if (orderType === 11) {
29375                    orderType = 23;
29376                } else if (orderType === 21) {
29377                    orderType = 22;
29378                } else if (orderType === 12) {
29379                    orderType = 24;
29380                } else {
29381                    orderType = 13;
29382                }
29383
29384                jsdata["Order_Min_Stock_pct"] = jAutoOrdering.find('#minimum_pct').val();
29385            }
29386        } else if (jOrderDates.length === 1) {
29387            jsdata["Order_dt"] = jHead.find('#Order_dt').val();
29388            jsdata["Order_Received_dt"] = jHead.find('#Order_Received_dt').val();
29389            //jsdata["Stock_dt"] = jHead.find('#Stock_dt').val();
29390
29391            if (UTIL.isDate(jsdata["Order_Received_dt"])) {
29392                orderType = 4;
29393            } else {
29394                orderType = 2;
29395            }
29396        }
29397
29398        jsdata["Order_Type_cd"] = orderType;
29399
29400        if (isPrinting) {
29401            jsdata["Order_Printed_fl"] = "1";
29402        }
29403        
29404        if (isDelete) { jsdata["Is_Delete_fl"] = "1"; }
29405
29406        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsdata })
29407            .success(function(data, textStatus, jqXHR) {
29408                if (UTIL.Validate.hasPermissionError(data)) { return; }
29409                
29410                var tbody = $(data);
29411                
29412                if (isDelete) {
29413                	GLO.Inventory.Order.back();
29414                } else if (UTIL.isEmpty(shipmentId) && UTIL.coalesceInt(otype, 0) < 3) {
29415					var shipmentId = $(data).attr('shipment_id');
29416					
29417					if (!UTIL.isEmpty(shipmentId)) {
29418						GLO.Inventory.updateHash('order', shipmentId, 'order-list');
29419					}
29420				}
29421                
29422                /*
29423                if (orderType < 5) {
29424                    location.reload();      //toDo (low priority): later --> don't do a refresh; instead just update the rows.
29425                    return;
29426                }
29427                */
29428                var tr, tbl = $('#inventory-table tbody');
29429                var trs = tbody.find('tr');						//var trs = $('<table>' + restockXml + '</table>').find('tr');
29430                
29431                for (var j=0; j < trs.length; j++) {
29432                    tr = tbl.find('tr#' + trs.eq(j).attr('inventory_id'));
29433                    _conIRestock.updateLineItem(tr, trs.eq(j).attr('in_stock_dr'), trs.eq(j).attr('cost_mn'));
29434                    
29435                    trs.eq(j).html('<td>' + tr.find('.item-name').text() + '</td>');
29436                }
29437                
29438                if (orderType !== 1 && orderType !== 4) {		//= if unreceived order need to reset row's total count.
29439                	var resetRows = tbl.find('tr:visible .item-in-stock-edit input');
29440                	
29441                	for (var r=0; r < resetRows.length; r++) {
29442                		resetRows.eq(r).change();
29443                	}
29444                }
29445	            
29446	            _orderUpdateSuccessMessage(orderType, trs, updCount);
29447	            saveBtn.find('a').css({ "border": "3px solid transparent" });
29448	            
29449                if (UTIL.isEmpty(shipmentId)) {
29450                    shipmentId = tbody.attr('shipment_id');              //var currid = jHead.find('#Shipment_id').val();            //jHead.find('#Shipment_id').val(shipmentId);
29451                    
29452                    if (isOrder) {
29453                        if ($('#inventory-automatic-ordering:visible').length === 1) {
29454                            $('#inventory-automatic-ordering:visible').addClass('hide');
29455                            $('#inventory-order-dates').removeClass('hide');
29456                        }
29457                    }
29458                    
29459                    if (isEmail) {
29460                    	GLO.Inventory.updateHash('order', shipmentId, '', 'email');      //GLO.Inventory.updateHash('restock', shipmentId);
29461                    }
29462                } else if (isEmail) {
29463                	GLO.Inventory.Order.email(true);
29464                }
29465            })
29466            .error(function(jqXHR, textStatus, errorThrown) {
29467                if (isDelete) {
29468                	new GLO.Popup.Error('Unable to delete the order.  Please try again later.');
29469                } else {
29470                	new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
29471                }
29472                
29473                GLO.UI.Form.resetProcessing();
29474            });
29475    }
29476    
29477    function _orderUpdateSuccessMessage(orderType, trs, updCount) {
29478    	if (orderType === 0 || orderType === 2 || orderType >  9) {
29479    		new GLO.Popup.Success(updCount + ' ' + SA.Resource.ProductsUpdated.toLowerCase());
29480    	} else {
29481	    	var h1 = '<h1 style="margin-bottom: 0; letter-spacing: 1px;">' + SA.Resource.StockUpdatedSuccessfully + '</h1>';
29482	    	var msg = '<div style="margin-bottom: 20px; line-height: 200%; font-size: 150%; letter-spacing: 1px;">' + SA.Resource.NewStockTotals + '</div>';
29483	    	var htm = '<table style="width: 100%;"> <thead> <tr> <th>' + SA.Resource.Product + '</th> <th>' + SA.Resource.InStock + '</th> <th>' + SA.Resource.Cost + '</th> </tr> </thead> <tbody>';
29484	    	
29485	    	for (var i=0; i < trs.length; i++) {
29486	    		htm += '<tr> <td>' + trs.eq(i).text() + '</td> <td>' + trs.eq(i).attr('in_stock_dr') + '</td> <td style="white-space: nowrap;">$ ' + trs.eq(i).attr('cost_mn') + '</td> </tr>';
29487	    	}
29488	    	
29489	    	var css = { "padding-left": "0" };
29490	    	
29491	    	if (!GLO.Info.isMobile()) {
29492	    		css["max-height"] = (window.innerHeight - 200);
29493	    		css.overflow = "auto";
29494	    	}
29495	    	
29496	    	htm = '<div id="pop-info-new-stock-totals">' + h1 + msg + htm + '</tbody> </table> </div>';
29497	    	var ojpop = new GLO.Popup.Info(htm);
29498	    	var jpop = ojpop.getPopup();
29499	    	jpop.find('.pop-icon').remove();						//jpop.css({ "background-image": "none" });
29500	    	jpop.find('.msg').css(css);
29501	    	ojpop.realign();
29502	    }
29503    }
29504    
29505    _conIRestock.updateLineItem = function(tr, stock, cost) {
29506    	if (!UTIL.isEmpty(cost)) { cost = '$' + cost; }
29507    	
29508    	tr.find('.item-cost').text(cost).attr('title', '');
29509    	tr.find('.item-cost-edit').attr('title', '');
29510    	
29511		//tr.find('.current-in-stock').text(stockNew);
29512		tr.find('.new-in-stock-total').text(stock);
29513		tr.find('.item-in-stock').text(stock);
29514    }
29515    
29516    _conIRestock.DEL_updateLineItem = function(tr) {
29517    	var costNew = UTIL.coalesceFloat(tr.find('.item-cost-edit input').val(), 0);
29518    	var stockNew = UTIL.coalesceFloat(tr.find('.item-in-stock-edit input').val(), 0);
29519    	
29520    	var costCurr = UTIL.coalesceFloat(tr.find('.item-cost').text().replace('$', ''), 0);
29521    	var stockCurr = UTIL.coalesceFloat(tr.find('.item-in-stock').text(), 0);
29522    	
29523    	costNew = (costCurr * stockCurr + costNew * stockNew) / (stockCurr + stockNew);
29524    	
29525    	if (isNaN(costNew) || costNew == 0) {
29526    		costNew = '';
29527    	} else {
29528    		costNew = '$' + UTIL.roundMoney(costNew);
29529    	}
29530    	
29531    	stockNew = UTIL.roundMoney(stockCurr + stockNew);
29532    	
29533    	tr.find('.item-cost').text(costNew).attr('title', '');
29534    	tr.find('.item-cost-edit').attr('title', '');
29535    	
29536		//tr.find('.current-in-stock').text(stockNew);
29537		tr.find('.new-in-stock-total').text(stockNew);
29538		tr.find('.item-in-stock').text(stockNew);
29539    }
29540    
29541    function coalesceStringNumber(val) {
29542        if (UTIL.isNumber(val)) {
29543            return val;
29544        } else {
29545            return '0';
29546        }
29547    }
29548
29549    return _conIRestock;
29550})();
29551
29552GLO.Inventory.Audit = (function() {
29553    function _conIAudit() { }
29554    
29555    _conIAudit.rowEdit = function(thisElement, event) {
29556    	GLO.Inventory.setFooter(200);
29557    }
29558    
29559    function _displayAllRows() {
29560    	var MAX_ROWS = 100		//= if less than 100 products -> display all products by default.
29561    	var pcount = $('#inventory-table').find('tbody > tr').length;
29562        
29563        if (pcount < MAX_ROWS) {
29564        	var jco = $('#inventory-header-filter #Filter_Company');
29565        	jco.val('').change();
29566        }
29567    }
29568    
29569    _conIAudit.openEdit = function(id) {
29570        if (UTIL.isEmpty(id) || (GLO.Inventory.shipment && GLO.Inventory.shipment.length && GLO.Inventory.shipment.id == id) ) {
29571            GLO.Inventory.Restock.openEdit(id, 200);
29572            _displayAllRows();
29573            
29574            return;
29575        }
29576		
29577        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Order?id=' + id + '&isAudit=1';
29578        
29579        $('#inventory-header-help-icon').removeClass('hide');
29580        $('#inventory-search-results').addClass('processing');                          //GLO.UI.Form.beginProcessing(frm.find('.btnSave'));
29581        $('.inventory-header').after('<div id="inventory-temporary-throbber" style="width: 100px; margin: auto;">' + $('.loadingDiv').clone().find('img').css({"margin": "50px auto"}).outerHTML() + '</div>')
29582        
29583        var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
29584            .success(function(data, textStatus, jqXHR) {
29585                $('#inventory-search-results').addClass('hide').removeClass('processing');               //GLO.UI.Form.resetProcessing();
29586                $('#inventory-temporary-throbber').remove();
29587                $('#inventory-table').removeClass('hide');
29588                
29589                var ul = $(data);
29590                var li = ul.find('li');
29591                var dt, cnt, obj, arr = [];
29592                
29593                for (var i=0; i < li.length; i++) {
29594                    obj = { "inventory_id": li.eq(i).attr('inventory_id'), "actual_dr": li.eq(i).attr('actual_dr') };
29595                    
29596                    if (li.eq(i).attr('name_vc')) {
29597                    	obj.name_vc = li.eq(i).attr('name_vc');
29598                    	obj.vendor_name_vc = li.eq(i).attr('vendor_name_vc');
29599                    	obj.size_dr = li.eq(i).attr('size_dr');
29600                    	obj.unit_abbreviation = li.eq(i).attr('unit_abbreviation');
29601	                    obj.type_name_vc = li.eq(i).attr('type_name_vc')
29602	                    obj.type_category_name_vc = li.eq(i).attr('type_category_name_vc');
29603                    }
29604                    
29605                    arr.push(obj);
29606                }
29607                
29608                GLO.Inventory.shipment = arr;
29609                
29610        		var note = ul.text();
29611                GLO.Inventory.Restock.openEdit(id, 200, note);
29612            })
29613            .error(function(jqXHR, textStatus, errorThrown) {
29614                //new GLO.Popup.Error('Unable to open at this time.  Please try again later.');
29615                $('#inventory-search-results').removeClass('processing');               //GLO.UI.Form.resetProcessing();
29616            });
29617    }
29618    
29619    _conIAudit.save = function(jrows) {
29620    	var uri = GLO.Link.Page.Provider.Home + 'Inventory/Audit';
29621    	var updCount = 0, xml = '', row, expected, actual, diff;
29622        
29623        for (var i=0; i < jrows.length; i++) {
29624            row = jrows.eq(i);
29625            actual = row.find('.item-audit input').val();
29626            
29627            if (UTIL.isNumber(actual)) {
29628            	expected = row.find('.item-in-stock').text();
29629            	diff = row.find('.item-audit-diff').text().replace('+', '');
29630                
29631                if (UTIL.isEmpty(expected)) { expected = '0'; }
29632                if (UTIL.isEmpty(diff)) { diff = '0'; }
29633                
29634                xml += '<tr inventory_id="' + row.attr('id') + '" expected_dr="' + expected + '" actual_dr="' + actual + '" diff_dr="' + diff + '"/>';
29635                ++updCount;
29636            }
29637        }
29638        
29639        if (jrows.length === 0) {
29640        	GLO.Popup.Warning(SA.Resource.InventoryAuditEmptyWarning);
29641            return;
29642        } else if (xml === '') {
29643        	GLO.Popup.Warning(SA.Resource.InventoryAuditEmptyWarning2);
29644            return;
29645        }
29646        
29647        var jHead = $('#inventory-header-action-container');
29648		var note = jHead.find('#Shipment_Note_vc:visible').val();
29649		var jsdata = GLO.Inventory.Vendor.getSelected(jHead);
29650		
29651		var shipmentId = GLO.Uri.hash('id');
29652		if (!UTIL.isEmpty(shipmentId)) { jsdata["Shipment_id"] = shipmentId; }
29653		
29654		jsdata["Note_vc"] = UTIL.htmlEncode(note);
29655		jsdata["Restock_xml"] = UTIL.htmlEncode(xml);
29656		
29657		var saveBtn = jHead.find('.btnSave:visible');
29658        GLO.UI.Form.beginProcessing( saveBtn );
29659        
29660        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsdata })
29661            .success(function(data, textStatus, jqXHR) {
29662                if (UTIL.Validate.hasPermissionError(data)) { return; }
29663                
29664                new GLO.Popup.Success(updCount + ' ' + SA.Resource.ProductsUpdated.toLowerCase());
29665                
29666                //GLO.Inventory.updateHash('audit', $(data).attr('shipment_id'));
29667                document.location = document.location.protocol + '//' + document.location.host + '/provider/inventory';
29668            })
29669            .error(function(jqXHR, textStatus, errorThrown) {
29670                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
29671                GLO.UI.Form.resetProcessing();
29672            });
29673    }
29674    
29675	return _conIAudit;
29676})();
29677
29678
29679GLO.Inventory.Order = (function() {
29680    function _conIOrder() { }
29681    
29682    function _displayPopulatedOrder(id) {
29683    	var createDate = GLO.Inventory.shipment.create_dt;
29684		var orderDate = GLO.Inventory.shipment.submit_dt;
29685		var receiveDate = GLO.Inventory.shipment.received_dt;
29686		var stockDate = GLO.Inventory.shipment.stock_dt;
29687		
29688		var vid = GLO.Inventory.shipment.vendor_id;
29689		var did = GLO.Inventory.shipment.distributor_id
29690		
29691		var orderType = _conIOrder.populateHeaderAndReturnOrderType(createDate, orderDate, receiveDate, stockDate
29692								, GLO.Inventory.shipment.create_by_staff_vc, GLO.Inventory.shipment.update_by_staff_vc, GLO.Inventory.shipment.update_dt
29693								, vid, did);
29694    	
29695    	var note = GLO.Inventory.shipment.note.replace('<br/>', '\n');
29696    	
29697    	_populateLocationByShipment();
29698    	GLO.Inventory.Restock.openEdit(id, orderType, note);
29699    }
29700    
29701    function _resetSaveButton() {
29702    	var j = $('#inventory-order-dates-buttons');
29703    	j.find('#btn-order-update-stock').addClass('hide');
29704    	j.find('#btn-order-save').removeClass('hide');
29705    }
29706    
29707    _conIOrder.openEdit = function(id) {
29708        _resetSaveButton();
29709        $('#inventory-header-help-icon').removeClass('hide');
29710        
29711        if (UTIL.isEmpty(id)) {
29712            GLO.Inventory.Restock.openEdit(id, 2);
29713            return;
29714        } else if (GLO.Inventory.shipment && GLO.Inventory.shipment.length && GLO.Inventory.shipment.id == id) {
29715        	_displayPopulatedOrder(id);
29716        	return;
29717        }
29718		
29719        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Order?id=' + id;
29720        
29721        $('#inventory-search-results').addClass('processing');                          //GLO.UI.Form.beginProcessing(frm.find('.btnSave'));
29722        $('.inventory-header').after('<div id="inventory-temporary-throbber" style="width: 100px; margin: auto;">' + $('.loadingDiv').clone().find('img').css({"margin": "50px auto"}).outerHTML() + '</div>')
29723
29724        var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
29725            .success(function(data, textStatus, jqXHR) {
29726                $('#inventory-search-results').addClass('hide').removeClass('processing');               //GLO.UI.Form.resetProcessing();
29727                $('#inventory-temporary-throbber').remove();
29728                
29729                $('#inventory-order-list-buttons').addClass('hide');
29730                $('#inventory-table').removeClass('hide');
29731                
29732                var ul = $(data);
29733                var li = ul.find('li');
29734                var dt, cnt, obj, arr = [];
29735                
29736                for (var i=0; i < li.length; i++) {
29737                    cnt = UTIL.coalesceInt(li.eq(i).attr('count_dr'), li.eq(i).attr('order_count_nr'));
29738                    
29739                    obj = { "event_id": li.eq(i).attr('event_id'), "inventory_id": li.eq(i).attr('inventory_id')
29740	                		, "count_dr": cnt, "cost_mn": li.eq(i).attr('cost_mn'), "order_count_nr": li.eq(i).attr('order_count_nr') };
29741                    
29742                    if (li.eq(i).attr('name_vc')) {
29743                    	obj.name_vc = li.eq(i).attr('name_vc');
29744                    	obj.vendor_name_vc = li.eq(i).attr('vendor_name_vc');
29745                    	obj.size_dr = li.eq(i).attr('size_dr');
29746                    	obj.unit_abbreviation = li.eq(i).attr('unit_abbreviation');
29747	                    obj.type_name_vc = li.eq(i).attr('type_name_vc')
29748	                    obj.type_category_name_vc = li.eq(i).attr('type_category_name_vc');
29749                    }
29750                    
29751                    arr.push(obj);
29752                }
29753                
29754                var createDt = UTIL.cleanString(ul.attr('create_date'));
29755                var orderDt = ul.attr('order_dt');
29756                var receiveDt = ul.attr('order_received_dt');
29757                var stockDt = ul.attr('stock_dt');
29758                
29759                var orderType = _conIOrder.populateHeaderAndReturnOrderType(createDt, orderDt, receiveDt, stockDt
29760					                		, ul.attr('create_by_staff_vc'), ul.attr('update_by_staff_vc'), ul.attr('update_date')
29761					                		, ul.attr('vendor_id'), ul.attr('distributor_id'), ul.attr('vendor_name_vc'), ul.attr('distributor_name_vc'));
29762                _populateLocation(ul);
29763                
29764                GLO.Inventory.shipment = arr;
29765                GLO.Inventory.shipment.shipment_number_vc = ul.attr('shipment_number_vc');
29766                
29767        		var note = ul.text();
29768                GLO.Inventory.Restock.openEdit(id, orderType, note);
29769            })
29770            .error(function(jqXHR, textStatus, errorThrown) {
29771                //new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
29772                $('#inventory-search-results').removeClass('processing');               //GLO.UI.Form.resetProcessing();
29773            });
29774    }
29775    function _populateLocation(ul) {
29776    	var j = $('#order-editable-fields');
29777    	var locationId = ul.attr('location_id'), isle = UTIL.cleanString(ul.attr('isle_vc')), shelf = UTIL.cleanString(ul.attr('shelf_vc')), rack = UTIL.cleanString(ul.attr('rack_vc'));
29778    	
29779    	j.find('#Location_id').val(locationId);
29780    	j.find('#Isle_vc').val(isle);
29781    	j.find('#Shelf_vc').val(shelf);
29782    	j.find('#Rack_vc').val(rack);
29783    }
29784    function _populateLocationByShipment() {
29785    	var j = $('#order-editable-fields');
29786    	var locationId = GLO.Inventory.shipment.location_id, isle = UTIL.cleanString(GLO.Inventory.shipment.isle_vc);
29787    	var shelf = UTIL.cleanString(GLO.Inventory.shipment.shelf_vc), rack = UTIL.cleanString(GLO.Inventory.shipment.rack_vc);
29788    	
29789    	j.find('#Location_id').val(locationId);
29790    	j.find('#Isle_vc').val(isle);
29791    	j.find('#Shelf_vc').val(shelf);
29792    	j.find('#Rack_vc').val(rack);
29793    }
29794    _conIOrder.populateHeaderAndReturnOrderType = function(createDate, orderDate, receiveDate, stockDate
29795    														, createBy, updateBy, updateDate
29796    														, vendorId, distributorId, vendorName, distributorName) {
29797    	var jHead = $('#inventory-header-action-container');
29798        //jHead.find('#Shipment_Note_vc').val( UTIL.cleanString(ul.text()) );
29799		
29800		createBy = ' ' + SA.Resource.CreatedBy + ': ' + createBy;
29801		if (!UTIL.isEmpty(updateBy)) { createBy += '\x0A' + SA.Resource.UpdatedBy + ': ' + updateBy + ' ' + SA.Resource.on_text + ' ' + updateDate; }
29802		
29803        jHead.find('#Order_Create_Date').attr('title', createBy).text(createDate);
29804
29805        if (UTIL.isDate(orderDate)) { orderDate = new Date(orderDate).toGloDate(); } else { orderDate = ''; }
29806        jHead.find('#Order_dt').val(orderDate);
29807
29808        if (UTIL.isDate(receiveDate)) {
29809            receiveDate = new Date(receiveDate).toGloDate();
29810            var orderType = 4;
29811        } else {
29812            receiveDate = '';
29813            var orderType = 2;
29814        }
29815        
29816        jHead.find('#Order_Received_dt').attr('original_value', receiveDate).val(receiveDate);
29817        jHead.find('#Stock_dt').text( UTIL.cleanString(stockDate) );
29818        
29819        //var jCompanies = $('#Filter_Company');
29820        //if (!UTIL.isEmpty(did)) { var dnm = jCompanies.val('option[value="d' + did + '"]').attr('value'); }
29821        //if (!UTIL.isEmpty(vid)) { var vnm = jCompanies.val('option[value="v' + vid + '"]').attr('value'); }
29822        
29823        return orderType;
29824    }
29825    
29826    _conIOrder.openList = function() {      		//= for order received.
29827        var start = new Date();
29828        var end = new Date(start.getFullYear(), start.getMonth(), start.getDate() + 1);
29829        start.setMonth(start.getMonth() - 3);
29830        
29831        var uhash = 'onlyopenorders=1&start=' + start + '&end=' + end;
29832
29833        //document.location.hash = uhash;
29834        //try { window.history.pushState("", "Inventory-Report", url); } catch (e) { }
29835
29836        var url = GLO.Link.Page.Provider.Home + 'report/ShipmentHistory?' + uhash;
29837        GLO.UI.Form.beginProcessing( $('#button-order-received') );
29838
29839        $('#inventory-table, #inventory-header-filter').addClass('hide');
29840        $('#inventory-order-list-buttons, #manage-inventory').removeClass('hide');
29841        $('#inventory-header-help-icon').removeClass('hide');
29842        
29843        var throbber = $('<div style="text-align: center;">' + $('.loadingDiv').clone().find('img').css({"margin": "150px auto"}).outerHTML() + '</div>');
29844        $('#inventory-search-results').removeClass('hide').html(throbber);
29845
29846        $('h2.inventory-header #inventory-header-text').text(SA.Resource.UnfilledOrders);
29847        var w = GLO.Inventory.docWidth + 'px';
29848        //$('#doc3').css({ "width": w });
29849        
29850        SA.Help.display('fill-order');
29851        
29852        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
29853            .success(function(data, textStatus, jqXHR) {
29854                GLO.UI.Form.resetProcessing();
29855                
29856                if (!UTIL.isEmpty(data)) {
29857                    $('#inventory-search-results:visible').html(data);
29858                    
29859                    var tbl = $('#inventory-search-results:visible').find('table.tablesorter:visible');
29860                    UI.initTableSorter(tbl);
29861                } else {
29862                    GLO.Popup.Info(SA.Resource.NoUnfilledOrderMessage);
29863                }
29864            })
29865            .error(function(jqXHR, textStatus, errorThrown) {
29866                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
29867                GLO.UI.Form.resetProcessing();
29868            });
29869    }
29870	
29871    _conIOrder.back = function() {
29872    	if (!GLO.Inventory.backViaUri()) {
29873	        if (GLO.Inventory.filterIsEmpty()) {
29874	        	GLO.Inventory.updateHash('product-list-intro');
29875	        } else {
29876	        	GLO.Inventory.updateHash('product-list');
29877    		}
29878    	}
29879    }
29880
29881    _conIOrder.dateChange = function(inputField) {      //inputField = #Order_Received_dt
29882        var jtbl = $('#inventory-table');
29883        var orderId = $('#inventory-order-header #Order_id').val();
29884        
29885        if (UTIL.isDate(inputField.value)) {
29886            //$('#inventory-order-disclaimer, #inventory-order-dates-buttons').addClass('hide');
29887            //$('#inventory-restock-edit-buttons').removeClass('hide');
29888            
29889            var jbtns = $('#inventory-order-dates-buttons');
29890			jbtns.find('.btnSave').addClass('hide');
29891			jbtns.find('#btn-order-update-stock').removeClass('hide');
29892            
29893            var jStockDate = $('#inventory-order-dates #Stock_dt');
29894            
29895            if (UTIL.isEmpty(jStockDate.text())) {
29896                var dtOR = $(inputField);
29897
29898                if (!UTIL.isEmpty(dtOR.attr('original_value'))) {
29899                    var dtStock = dtOR.attr('original_value');
29900                } else {
29901                    var dtStock = new Date();
29902                    dtStock = dtStock.getMonthString(true) + ' ' + dtStock.getDate() + ' @ ' + dtStock.toGloTime();
29903                }
29904
29905                jStockDate.text(dtStock);
29906            }
29907            
29908            $('#inventory-table tbody tr').each(function() {
29909				var me = $(this);
29910            	var ocount = me.find('.item-order-count input');
29911            	
29912            	if (UTIL.isEmpty(ocount.val())) {
29913            		ocount.val( me.find('.item-in-stock-edit input').val() );
29914            	}
29915        	});
29916            
29917            var orderType = 4;
29918            GLO.Inventory.displayColumns(orderType, jtbl, orderId);
29919        } else {
29920            //$('#inventory-order-disclaimer, #inventory-order-dates-buttons').removeClass('hide');
29921            //$('#inventory-restock-edit-buttons').addClass('hide');
29922            
29923            var jbtns = $('#inventory-order-dates-buttons');
29924			jbtns.find('#btn-order-update-stock').addClass('hide');
29925            jbtns.find('#btn-order-save').removeClass('hide');
29926			
29927            //if (!UTIL.isEmpty(dtOR.attr('original_value'))) { $('#inventory-order-dates #Stock_dt').text(''); }
29928            $('#inventory-order-dates #Stock_dt').text('');
29929            
29930            var orderType = 2;
29931            GLO.Inventory.displayColumns(orderType, jtbl, orderId);
29932        }
29933        
29934        GLO.Inventory.setFooter(orderType);
29935    }
29936    
29937    _conIOrder.generate = function(isOverride) {
29938        var jHead = $('#inventory-header-action-container');
29939        var jAutoOrdering = jHead.find('#inventory-order-header');
29940        var jsdata = {}, useDefault = true, co = jHead.find('#Filter_Company').val();
29941        var trOrder = $('#inventory-table > tbody > tr:visible');
29942        
29943        if (trOrder.length > 0 && !UTIL.parseBool(isOverride)) {
29944        	var msgConfirm = '<p>Remove ' + UTIL.pluralLabel(trOrder.length, 'order row') + ' below and generate new order?<
29944/p>';
29945        	var htmConfirm = '<div id="pop-confirm-generate-order">' + msgConfirm + '</div>';
29946        	var fnConfirm = function() { GLO.Inventory.Order.generate(true); };
29947        	
29948        	GLO.Popup.Confirm.open(htmConfirm, 'Remove Rows + Generate Order?', fnConfirm);
29949        	return;
29950        }
29951        
29952        jHead.find('#last_order_date').text('');
29953
29954        if (!UTIL.isEmpty(co)) {
29955            if (co.substring(0, 1) === 'v') {
29956                jsdata["vendor_id"] = co.substring(1);
29957            } else if (co.substring(0, 1) === 'd') {
29958                jsdata["distributor_id"] = co.substring(1);
29959            } else if (co.substring(0, 1) === 'p') {
29960                jsdata["vendor_id"] = $('select#Product_Line_id option[value="' + co.substring(1) + '"]').attr('vendor_id');
29961
29962                jHead.find('#Filter_Company').val('v' + jsdata["vendor_id"]);
29963                GLO.Inventory.filterOnChange(jHead);
29964            }
29965        }
29966
29967        if (jAutoOrdering.find('#auto_ordering_last_order_fl').prop('checked')) {
29968            jsdata["Since_Last_Order_fl"] = "1";
29969            useDefault = false;
29970        }
29971
29972        if (jAutoOrdering.find('#auto_ordering_dates_fl').prop('checked')) {
29973            jsdata["Start_dt"] = jAutoOrdering.find('#auto_start_dt').val();
29974            jsdata["End_dt"] = jAutoOrdering.find('#auto_end_dt').val();
29975            useDefault = false;
29976
29977            if (UTIL.isEmpty(jsdata["Start_dt"])) { 
29978                var st = new Date();
29979                st = new Date(st.setDate(st.getDate() - 14)).toGloDate();
29980                
29981                jsdata["Start_dt"] = st;
29982                jAutoOrdering.find('#auto_start_dt').val(st);
29983            }
29984
29985            if (UTIL.isEmpty(jsdata["End_dt"])) {
29986                jsdata["End_dt"] = new Date().toGloDate();
29987                jAutoOrdering.find('#auto_end_dt').val(jsdata["End_dt"]);
29988            }
29989        }
29990
29991        if (jAutoOrdering.find('#auto_ordering_minimum_fl').prop('checked')) {
29992            var minpct = jAutoOrdering.find('#minimum_pct').val();
29993            
29994            jsdata["Minimum_pct"] = UTIL.coalesce(minpct, 100);
29995            useDefault = false;
29996
29997            if (UTIL.isEmpty(minpct)) { jAutoOrdering.find('#minimum_pct').val(100); }
29998        }
29999
30000        if (useDefault) {
30001            jsdata["Since_Last_Order_fl"] = "1";
30002            jsdata["Minimum_pct"] = 100;
30003
30004            jAutoOrdering.find('#auto_ordering_last_order_fl').prop('checked', true);
30005            jAutoOrdering.find('#auto_ordering_minimum_fl').prop('checked', true);
30006            jAutoOrdering.find('#minimum_pct').val(100);
30007        }
30008
30009        var btn = jAutoOrdering.find('#inventory-automatic-order-button');
30010        GLO.UI.Form.beginProcessing(btn);
30011        var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderGenerate';
30012
30013        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsdata })
30014            .success(function(data, textStatus, jqXHR) {
30015                if (UTIL.Validate.hasPermissionError(data)) { return; }
30016                if ($('#inventory-automatic-ordering:visible').length === 0) { return; }
30017
30018                if (data) {
30019                    var li, ul = $(data);
30020
30021                    if (ul.attr('error_cd')) {
30022                        GLO.Popup.Warning(ul);
30023                    } else {
30024                        $('#inventory-table tbody tr').each(function() {
30025                            var me = $(this);
30026                            var rowId = me.attr('id');
30027                            li = ul.find('li[inventory_id="' + rowId + '"]');
30028
30029                            if (li.length === 1) {
30030                                me.removeClass('hide');
30031                                me.find('.item-in-stock-edit input').val(li.attr('amount_nr')).change();
30032                            } else {
30033                                me.addClass('hide');
30034                            }
30035                        });
30036                        
30037                        var lastOrderDt = ul.attr('last_order_dt');
30038                        if (!UTIL.isEmpty(lastOrderDt)) { $('#last_order_date').text(lastOrderDt); }
30039
30040                        GLO.Inventory.setFooter(2);
30041                    }
30042                }
30043            })
30044            .error(function(jqXHR, textStatus, errorThrown) {
30045                new GLO.Popup.Error('Unable to generate the order at this time.  Please try again later.');
30046                GLO.UI.Form.resetProcessing();
30047            });
30048        
30049    }
30050
30051    _conIOrder.remove = function(deleteButton) {
30052        var shipmentId = GLO.Inventory.Restock.getShipmentId();
30053        var msg = SA.Resource.DeleteOrderConfirm;
30054        deleteButton = $(deleteButton).parent();
30055
30056        GLO.Popup.Confirm(msg, function() {
30057            GLO.Inventory.Order.removeConfirmed(deleteButton, shipmentId);
30058        });
30059    }
30060
30061    _conIOrder.removeConfirmed = function(deleteButton, shipmentId) {
30062        var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderDelete';
30063        GLO.UI.Form.beginProcessing(deleteButton);
30064        
30065        if (GLO.Inventory.getOrderType() === 4) {
30066        	$('#Order_Received_dt').val('').change();
30067        	GLO.Inventory.Restock.save(false, true, true);
30068        	return;
30069        }
30070        
30071        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Shipment_id": shipmentId } })
30072            .success(function(data, textStatus, jqXHR) {
30073                if (UTIL.Validate.hasPermissionError(data)) { return; }
30074                
30075                GLO.Inventory.Order.back();
30076            })
30077            .error(function(jqXHR, textStatus, errorThrown) {
30078                new GLO.Popup.Error('Unable to delete the order at this time.  Please try again later.');
30079                GLO.UI.Form.resetProcessing();
30080            });
30081    }
30082	
30083	_conIOrder.email = function(wasSaved) {
30084		if (!wasSaved) {
30085			var saveButton = $('#inventory-header-action-container').find('.btnSave:visible');
30086			
30087			if (saveButton.length === 1 && saveButton.find('a').css("border-color").toLowerCase() === 'rgb(255, 0, 0)') {
30088				GLO.Inventory.Restock.save(false, true, false, true);
30089				return;
30090			} else if (UTIL.isEmpty(GLO.Inventory.Restock.getShipmentId())) {
30091				GLO.Inventory.Restock.save(false, true, false, true);
30092				return;
30093			}
30094		}
30095		
30096		var ddStaff = '<option>' + $('.staffDD:first').html() + '</option>';
30097		
30098		var div = $('<div id="email-order-popup">'
30099					+ '<h2>' + SA.Resource.EmailOrder + '</h2>'
30100					+ '<style id="pop-return-style"> .ui-autocomplete { z-index: 6000 !important; } </style>'
30101					+ '<div id="email-order-popup-container">'
30102						+ '<div id="email-order-row1">'
30103							+ '<label id="email-order-add-client-label" for="email-order-to-client"> <b>' + SA.Resource.SendTo + '</b> <span>( ' + SA.Resource.enter_client_name + ' )</span> </label>'
30104							+ '<input id="email-order-to-client" type="text" maxlength="100"/>'
30105							+ '<span id="email-order-add-client" style="white-space: nowrap;">( <a onclick="UserPortal.Create.addClientLink()" title="' + SA.Resource.AddNewClient + '">' + SA.Resource.AddClient.toLowerCase() + '</a> )</span>'
30106						+ '</div>'
30107						+ '<div id="email-order-row2">'
30108							+ '<label for="email-order-copy-staff"> <b>' + SA.Resource.CopyStaff + '</b> <span>( cc staff )</span></label>'
30109							+ '<select id="email-order-copy-staff" type="text">' + ddStaff + '</select>'
30110						+ '</div>'
30111						+ '<div id="email-order-row3a">'
30112							+ '<label for="email-order-include-note">' + SA.Resource.IncludeNoteInEmail + '</label>'
30113						+ '</div>'
30114						+ '<div id="email-order-row3b">'
30115							+ '<textarea id="email-order-include-note" style="width: 96%;"></textarea>'
30116						+ '</div>'
30117					+ '</div>'
30118				+ '</div>');
30119		
30120		var oj = GLO.Popup.Custom(div, GLO.Inventory.Order.emailConfirmed);
30121		var jpop = oj.getPopup();
30122		
30123		jpop.addClass('no-persist');
30124		jpop.find('h2').css({ "letter-spacing": "2px" });
30125		
30126		jpop.find('.pop-buttons').css({ "width": "300px", "margin": "auto", "margin-bottom": "8px" });
30127		jpop.find('.btnSave a').text('Send');
30128		//jpop.find('.btnCancel a').text(SA.Resource.Close);
30129		
30130		jpop.find('#email-order-to-client').autocomplete({
30131            minLength: 2, source: GLO.Link.Object.Provider.UserSearch + '?isorder=1',
30132            select: function(event, ui) {
30133                this.value = ui.item.value
30134                $('#email-order-popup').attr('client_id', ui.item.id);
30135            }
30136        });
30137        
30138        jpop.find('#email-order-copy-staff').val(GLO.Info.StaffId);
30139        
30140        var note = UTIL.coalesce($('#Shipment_Note_vc:visible').val(), $('#shipment-detail-header-note').text());
30141        jpop.find('#email-order-include-note').val(note);
30142	}
30143	
30144	_conIOrder.emailConfirmed = function(clientId) {
30145		var shipmentId =  $('#shipment-detail-header').attr('shipment_id');
30146		if (UTIL.isEmpty(shipmentId)) { shipmentId = GLO.Inventory.Restock.getShipmentId(); }
30147		
30148		var jpop = $('#email-order-popup');
30149		var cid = jpop.attr('client_id');
30150		var cname = jpop.find('#email-order-to-client').val();
30151		var sid = jpop.find('#email-order-copy-staff').val();
30152		var note = UTIL.replaceAll(UTIL.replaceAll(jpop.find('#email-order-include-note').val(), '<', ''), '>', '');
30153		
30154		if (UTIL.isEmpty(cid)) {
30155			GLO.Popup.Warning(SA.Resource.PleaseEnterClientName, function() { $('#email-order-popup').find('#email-order-to-client').focus(); });
30156			return;
30157		}
30158		
30159		var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderEmail';
30160        var emailBtn = $('#shipment-detail-header-buttons #btnEmail');
30161        
30162        GLO.UI.Form.beginProcessing(jpop.closest('.glopop').find('.btnSave'));
30163        
30164        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "shipment_id": shipmentId, "to_client_id": cid, "cc_staff_id": sid, "note_vc": note } })
30165            .success(function(data, textStatus, jqXHR) {
30166            	if (UTIL.Validate.hasPermissionError(data)) { return; }
30167            	
30168            	data = $(data);
30169            	
30170            	if (data.attr('error_cd') == '100') {
30171            		ClientProfile.goto(cid , 1, cname);
30172            		
30173            		var msg = cname  + ' ' + SA.Resource.EmailMissingWarning + ' ' + cname + '.';
30174            		GLO.Popup.Warning(msg, function() { $('#simplemodal-container').css({ "z-index": 9999 }); });
30175            	} else {
30176	            	var dt = new Date().toGloDate();
30177	                var j = $('#inventory-order-dates').find('#Order_dt');
30178	                
30179	                if (UTIL.isEmpty(j.val())) { j.val(dt); }
30180	                
30181	                GLO.UI.Form.resetProcessing();
30182	                GLO.Popup.close();
30183	                GLO.Popup.Success(SA.Resource.OrderEmailed);
30184                }
30185            })
30186            .error(function(jqXHR, textStatus, errorThrown) {
30187                var htm = '<p>There is a problem sending this order as an email</p> <p>Please wait a few minutes before sending this email</p>';
30188                GLO.Popup.Error.open(htm, 'Order Email Not Sent');
30189                GLO.UI.Form.resetProcessing();
30190            });
30191	}
30192	
30193    _conIOrder.printView = function() {
30194		var shipmentId =  $('#shipment-detail-header').attr('shipment_id');
30195		_savePrintDate(shipmentId);
30196		
30197		UI.Print.printOnDevice();
30198	}
30199	
30200    _conIOrder.print = function() {
30201        var dt = new Date();
30202        var sdt = dt.toGloDateString(true, true, true, true) + ' @ ' + dt.toGloTime();
30203        
30204        var jPrint = $('#print-order-only').addClass('print-only').removeClass('print-order-only');
30205        jPrint.find('#print-only-date-header').text(sdt);
30206        
30207        setTimeout(GLO.Inventory.Order.afterPrint, 450);
30208        UI.Print.printOnDevice();
30209        
30210        var shipmentId = GLO.Inventory.Restock.getShipmentId();
30211
30212        var jOrderDate = $('#inventory-order-dates').find('#Order_dt');
30213        if (!UTIL.isEmpty(jOrderDate.val())) { jOrderDate.val(dt.toGloDate()); }
30214        
30215        if (!UTIL.isEmpty(shipmentId)) {
30216            _savePrintDate(shipmentId);
30217        } else {
30218            GLO.Inventory.Restock.save(true, true);
30219        }
30220    }
30221	
30222	_conIOrder.afterPrint = function() {
30223		if (document.readyState == "complete") {
30224            $('#print-order-only').addClass('print-order-only').removeClass('print-only');
30225        } else {           
30226            setTimeout(GLO.Inventory.Order.afterPrint, 150);
30227        }
30228    }
30229	
30230    function _savePrintDate(shipmentId) {
30231        var uri = GLO.Link.Page.Provider.Home + 'Inventory/OrderPrinted';
30232        var printBtn = $('#inventory-order-print-button');
30233        GLO.UI.Form.beginProcessing(printBtn);
30234
30235        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Shipment_id": shipmentId } })
30236            .success(function(data, textStatus, jqXHR) {
30237            	if (UTIL.Validate.hasPermissionError(data)) { return; }
30238            	
30239            	var dt = new Date().toGloDate();
30240                var j = $('#inventory-order-dates').find('#Order_dt');
30241                
30242                if (UTIL.isEmpty(j.val())) { j.val(dt); }
30243            })
30244            .error(function(jqXHR, textStatus, errorThrown) {
30245                //new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
30246                GLO.UI.Form.resetProcessing();
30247            });
30248    }
30249
30250    _conIOrder.save = function() {
30251        GLO.Inventory.Restock.save(false, true);
30252    }
30253
30254    return _conIOrder;
30255})();
30256
30257
30258GLO.Inventory.Item = (function() {
30259    function _conIItem() { }
30260    var _lookingUpCostBasis = false;
30261    var _loadingCostPopup = false;
30262	var cropper = null;
30263	
30264    _conIItem.openViewPopup = function(id) {
30265        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemSummary?id=' + id + '&dt=' + UTIL.getDateString();      //var uri = GLO.Link.Page.Provider.Home + 'Inventory#action=view-product&id=' + id;           //UI.openChildWindow(uri, '', true);
30266        var throbber = $('<div style="text-align: center;">' + $('.loadingDiv').clone().find('img').css({"margin": "150px auto"}).outerHTML() + '</div>');
30267        
30268        var ojpop = new GLO.Popup.Custom(throbber, UserPortal.Price.productCommissionSet);
30269        jpop = ojpop.getPopup();            //.addClass('no-persist');
30270
30271        jpop.find('.pop-buttons-parent').remove();
30272        jpop.css({ "padding-left": "0", "padding-right": "0", "padding-top": "0" });
30273        
30274        var ocss = { "min-height": "100px", "min-width": "550px", "margin-left": "0", "margin-right": "0", "padding-top": "0", "padding-left": "0", "padding-right": "0" };
30275        
30276        if (GLO.Info.isMobile() && !GLO.Info.isLandscape()) { ocss["min-width"] = "320px"; }
30277        
30278        jpop.find('.msg').css(ocss).load(uri, function(responseText, textStatus, XMLHttpRequest) {
30279            if (GLO.Log.processesSecurityException(jpop, arguments[0], arguments[1], arguments[2])) { return; }
30280
30281            $('.msg').find('#product-summary-buttons-parent').removeClass('hide');		//.css({ "position": "", "margin-left": "", "margin": "auto", "margin-top": "30px", "width": "300px" });
30282            
30283            ojpop.realign();
30284        });
30285    }
30286
30287    _conIItem.back = function() {
30288        GLO.Inventory.updateHash('product-list');
30289    }
30290
30291    _conIItem.unHide = function() {
30292        if (GLO.Inventory.prevHash.indexOf('-list') !== -1) {
30293        	GLO.Inventory.updateHash(GLO.Inventory.prevHash, GLO.Inventory.prevHashId);
30294        } else if (GLO.Inventory.prevIsItem) {
30295			var id = UTIL.coalesce(GLO.Inventory.prevItemId, $('#inventory-item-edit #Inventory_id').val());
30296			
30297			if (!UTIL.isEmpty(id)) {
30298	            GLO.Inventory.updateHash('edit-product', id);
30299	        } else {
30300	            GLO.Inventory.updateHash('new-product', 0);
30301	        }
30302		} else if (GLO.Inventory.isProductListView(GLO.Inventory.prevHash)) {
30303        	GLO.Inventory.updateHash(GLO.Inventory.prevHash);
30304        } else {
30305        	GLO.Inventory.updateHash('product-list');
30306        }
30307    }
30308	
30309	_conIItem.openItem = function(id) {
30310		var jbtn = $(event.currentTarget);
30311		
30312		if ($('#manage-inventory').length && GLO.Inventory.isProductList) {
30313			_conIItem.click(event.currentTarget, id);
30314			
30315			setTimeout(function() {
30316				if ($('#inventory-item-summary').closest('#simplemodal-container').length) {
30317					$.modal.close();
30318				}
30319			}, 1100);
30320		} else {
30321			GLO.Uri.gotoUri('provider/inventory#action=view-product&id=' + id);
30322		}
30323		
30324		setTimeout(function() {
30325			GLO.UI.Form.beginProcessing(jbtn);
30326		}, 100);
30327	}
30328	
30329    _conIItem.click = function(element, id) {
30330        if (UTIL.isEmpty(id)) { id = $(element).closest('tr').attr('id'); }
30331        var action = GLO.Uri.hash('action').toLowerCase();
30332        
30333        if (action === 'order' || action === 'audit' || action === 'restock' || $('#shipment-detail-header:visible').length === 1 || document.location.pathname.substring(0, 9) === '/reports/') {
30334            if (GLO.Info.isMobile(true)) { GLO.UI.animate(10); }
30335            
30336            var url = document.location.protocol + '//' + document.location.host + '/provider/inventory/#action=edit-product&id=' + id;
30337            var childWindow = UI.openChildWindow(url, '', true, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes,height=800");
30338        } else if ( $('#inventory-item-form').length === 0) {
30339            GLO.Inventory.updateHash('view-product', id);
30340        } else {
30341            GLO.Inventory.updateHash('edit-product', id);
30342        }
30343    }
30344
30345    _conIItem.openView = function(id) {
30346        var jItem = $("#inventory-item-view");
30347        var tr = $('#inventory-table tbody tr#' + id);
30348
30349        var type = tr.find('.item-type-category').text()
30350        var category = tr.find('.item-type').text()
30351
30352        if (type && category) {
30353	         type = type + " - " + category;
30354        } else if (category) {
30355	        type = category;
30356        }
30357        
30358        jItem.attr('is_gift_card_fl', tr.attr('is_gift_card_fl'));
30359        
30360        jItem.find('#vw-name').text( UTIL.coalesce(tr.find('.item-name').attr('title'), tr.find('.item-name').text()) );
30361        jItem.find('#vw-vendor').text( tr.find('.item-vendor').text() );
30362        
30363        jItem.find('#vw-sku').text( tr.attr('sku_vc') );
30364        jItem.find('#vw-upc').text( tr.attr('upc_vc') );
30365        jItem.find('#vw-shelf').text( tr.find('.item-shelf').text() );
30366
30367        jItem.find('#vw-type').text(type);
30368        jItem.find('#vw-size').text( tr.find('.item-size').text() );
30369        
30370        var cost = tr.find('.item-cost').text();
30371        if (!UTIL.isEmpty(cost)) { cost = '$' + cost; }
30372        jItem.find('#vw-cost').text(cost);
30373
30374        var price = tr.find('.item-price').text();
30375        //if (!UTIL.isEmpty(price)) { price = '$' + price; }
30376        jItem.find('#vw-price').text(price);
30377
30378        var eprice = tr.attr('employee_price_mn');
30379        if (!UTIL.isEmpty(eprice)) { eprice = '$' + eprice; }
30380        jItem.find('#vw-employee-price').text(eprice);
30381
30382        jItem.find('#vw-in-stock').text(tr.find('.item-in-stock').text());
30383        jItem.find('#vw-min-stock').text(tr.find('.item-minimum-stock:visible').text());
30384        
30385        var desc = tr.find('.item-desc').text();
30386        
30387        if (!UTIL.isEmpty(desc)) { 
30388            jItem.find('#vw-description').text(desc);
30389            jItem.find('.vw-item-description').removeClass('hide');
30390        } else {
30391            jItem.find('.vw-item-description').addClass('hide');
30392        }
30393        
30394        if (UTIL.parseBool(tr.attr('for_retail_fl'))) {
30395            jItem.find('#vw-is-for-retail').removeClass('hide');
30396        } else {
30397            jItem.find('#vw-is-for-retail').addClass('hide');
30398        }
30399
30400        if (UTIL.parseBool(tr.attr('for_internal_fl'))) {
30401            jItem.find('#vw-is-for-internal').removeClass('hide');
30402        } else {
30403            jItem.find('#vw-is-for-internal').addClass('hide');
30404        }
30405
30406        tax = tr.attr('tax_rate_pct');
30407        commission = tr.attr('commission_pct');
30408
30409        if (!UTIL.isEmpty(tax)) {
30410            jItem.find('#vw-tax-rate').text(tax);
30411            jItem.find('.vw-item-tax-rate').removeClass('hide');
30412        } else {
30413            jItem.find('.vw-item-tax-rate').addClass('hide');
30414        }
30415                
30416        if (!UTIL.isEmpty(commission)) {
30417            jItem.find('#vw-commission').text(tax);
30418            jItem.find('.vw-item-commission').removeClass('hide');
30419        } else {
30420            jItem.find('.vw-item-commission').addClass('hide');
30421        }
30422
30423        jItem.removeClass('hide');
30424    }
30425
30426    _conIItem.openEdit = function(id) {
30427        GLO.Inventory.Item.costXml = null;
30428        var jItem = $("#inventory-item-form");
30429        var jOverride = $('#inventory-item-override-row');
30430
30431        var nm = '', vendor = '', productLine = '', sku = '', upc = '', category = '', typeId = '', size = '', unit = '', shelfDays = '';
30432        var webCode = null, forRetail = true, forInternal = '', trackStock, cost = '', price = '', inStock = '', minStock = '', employeePrice = '', tax = '', commission = '', desc = '';     //overrideTax = false
30433		var itemImageFilename='', itemImageCount = '', isVariation = 0, hasVariations = 0, parentInventoryId = 0, isCombo = 0, isBundle = 0;
30434
30435        jOverride.find('label').css({ "cursor": "pointer", "text-decoration": "underline" });
30436        jOverride.find('#inventory-item-override-tax, #inventory-item-override-commission').addClass('hide');
30437
30438        if (!UTIL.isEmpty(id)) {
30439            if (id == 0) {        //= is going back to new product.
30440                jItem.removeClass('hide');
30441                return;
30442            }
30443
30444            var tr = $('#inventory-table tbody tr#' + id);
30445            
30446            nm = UTIL.coalesce(tr.find('.item-name').attr('title'), tr.find('.item-name').text());
30447            vendor = tr.find('.item-vendor').attr('vendor_id');
30448            productLine = tr.find('.item-product-line').attr('product_line_id');
30449            
30450            sku = UTIL.coalesce($.trim(tr.find('.item-sku').attr('title')), $.trim(tr.find('.item-sku').text()), tr.attr('sku_vc'));
30451            upc = UTIL.coalesce($.trim(tr.find('.item-upc').attr('title')), $.trim(tr.find('.item-upc').text()), tr.attr('upc_vc'));
30452            shelfDays = UTIL.coalesceInt(tr.find('.item-shelf').attr('order_by'), tr.attr('shelf_days_nr'));
30453            
30454            category = tr.find('.item-type-category').attr('type_category_id');
30455            typeId = tr.find('.item-type').attr('type_id');
30456            
30457            unit = tr.find('.item-size').attr('unit_id');
30458            var unitAbbreviation = $('select#Unit_id option[value="' + unit + '"]').attr('title');
30459            size = jQuery.trim(tr.find('.item-size').attr('size_dr'));									//.replace(unitAbbreviation, '')
30460            
30461            trackStock = UTIL.parseBool(tr.attr('track_stock_fl')) && (GLO.Info.providerPackage != 4);
30462            forRetail = UTIL.parseBool(tr.attr('for_retail_fl'));
30463            forInternal = UTIL.parseBool(tr.attr('for_internal_fl'));
30464            webCode = tr.attr('web_cd');
30465            
30466            cost = tr.find('.item-cost').text();
30467            
30468            if (UTIL.isEmpty(cost)) {
30469            	cost = 'set cost';
30470        	} else {
30471        		cost = '$' + UTIL.roundMoney(cost.replace('$', ''));
30472        	}
30473
30474            inStock = tr.find('.item-in-stock').text();
30475            if (UTIL.isNumber(inStock)) { inStock = parseInt(inStock); }
30476            
30477            minStock = tr.find('.item-minimum-stock').text();
30478            
30479            price = UTIL.cleanString(tr.find('.item-price')).text().replace('$', '');
30480            employeePrice = UTIL.cleanString(tr.attr('employee_price_mn')).replace('$', '');           //employeePrice = tr.find('.item-employee-price').text();
30481
30482            tax = tr.attr('tax_rate_pct');                               //tax = tr.find('.item-tax').text();
30483            commission = tr.attr('commission_pct');
30484
30485            if (!UTIL.isEmpty(tax) || !UTIL.isEmpty(commission)) {
30486                if (!UTIL.isEmpty(tax)) {
30487                    jOverride.find('label[for="Tax_Rate_pct"]').css({ "text-decoration": "" });
30488                    jOverride.find('#inventory-item-override-tax').removeClass('hide');
30489                } 
30490                
30491                if (!UTIL.isEmpty(commission)) {
30492                    jOverride.find('label[for="Commission_pct"]').css({ "text-decoration": "" });
30493                    jOverride.find('#inventory-item-override-commission').removeClass('hide');
30494                }
30495            }
30496            
30497            desc = tr.find('.item-desc').text();
30498			itemImageFilename = tr.find('.item-image-path').text();
30499			itemImageCount = tr.find('.item-image-count').text();
30500			isVariation = (UTIL.parseBool(tr.find('.item-is-variation').text())) ? 1 : 0;
30501			hasVariations = (UTIL.parseBool(tr.find('.item-has-variations').text())) ? 1 : 0;
30502			parentInventoryId = tr.find('.item-parent-inventory-id').text();
30503			isCombo = (UTIL.parseBool(tr.find('.item-is-combo').text())) ? 1 : 0;
30504			isBundle = (UTIL.parseBool(tr.find('.item-is-bundle').text())) ? 1 : 0;
30505            jItem.find('#inventory-item-override-row')
30506
30507			if (isBundle) {
30508				GLO.Inventory.Item.getBundleProducts(id);
30509			} else {
30510				resetChildProductsGrid();
30511				$('#Price_mn').removeAttr('disabled');
30512				$('#Employee_Price_mn').removeAttr('disabled');
30513				$('#Avg_Cost_mn').attr("onclick","GLO.Inventory.Item.openCostPopup()");
30514			}
30515
30516            /* for now only lookup this information when click to open the cost basis popup
30517                if (!UTIL.isEmpty(tr.find('.item-cost-parent').attr('last_cost_mn'))) {
30518                    _lookupCostBasis(id);
30519                }
30520            */
30521
30522            jItem.find('#In_Stock_link').removeClass('hide').text(inStock);
30523            jItem.find('#Avg_Cost_mn').removeClass('hide').text(cost);
30524            jItem.find('#In_Stock_dr').addClass('hide');
30525
30526            var jHead = $('.inventory-header');
30527            jHead.find('#inventory-header-options-link, #inventory-header-reports-link').addClass('hide');
30528            jHead.find('.btnBuyNow, .btnReturnProduct').removeClass('hide');
30529            
30530            if (trackStock) { jItem.find('#In_Stock_dr, #Cost_mn, #Cost_mn_dollar').addClass('hide'); }
30531        } else {
30532            var jvendorDD = jItem.find('#Vendor_id');		//if (jvendorDD.find('option').length === 2) { vendor = jvendorDD.find('option').eq(1).attr('value'); }
30533            var tr = null;
30534            
30535            jItem.find('#In_Stock_dr, #Cost_mn_dollar, #Cost_mn').removeClass('hide');
30536            jItem.find('#In_Stock_link, #Avg_Cost_mn').addClass('hide');
30537            
30538            trackStock = UTIL.parseBool($('#inventory-options').attr('track_stock_fl'));
30539            
30540            if (UTIL.parseBool(GLO.Uri.hash('internal-use'))) {
30541            	forRetail = 0;
30542            	forInternal = 1;
30543            	price = employeePrice = tax = commission = 0;
30544            	
30545            	$('#inventory-item-override-commission').toggleClass('hide');
30546    			$('#inventory-item-override-tax').toggleClass('hide');
30547            }
30548        }
30549        
30550        jItem.find('#Inventory_id').val(UTIL.cleanString(id));
30551        jItem.find('#Name_vc').val(nm).focus();
30552        jItem.find('#Vendor_id').val(vendor).change();
30553        jItem.find('#Product_Line_id').val(productLine);
30554        jItem.find('#Unit_id').val(unit);
30555
30556        jItem.find('#SKU_vc').val(sku);
30557        jItem.find('#UPC_vc').val(upc);
30558        _setShelfLife(jItem, shelfDays);
30559
30560        if (!UTIL.isEmpty(category) && UTIL.isEmpty(typeId)) {
30561        	var jtype = jItem.find('#Inventory_Type_id');
30562        	
30563        	if (jtype.find('option[value="c' + category + '"]').length === 0) {
30564        		var catName = $('#Type_Category_id').find('option[value="' + category + '"]').text();
30565        		jtype.find('option:first').after('<option value="c' + category + '">' + catName + '</option>');
30566        	}
30567        	
30568        	jtype.val('c' + category);
30569        } else {
30570        	jItem.find('#Inventory_Type_id').val(typeId);
30571        }
30572        
30573        jItem.find('#Size_dr').val(size);
30574        jItem.find('#Web_cd').val(webCode);
30575        jItem.find('#For_Retail_fl').prop('checked', forRetail);
30576        jItem.find('#For_Internal_fl').prop('checked', forInternal);
30577        jItem.find('#Track_Stock_fl').prop('checked', trackStock);
30578        
30579        jItem.find('#Cost_mn').val(cost.replace('$', ''));
30580        jItem.find('#Price_mn').val(price);
30581
30582        jItem.find('#In_Stock_dr').val(inStock);
30583        jItem.find('#Minimum_Stock_dr').val(minStock);
30584        jItem.find('#Employee_Price_mn').val(employeePrice);
30585        
30586        jItem.find('#Tax_Rate_pct').val(tax);                   //jItem.find('#Override_Tax_Rate_fl').prop('checked', overrideTax);
30587        jItem.find('#Commission_pct').val(commission);
30588
30589        jItem.find('#Description_vc').val(desc);
30590
30591		if (id !== '') {
30592			//item has been saved
30593			//TODO: DISPLAY ITEM IMAGE COUNT
30594		}
30595		else {
30596
30597			//TODO: CHANGE MANAGE IMAGES TO ADD IMAGES
30598		}
30599
30600        if (false && $('#Vendor_id option').length === 1) {			//= brand is optional so do NOT require creating brand first.
30601            GLO.Inventory.Vendor.openEdit();
30602        } else {
30603            jItem.removeClass('hide');
30604        }
30605        
30606        _setGiftCard(tr, jItem);
30607        _conIItem.setMarkup();
30608        
30609        jItem.find('#Track_Stock_fl').change();
30610        jItem.find('.btnSave a').css({ "border": "3px solid transparent" });
30611        jItem.find('input:first').focus();
30612
30613		if (isVariation == 1) {
30614			//hide buttons, manage options link
30615			$(jItem.find('#inventory-item-image-row')[0]).addClass('hide');
30616			$(jItem.find('#inventory-item-buttons')[0]).find('#ba-Save').addClass('hide');
30617			$(jItem.find('#inventory-item-buttons')[0]).find('.btnDelete').addClass('hide');
30618			$(jItem.find('#inventory-item-is-variant-row')[0]).removeClass('hide');
30619			if (parentInventoryId > 0) {
30620				var masterProductLinkEl = $(jItem.find('#inventory-item-is-variant-row')[0]).find('#link-to-master-product');
30621				var masterProductPageUrl = document.location.protocol + '//' + document.location.host + '/provider/inventory/#action=edit-product&id=' + parentInventoryId;
30622				$(masterProductLinkEl).attr('href',masterProductPageUrl);
30623			}
30624		}
30625		else {
30626			$(jItem.find('#inventory-item-image-row')[0]).removeClass('hide');
30627			$(jItem.find('#inventory-item-buttons')[0]).find('#ba-Save').removeClass('hide');
30628			$(jItem.find('#inventory-item-buttons')[0]).find('.btnDelete').removeClass('hide');
30629			$(jItem.find('#inventory-item-is-variant-row')[0]).addClass('hide');
30630			var masterProductLinkEl = $(jItem.find('#inventory-item-is-variant-row')[0]).find('#link-to-master-product');
30631			var masterProductPageUrl = '#';
30632			$(masterProductLinkEl).attr('href',masterProductPageUrl);
30633		}
30634
30635		if (hasVariations == 1) {
30636
30637		}
30638    }
30639    function _setGiftCard(tr, jitem) {
30640    	var isGiftCard = ((tr && UTIL.parseBool(tr.attr('is_gift_card_fl'))) || (tr === null && GLO.Uri.hash('and') == 'gift-card')) ? 1 : 0;
30641    	
30642    	jitem.find('#Is_Gift_Card_fl').val(isGiftCard);
30643        
30644        if (isGiftCard) {
30645        	var isGiftVoucher = (jitem.find('#Inventory_Type_id option:selected').attr('default_t
30645ype_id') == 116);
30646        	jitem.addClass('is-gift-card');
30647        	jitem.find('#Enable_Gift_Voucher_fl').prop('checked', isGiftVoucher).change();
30648        	
30649        	_populateReferrerVoucherList(jitem, tr);
30650        	
30651        	if (tr) {
30652        		jitem.find('#Expire_Days_sr').val(tr.attr('expire_days_sr'));
30653        		jitem.find('#Min_Purchase_mn').val(tr.attr('min_purchase_mn'));
30654        		jitem.find('#Referrer_Amount_mn').val(tr.attr('referrer_amount_mn'));
30655        		
30656        		jitem.find('#Gift_Only_fl').prop('checked', UTIL.parseBool(tr.attr('gift_only_fl')));
30657        		jitem.find('#New_Client_Only_fl').prop('checked', UTIL.parseBool(tr.attr('new_client_only_fl')));
30658        		return;
30659        	} else {
30660        		jitem.find('#inventory-item-override-tax').removeClass('hide');
30661        		jitem.find('#inventory-item-override-commission').removeClass('hide');
30662        		
30663        		//GLO.Uri.removeHashKey('and');			//= do NOT call because re-triggers hashChange
30664        		var typeId = GLO.Inventory.Type.getGiftCardSubCategory();
30665        		jitem.find('#Inventory_Type_id').val(typeId);
30666        		
30667        		jitem.find('#Tax_Rate_pct').val('0');
30668        		jitem.find('#Commission_pct').val('0');
30669        		jitem.find('#For_Retail_fl').prop('checked', true);
30670        	}
30671        	
30672        	_autoAddGiftCardTypeIfMissingCheck();
30673        } else {
30674        	jitem.removeClass('is-gift-card');
30675        }
30676        
30677        jitem.find('#Expire_Days_sr, #Min_Purchase_mn, #Referrer_Amount_mn').val('');
30678        jitem.find('#Gift_Only_fl, #New_Client_Only_fl').prop('checked', false);
30679    }
30680    function _autoAddGiftCardTypeIfMissingCheck() {
30681    	if ($('select#Inventory_Type_id option[default_type_id = 115]').length === 0) {
30682    		_autoAddGiftCardTypeIfMissing();
30683    	} else if ($('select#Inventory_Type_id option[default_type_id = 116]').length === 0) {
30684    		_autoAddGiftCardTypeIfMissing();
30685    	} else if ($('select#Type_Category_id option[default_type_category_id = 41]').length === 0) {
30686    		_autoAddGiftCardTypeIfMissing();
30687    	}
30688    }
30689    function _autoAddGiftCardTypeIfMissing() {
30690    	var uri = GLO.Link.Page.Provider.Home + 'Inventory/CreateGiftType';
30691        var jqxhr = $.ajax({ type: "POST", "url": uri, "cache": false })
30692            .success(function(data, textStatus, jqXHR) {
30693                if (UTIL.coalesceInt($(data).attr('change_count_sr')) > 0) {
30694                	var msg = '<p>Loading missing gift card/voucher category and sub-category...</p>';
30695                	GLO.Popup.Processing.open('<div id="pop-processing-gift-type-created">' + msg + '</div>', 'Loading Gift Data...');
30696                	
30697                	setTimeout(function() {
30698                		location.reload();
30699                	}, 900);
30700                }
30701            });
30702            //.error(function(jqXHR, textStatus, errorThrown) {  });
30703    }
30704    
30705    function _populateReferrerVoucherList(jitem, tr) {
30706    	var voucherTypeId = $('select#Inventory_Type_id option[default_type_id = 116]').val();
30707    	var jvoucher = $('#inventory-table').find('tbody td.item-type[type_id = ' + voucherTypeId + ']');
30708    	var referrerInventoryId = null, optionList = '<option value=""></option>';
30709    	
30710    	if (jvoucher.length > 1 || (jvoucher.length == 1 && jvoucher.closest('tr').attr('id') != tr.attr('id'))) {			//= more than 1 voucher or this is not the voucher
30711	    	if (tr) {
30712	    		referrerInventoryId = tr.attr('referrer_inventory_id');
30713        	}
30714	    	
30715	    	for (var i=0; i < jvoucher.length; i++) {
30716	    		var selectedAttribute = '', jtr = jvoucher.eq(i).parent('tr');
30717	    		var inventoryId = jtr.attr('id');
30718	    		var name = jtr.find('.item-name').text();
30719	    		
30720	    		if (referrerInventoryId == inventoryId) {
30721	    			selectedAttribute = ' selected="selected"';
30722	    		}
30723	    		
30724	    		optionList += '<option value="' + inventoryId + '"' + selectedAttribute + '>' + name + '</option>';
30725	    	}
30726	    	
30727	    	jitem.find('#Referrer_Inventory_id').html(optionList).removeClass('hide');
30728	    	jitem.find('label[for="Referrer_Inventory_id"]').removeClass('hide');
30729    	} else {
30730    		jitem.find('label[for="Referrer_Inventory_id"], #Referrer_Inventory_id').addClass('hide');
30731    	}
30732    }
30733    function _setShelfLife(jitem, shelfDays) {
30734    	if (shelfDays > 0) {
30735    		if (shelfDays % 365 == 0) {
30736    			var days = parseInt(shelfDays/365), period = '365';
30737    		} else if (shelfDays % 30 == 0) {
30738    			var days = parseInt(shelfDays/30), period = '30';
30739    		} else if (shelfDays % 7 == 0) {
30740    			var days = parseInt(shelfDays/7), period = '7';
30741    		} else {
30742    			var days = parseInt(shelfDays), period = '1';
30743    		}
30744    	} else {
30745    		var days = '', period = '';
30746    	}
30747    	
30748    	jitem.find('#Shelf_Life_nr').val(days);
30749    	jitem.find('#Shelf_Life_Period_nr').val(period);
30750    }
30751    function _saveShelf(frm, jsonItem) {
30752    	var nr = frm.find('#Shelf_Life_nr').val();
30753    	var period = frm.find('#Shelf_Life_Period_nr').val();
30754    	
30755    	if (nr > 0) {
30756    		jsonItem.Shelf_Life_Days_nr = parseInt(parseInt(nr) * parseInt(period));
30757    	}
30758    }
30759    
30760    _conIItem.changeType = function() {
30761    	var jitem = $("#inventory-item-form");
30762    	var isVoucher = (jitem.find('#Inventory_Type_id option:selected').attr('default_type_id') == 116);
30763    	var jenable = jitem.find('#Enable_Gift_Voucher_fl');
30764    	
30765    	if (!isVoucher && jenable.prop('checked')) {
30766    		jenable.prop('checked', false).change();
30767    	} else if (isVoucher && !jenable.prop('checked')) {
30768    		jenable.prop('checked', true).change();
30769    	}
30770    }
30771    _conIItem.changeEnableVoucher = function() {
30772    	var jitem = $("#inventory-item-form");
30773    	var isEnabled = jitem.find('#Enable_Gift_Voucher_fl').prop('checked');
30774    	
30775    	if (isEnabled) {
30776    		jitem.addClass('is-gift-voucher-enabled');
30777    		
30778    		var jtype = jitem.find('#Inventory_Type_id');
30779    		
30780    		if (jtype.find('option:selected').attr('default_type_id') != 116) {
30781    			jtype.find('option[default_type_id=116]').prop('selected', true);
30782    		}
30783    	} else {
30784    		jitem.removeClass('is-gift-voucher-enabled');
30785    	}
30786    }
30787    _conIItem.changeTrackStock = function(element) {
30788    	var j = $('#inventory-item-edit:visible');
30789    	var iid = j.find('#Inventory_id').val();
30790    	
30791    	if (j.length === 0) { return; }
30792    	
30793    	if (element.checked) {
30794    		j.find('.track-stock-level').css({ "background-color": "#C1FFC1" });
30795    		j.find('label[for="In_Stock_dr"], label[for="Minimum_Stock_dr"]').css({ "text-decoration": "" });
30796    		
30797    		j.find('#Minimum_Stock_dr').removeClass('hide');
30798    		
30799    		if (!UTIL.isEmpty(iid)) {
30800    			j.find('#In_Stock_link, #Avg_Cost_mn').removeClass('hide');
30801    			j.find('#Cost_mn').addClass('hide');
30802    			
30803    			if (!UTIL.isNumber(j.find('#Avg_Cost_mn').text(), true)) {
30804	    			j.find('#Avg_Cost_mn').text('set cost');
30805	    		}
30806    		} else {
30807    			j.find('#In_Stock_dr, #Cost_mn').addClass('hide');
30808    		}
30809    	} else {
30810    		j.find('.track-stock-level').css({ "background-color": "#ddd" });
30811    		j.find('label[for="In_Stock_dr"], label[for="Minimum_Stock_dr"]').css({ "text-decoration": "line-through" });
30812    		
30813    		j.find('#Avg_Cost_mn, #In_Stock_dr, #In_Stock_link, #Minimum_Stock_dr').addClass('hide');
30814    		j.find('#Cost_mn').removeClass('hide');
30815    		
30816    		if (!UTIL.isNumber(j.find('#Cost_mn').val(), true)) { j.find('#Cost_mn').val(''); }
30817    	}
30818    }
30819    
30820    _conIItem.clickCommission = function(element) {
30821        $('#inventory-item-override-commission').toggleClass('hide');
30822    }
30823
30824    _conIItem.clickTax = function(element) {
30825        $('#inventory-item-override-tax').toggleClass('hide');
30826    }
30827
30828    _conIItem.setMarkup = function() {
30829        var jItem = $("#inventory-item-form");
30830        var jpm = jItem.find('#Price_Markup_pct');
30831        
30832        var cost = UTIL.coalesceMoney(UTIL.cleanString(UTIL.coalesce(jItem.find('#Cost_mn:visible').val(), jItem.find('#Avg_Cost_mn:visible').text())).replace('$', ''));
30833        var price = UTIL.coalesceMoney(jItem.find('#Price_mn').val());
30834        
30835        if (cost > 0 && price > 0 && UTIL.isNumber(cost, true) && UTIL.isNumber(price, true) && cost > 0) {
30836        	var pm = ( ( ( parseFloat(price) - parseFloat(cost) ) / parseFloat(cost) ) * 100).toFixed(0);
30837	        jpm.text(pm + '%');
30838	        jpm.parent().find('small').removeClass('hide');
30839        } else {
30840            jpm.text('');
30841            jpm.parent().find('small').addClass('hide');
30842        }
30843    }
30844
30845    _conIItem.vendorChanged = function(vendorDD) {
30846        var vid = $(vendorDD).val();
30847        if (UTIL.isEmpty(vid)) { vid = ''; }
30848
30849        var options = $('#inventory-item-form').find('#Product_Line_id option');
30850
30851        for (var i=1; i < options.length; i++) {
30852            if (vid === '') {
30853                options.eq(i).removeClass('hide');
30854            } else if (vid == options.eq(i).attr('vendor_id')) {
30855                options.eq(i).removeClass('hide');
30856            } else {
30857                options.eq(i).addClass('hide');
30858            }
30859        }
30860    }
30861
30862    _conIItem.productLineChanged = function(plDD) {
30863        var vendorDD = $('#inventory-item-form').find('#Vendor_id');
30864
30865        if (vendorDD.val() == '') {
30866            var vid = $(plDD).find('option:selected').attr('vendor_id');
30867            vendorDD.val(vid);
30868        }
30869    }
30870
30871    _conIItem.populateCostBasis = function() {
30872        var jModal = $('#simplemodal-container');
30873        var jfrm = $('#inventory-item-form');
30874        var ul = $(GLO.Inventory.Item.costXml);
30875        
30876        if (jfrm.find('#Inventory_id').val() == ul.attr('inventory_id')) {
30877            var lis = ul.find('li');
30878            var dt;
30879            var len = lis.length;
30880            if (len > 10) { len = 11; }
30881
30882            for (var i=0; i < len; i++) {
30883                dt = lis.eq(i).attr('create_dt');
30884                
30885                _conIItem.addCostRow(lis.eq(i).attr('cost_mn'), lis.eq(i).attr('count_dr'), i, lis.eq(i).attr('stock_id'), dt);
30886            }
30887
30888            var acost = UTIL.roundMoney(ul.attr('avg_cost_mn'));
30889            var tcount = UTIL.roundMoney(ul.attr('total_count_dr'));
30890
30891            jfrm.find('#Avg_Cost_mn').text('$' + acost);
30892            jfrm.find('#In_Stock_link').text(tcount);
30893        }
30894
30895        _conIItem.editCostBasis();
30896    }
30897
30898    _conIItem.openCostPopup = function() {
30899        _loadingCostPopup = true;
30900
30901        $('#inventory-item-edit-cost').modal();
30902        var jModal = $('#simplemodal-container').css({ "padding": "0" }).draggable({ "handle": "h2" });
30903        
30904        jModal.find('.btnSave a').css({ "border": "3px solid transparent" });
30905        var frm = $("#inventory-item-form");
30906        var trs = frm.find('.edit-cost-row');
30907
30908        for (var i=1; i < trs.length; ++i) {
30909            trs.eq(i).remove();
30910        }
30911
30912        if (jModal.height() < 10) {
30913            jModal.height(235);
30914        }
30915        
30916        if (innerWidth >= 840) {
30917        	jModal.width(800);
30918        	jModal.css({ "font-size": "131%" });
30919        	jModal.find(':text').css({ "width": "100px", "letter-spacing": "1px" });
30920        	jModal.find('.btnAddProduct > a').css({ "padding-left": "10px", "padding-right": "10px", "letter-spacing": "1px", "font-weight": "bold" });
30921        } else if (innerWidth >= 700) {
30922        	jModal.width(640);
30923        	jModal.css({ "font-size": "108%" });
30924        	jModal.find(':text').css({ "width": "80px", "letter-spacing": "1px" });
30925        } else if (innerWidth >= 500) {
30926        	jModal.width(500);
30927        } else {
30928        	jModal.find('.item-edit-created').css({ "white-space": "normal" });
30929        	jModal.find('th.edit-cost-item-column').text('#');
30930        	jModal.find('input.item-edit-count').css({ "width": "40px" });
30931        	
30932        	if (jModal.width() < 300 || innerWidth < 400) {
30933            	jModal.width(310).css({ "position": "relative", "left": "", "margin": "auto" });
30934            }
30935        }
30936        
30937        var iid = frm.find('#Inventory_id').val();
30938
30939        if (!UTIL.isEmpty(iid)) {
30940            _lookupCostBasis(iid);
30941        }
30942
30943        if (_lookingUpCostBasis) {
30944            var throbber = $('<div style="text-align: center; min-width: 60px; min-height: 60px;">' + $('.loadingDiv').clone().find('img').css({ "margin": "50px auto", "min-width": "50px" }).outerHTML() + '</div>');
30945            
30946            jModal.find('#inventory-item-edit-cost-throbber').removeClass('hide').html(throbber);
30947            jModal.find('#inventory-item-edit-cost-table, #inventory-item-edit-cost-buttons').addClass('hide');
30948        } else {
30949            _conIItem.openCostPopup2();
30950        }
30951        
30952        var h = jModal.find('#inventory-item-edit-cost').height();
30953        var w = jModal.find('#inventory-item-edit-cost').width();
30954        
30955        $.modal.update(h,w);
30956        $(window).resize();         //= re-center simpleModal.
30957        _loadingCostPopup = false;
30958    }
30959
30960    _conIItem.openCostPopup2 = function(frm) {
30961        var jModal = $('#simplemodal-container #inventory-item-edit-cost');
30962        jModal.find('#inventory-item-edit-cost-throbber').addClass('hide');
30963        jModal.find('#inventory-item-edit-cost-table, #inventory-item-edit-cost-buttons').removeClass('hide');
30964
30965        if (GLO.Inventory.Item.costXml) {
30966            GLO.Inventory.Item.populateCostBasis();
30967
30968            var ul = $(GLO.Inventory.Item.costXml);
30969            var iid = ul.attr('inventory_id');
30970            var cost = ul.attr('avg_cost_mn');
30971            var cnt = ul.attr('total_count_dr');
30972
30973            _updateCostBasis_ProductListRow(iid, cost, cnt);
30974        } else {
30975            var frm = $("#inventory-item-form");
30976            var iid = frm.find('#Inventory_id').val();
30977
30978            var cost = UTIL.coalesce(frm.find('#Avg_Cost_mn:visible').text().replace('$', ''), frm.find('#Cost_mn:visible').val());
30979            
30980            if (!UTIL.isNumber(cost, true)) {
30981            	cost = '';
30982            } else {
30983            	cost = UTIL.roundMoney(cost);
30984            }
30985
30986            if (!UTIL.isEmpty(iid)) {
30987                var dt = $('#inventory-table tbody').find('tr#' + iid).attr('last_update_dt');
30988                
30989                if (UTIL.isDate(dt)) {
30990                    dt = new Date(dt);
30991                    dt = dt.toGloDate() + ' ' + dt.toGloTime();
30992                    jModal.find('.item-edit-created').text(dt).attr('create_dt', dt);
30993                }
30994            }
30995            
30996            var cnt = UTIL.coalesce(frm.find('#In_Stock_dr:visible').val(), frm.find('#In_Stock_link:visible').text());
30997            
30998            if (UTIL.isNumber(cnt)) { cnt = UTIL.roundMoney(cnt); }
30999
31000            jModal.find('.item-edit-cost').val(cost);
31001            jModal.find('.item-edit-count').val(cnt);
31002
31003            _updateCostBasis_ProductListRow(iid, cost, cnt);
31004        }
31005
31006        _conIItem.editCostBasis();
31007    }
31008
31009    function _updateCostBasis_ProductListRow(iid, cost, cnt) {
31010        var jtr = $('#inventory-table').find('tr#' + iid);
31011        
31012        jtr.find('.item-cost').text(cost);
31013        jtr.find('.item-cost-edit input').val(cost);
31014        
31015        //jtr.find('.new-in-stock-total').text(cnt);
31016        jtr.find('.current-in-stock').text(cnt);
31017        jtr.find('.item-in-stock').text(cnt);
31018    }
31019
31020    _conIItem.addCostRow = function(cost, count, row, stockId, createDate) {
31021        var pop = $('#simplemodal-container');
31022        var tbl = pop.find('#inventory-item-edit-cost-table');
31023        
31024        var jrow = tbl.find('.edit-cost-row:last');
31025        if (UTIL.isEmpty(row)) { row = tbl.find('.edit-cost-row').length; }
31026
31027        if (UTIL.isNumber(cost, true)) {
31028            cost = UTIL.roundMoney(cost);
31029        } else {
31030            cost = '';
31031        }
31032
31033        if (UTIL.isNumber(count)) {
31034            count = UTIL.roundMoney(count);
31035        } else {
31036            count = '';
31037        }
31038
31039        if (row === 0) {
31040            jrow.attr('stock_id', stockId);
31041            jrow.find('.item-edit-created').text(createDate).attr('create_dt', undefined);
31042            jrow.find('.item-edit-cost').val(cost);
31043            jrow.find('.item-edit-count').val(count);
31044        } else if (row > 9) {
31045            GLO.Popup.Warning('You have reached the limit of 10 cost-basis rows');
31046            return false;
31047        } else {
31048            var newRow = jrow.clone();
31049            var popHeight = pop.height();
31050
31051            newRow.attr('stock_id', UTIL.cleanString(stockId));
31052            newRow.find('.item-edit-created').text( UTIL.cleanString(createDate) ).attr('create_dt', undefined);
31053            newRow.find('.item-edit-cost').val(cost);
31054            newRow.find('.item-edit-count').val(count);
31055
31056            jrow.after(newRow);
31057            
31058            if (popHeight === pop.height()) {
31059                $.modal.update(popHeight + 38);
31060                //tbl.height(tbl.height() + 38);
31061            }
31062        }
31063
31064        return true;
31065    }
31066
31067    _conIItem.removeCostRow = function(ev, icon) {
31068        var tr = $(icon).closest('tr');
31069
31070        if (tr.closest('tbody').find('tr').length === 1) {
31071            tr.find('input').val('');
31072            tr.find('.total-row-cost').text('');
31073        } else {
31074            var pop = $('#simplemodal-container');
31075            var popHeight = pop.height();
31076            
31077            tr.remove();
31078            
31079            if (popHeight === pop.height()) { $.modal.update(popHeight - 38); }
31080        }
31081
31082        _conIItem.editCostBasis(ev);
31083    }
31084
31085    _conIItem.closeCostBasis = function() {
31086        _lookingUpCostBasis = false;
31087        $.modal.close();
31088    }
31089
31090    _lookupCostBasis = function(id) {
31091        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemCost?id=' + id;
31092        _lookingUpCostBasis = true;
31093
31094        var jqxhr = $.ajax({ type: "GET", "url": uri, "cache": false })
31095            .success(function(data, textStatus, jqXHR) {
31096                _lookingUpCostBasis = false;
31097                
31098                if ($(data).find('li').length > 0) {
31099                    GLO.Inventory.Item.costXml = data;
31100                }
31101
31102                if ($('#inventory-item-edit-cost-throbber:visible').length === 1) {
31103                    GLO.Inventory.Item.openCostPopup2();
31104                }
31105                
31106                var h = $('#inventory-item-edit-cost').height();
31107                var w = $('#inventory-item-edit-cost').width();
31108                $.modal.update(h,w);
31109            })
31110            .error(function(jqXHR, textStatus, errorThrown) {
31111                _lookingUpCostBasis = false;
31112            });
31113    }
31114
31115    _conIItem.editCostBasis = function(ev) {
31116        if (ev) {
31117            $('#inventory-item-edit-cost').find('.btnSave a').css({ "border": "3px solid Red" });
31118        }
31119
31120        var tbl = $('#inventory-item-edit-cost-table');
31121        var trs = tbl.find('tbody tr');
31122        var cost, cnt, rowTotal, totalAvgCost = '', totalCost = 0, totalCount = 0, isValid = true;
31123
31124        for (var i=0; i < trs.length; i++) {
31125            cost = trs.eq(i).find('.item-edit-cost').val();
31126            cnt = trs.eq(i).find('.item-edit-count').val();
31127
31128            if (UTIL.isNumber(cost, true) && UTIL.isNumber(cnt)) {
31129                cost = parseFloat(cost);
31130                cnt = parseFloat(cnt);
31131                
31132                totalCost += cost * cnt;
31133                totalCount += cnt;
31134                
31135                rowTotal = UTIL.displayMoney(cost * cnt, false, false, true);
31136                trs.eq(i).find('.total-row-cost').text(rowTotal);
31137            } else {
31138                trs.eq(i).find('.total-row-cost').text('');
31139            }
31140        }
31141
31142        if (isValid) {
31143            if (totalCount !== 0) { totalAvgCost = UTIL.displayMoney(totalCost/totalCount, false, false, true); }
31144            
31145            totalCost = UTIL.displayMoney(totalCost, false, false, true);
31146            
31147            if (totalCount % 1 === 0) { totalCount = parseInt(totalCount); }
31148        } else {
31149            totalAvgCost = totalCost = totalCount = '';
31150        }
31151
31152        var tfoot = tbl.find('tfoot');
31153        tfoot.find('#item-edit-avg-cost').text(totalAvgCost);
31154        tfoot.find('#item-edit-count-total').text(totalCount);
31155        tfoot.find('#item-edit-cost-total').text(totalCost);
31156        $(window).resize();         //= re-center simpleModal.
31157    }
31158
31159    _conIItem.saveCostBasis = function() {
31160        var pop = $('#inventory-item-edit-cost');
31161        var trs = pop.find('.edit-cost-row');
31162        var jBtn = pop.find('.btnSave');
31163        var createDate, cost, count,  xmlCost = '';
31164
31165        for (var i=0; i < trs.length; i++) {
31166            cost = UTIL.cleanString(trs.eq(i).find('.item-edit-cost').val());
31167            count = UTIL.cleanString(trs.eq(i).find('.item-edit-count').val());
31168
31169            if (!UTIL.isNumber(cost, true) && cost !== '') {
31170                GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + cost + '</b> ' + SA.Resource.IsNotValidCost + '</div>', function() {
31171                    trs.eq(i).find('.item-edit-cost').focus();
31172                });
31173                return;
31174            } else if (!UTIL.isNumber(count) && count !== '') {
31175                GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">' + count + '</b> ' + SA.Resource.IsNotValidCount + '.  ' + SA.Resource.ItemMustBeNumberWarning + '.</div>', function() {
31176                    trs.eq(i).find('.item-edit-count').focus();
31177                });
31178                return;
31179            /*
31180            } else if (cost === '' && count === '') {
31181                var htm = '<div style="padding: 10px; font-size: larger; font-weight: bold;">Count and cost are both empty</div>';
31182                
31183                GLO.Popup.Warning.open(htm, 'Empty Warning', function() {
31184                    trs.eq(i).find('.item-edit-count').focus();
31185                });
31186                return;
31187            */
31188            }
31189
31190            if (i === 0) {
31191                createDate = trs.eq(i).find('.item-edit-created').attr('create_dt');
31192
31193                if (UTIL.isDate(createDate)) {
31194                    createDate = " create_dt='" + createDate + "'";
31195                } else {
31196                    createDate = '';
31197                }
31198            } else {
31199                createDate = '';
31200            }
31201
31202            xmlCost += "<tr stock_id='" + UTIL.cleanString(trs.eq(i).attr('stock_id')) + "' cost_mn='" + cost + "' count_dr='" + count + "'" + createDate + "/>";
31203        }
31204
31205        xmlCost = UTIL.htmlEncode(xmlCost);
31206        var inventoryId = $('#inventory-item-form #Inventory_id').val();
31207        
31208        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemCost';
31209        GLO.UI.Form.beginProcessing(jBtn);
31210
31211        var jqxhr = $.ajax({ type: "POST", "url": uri, "cache": false, "data": { "cost_basis_xml": xmlCost, "inventory_id": inventoryId } })
31212            .success(function(data, textStatus, jqXHR) {
31213                if (UTIL.Validate.hasPermissionError(data)) { return; }
31214                
31215                GLO.Inventory.Item.updateItemRow(data, inventoryId);
31216
31217                var jItem = $('#inventory-item-form');
31218
31219                if (data && inventoryId == jItem.find('#Inventory_id').val()) {
31220                    $.modal.close();            //GLO.Popup.close();
31221
31222                    var tr = $(data);
31223                    jItem.find('#Avg_Cost_mn').text( tr.find('.item-cost').text() );
31224
31225                    var inStock = tr.find('.item-in-stock').text();
31226                    jItem.find('#In_Stock_link').text(inStock);
31227                    jItem.find('#In_Stock_dr').val(inStock);
31228
31229                    if (tr.find('.inventory-item-cost-xml li').length > 0) {
31230                        GLO.Inventory.Item.costXml = tr.find('.inventory-item-cost-xml').html();
31231                    } else {
31232                        GLO.Inventory.Item.costXml = null;
31233                    }
31234                    
31235                    _conIItem.setMarkup();
31236                }
31237            })
31238            .error(function(jqXHR, textStatus, errorThrown) {
31239                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
31240                GLO.UI.Form.resetProcessing();
31241            });
31242    }
31243
31244    _conIItem.save = function() {
31245        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Item';
31246        var frm = $('#inventory-item-form');
31247        
31248        if (UTIL.isEmpty(frm.find('#Name_vc').val())) {
31249            GLO.Popup.Warning(SA.Resource.PleaseEnterProductName, function() { $('#inventory-item-form #Name_vc').focus(); });
31250            return;
31251        //} else if (UTIL.isEmpty(frm.find('#Vendor_id').val())) {
31252        //    GLO.Popup.Warning('Please enter a brand name', function() { $('#inventory-item-form #Inventory_Vendor_id').focus(); });
31253        //    return;
31254        }
31255        
31256        var iid = frm.find('#Inventory_id').val();
31257        var inm = frm.find('#Name_vc').val();
31258        var vid = frm.find('#Vendor_id').val();
31259        var plineid = frm.find('#Product_Line_id').val();
31260
31261        var sku = frm.find('#SKU_vc').val();
31262        var upc = frm.find('#UPC_vc').val();
31263        var itype = frm.find('#Inventory_Type_id').val();
31264
31265        var unit = frm.find('#Unit_id').val();
31266        var size = frm.find('#Size_dr').val();
31267        
31268        var webCode = frm.find('#Web_cd').val();
31269        var rfl = frm.find('#For_Retail_fl').prop('checked');
31270        var ifl = frm.find('#For_Internal_fl').prop('checked');
31271        
31272        var noTrackStock = !_isTrackStock(iid);
31273        var cost = frm.find('#Cost_mn:visible, #Avg_Cost_mn:visible').val();
31274        
31275        var price = UTIL.cleanString(frm.find('#Price_mn').val());
31276        var eprice = UTIL.cleanString(frm.find('#Employee_Price_mn').val());
31277        var instock = UTIL.coalesce(frm.find('#In_Stock_dr:visible').val(), frm.find('#In_Stock_link:visible').text());
31278        var minstock = UTIL.cleanString(frm.find('#Minimum_Stock_dr').val());
31279
31280        var tax = frm.find('#Tax_Rate_pct:visible').val();
31281        var commission = frm.find('#Commission_pct:visible').val();
31282        var desc = frm.find('#Description_vc').val();
31283        // var itemImageFilename = $('#item-image-path').val();
31284		// , "Item_Image_path_vc": itemImageFilename
31285
31286        if (!UTIL.isNumber(price, true) && price !== '') {
31287            GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + price + '</b> ' + SA.Resource.IsNotValidPrice + '.  ' + SA.Resource.PleaseEnterNumber + '.</div>', function() {
31288                $('#inventory-item-form').find('#Price_mn').focus();
31289            });
31290            
31291            return;
31292        } else if (!UTIL.isNumber(eprice, true) && eprice !== '') {
31293            GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + eprice + '</b> ' + SA.Resource.IsNotValidStaffPrice + '.  ' + SA.Resource.PleaseEnterNumber + '.</div>', function() {
31294                $('#inventory-item-form').find('#Employee_Price_mn').focus();
31295            });
31296
31297            return;
31298        } else if (!UTIL.isNumber(minstock) && minstock !== '') {
31299            GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">' + minstock + '</b> ' + SA.Resource.IsNotValidDesiredStockAmount + '.  ' + SA.Resource.PleaseEnterNumber + '.</div>', function() {
31300                $('#inventory-item-form').find('#Minimum_Stock_dr').focus();
31301            });
31302
31303            return;
31304//        } else if (!UTIL.isNumber(instock) && instock !== '' && UTIL.isEmpty(iid)) {
31305//            GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">' + UTIL.cleanString(instock) + '</b> is not a valid in stock amount.  Please enter a number.</div>', function() {
31306//                $('#inventory-item-form').find('#In_Stock_dr').focus();
31307//            });
31308//
31309//            return;
31310        } else if (!UTIL.isNumber(cost, true) && cost !== '' && UTIL.isEmpty(iid)) {
31311            GLO.Popup.Warning('<div style="padding: 10px;"><b style="font-size: larger;">$' + UTIL.cleanString(cost) + '</b> ' + SA.Resource.IsNotValidCost + '.  ' + SA.Resource.PleaseEnterNumber + '.</div>', function() {
31312                $('#inventory-item-form').find('#Cost_mn').focus();
31313            });
31314
31315            return;
31316        }
31317
31318        var jsonItem = {
31319                            "Inventory_id": iid, "Name_vc": inm, "Vendor_id": vid, "Product_Line_id": plineid
31320                            , "SKU_vc": sku, "UPC_vc": upc, "Inventory_Type_id": itype, "Unit_id": unit, "Size_dr": size
31321                            , "Web_cd": webCode, "For_Retail_fl": rfl, "For_Internal_fl": ifl, "Do_Not_Track_Stock_fl": noTrackStock
31322                            , "Cost_mn": cost, "Price_mn": price, "Employee_Price_mn": eprice
31323                            , "Minimum_Stock_dr": minstock, "In_Stock_dr": instock, "Tax_Rate_pct": tax
31324                            , "Commission_pct": commission, "Description_vc": desc
31325                        };
31326        
31327        if (!UTIL.isEmpty(itype) && itype.substring(0, 1) === 'c') {
31328        	jsonItem.Inventory_Type_id = '';
31329        	jsonItem.Category_id = itype.substring(1);
31330        }
31331        
31332        _saveGiftCard(frm, jsonItem);
31333        _saveShelf(frm, jsonItem);
31334        
31335        GLO.UI.Form.beginProcessing(frm.find('.btnSave'));
31336
31337        var jqxhr = $.ajax({ type: "POST", "url": uri, "cache": false, "data": jsonItem })
31338            .success(function(data, textStatus, jqXHR) {
31339                if (UTIL.Validate.hasPermissionError(data)) { return; }
31340                
31341                frm.find('.btnSave a').css({ "border": "3px solid transparent" });
31342                
31343                GLO.Inventory.Item.updateItemRow(data, iid);
31344                GLO.Inventory.setMaximumProductListRows(false);
31345                
31346                if (!UTIL.isEmpty(jsonItem.Category_id) && UTIL.isEmpty(jsonItem.Inventory_Type_id)) {
31347                	frm.find('#Inventory_Type_id').find('option[value="c' + jsonItem.Category_id + '"]').remove();
31348                }
31349                
31350                var isNewProduct = UTIL.isEmpty(iid);
31351                _setProductListFilterOnSave(data, isNewProduct);
31352                GLO.Inventory.updateHash('product-list');
31353            })
31354            .error(function(jqXHR, textStatus, errorThrown) {
31355                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
31356                GLO.UI.Form.resetProcessing();
31357            });
31358    }
31359	
31360	function _saveGiftCard(jitem, jsonItem) {
31361		//= check if user just changed category (did not go to menu item: Create -> Gift Card, instead just went to Create -> Product or changing existing normal product)
31362		var jtype = jitem.find('#Inventory_Type_id option:selected');
31363		var defaultType = jtype.attr('default_type_id'), defaultCategory = jtype.attr('default_type_category_id');
31364		
31365		if (defaultType == 115 || defaultType == 116 || defaultCategory == 41) {
31366			jsonItem.Is_Gift_Card_fl = 1;
31367		} else {
31368			jsonItem.Is_Gift_Card_fl = 0;
31369		}
31370		
31371		if (UTIL.parseBool(jsonItem.Is_Gift_Card_fl) && jitem.hasClass('is-gift-card')) {
31372			jsonItem.expire_days_sr = UTIL.coalesceInt(jitem.find('#Expire_Days_sr').val());
31373    		jsonItem.min_purchase_mn = UTIL.coalesceMoney(jitem.find('#Min_Purchase_mn').val());
31374    		
31375    		jsonItem.referrer_amount_mn = UTIL.coalesceMoney(jitem.find('#Referrer_Amount_mn').val());
31376    		var referrerInventoryId = jitem.find('#Referrer_Inventory_id').val();
31377    		
31378    		if (referrerInventoryId > 0) {
31379    			jsonItem.referrer_inventory_id = referrerInventoryId;
31380    		}
31381    		
31382    		jsonItem.gift_only_fl = jitem.find('#Gift_Only_fl').prop('checked')
31383    		jsonItem.new_client_only_fl = jitem.find('#New_Client_Only_fl').prop('checked');
31384		}
31385	}
31386	
31387	function _setProductListFilterOnSave(data, isNewProduct) {
31388		var jtbl = $('#inventory-table').find('tbody');
31389		var productCount = jtbl.find('tr').length;
31390		
31391		if (productCount < 20) {
31392			GLO.Inventory.filterClear();
31393			return;
31394		}
31395		
31396		//Step I: filter product list by new/updated item's brand so updated row + all other rows for this brand are displayed.
31397        var jfilter = $('#inventory-header-filter');
31398        var coFilter = '', jd = $(data);
31399        
31400        var pbrand = UTIL.cleanString(jd.find('.item-vendor').attr('vendor_id'));
31401        var pline = UTIL.cleanString(jd.find('.item-product-line').attr('product_line_id'));
31402        
31403        if (pline !== '' && jtbl.find('.item-product-line[product_line_id="' + pline + '"]').length > 4) {
31404        	coFilter = 'p' + pline;
31405        } else if (pbrand !== '') {
31406        	coFilter = 'v' + pbrand;
31407        }
31408        
31409        jfilter.find('#Filter_Company').find('option[value="' + coFilter + '"]').attr('selected', 'selected');
31410        
31411        //Step II: Filter Product List by Category/Type
31412        	//Step II-A: Lookup
31413	        var pcatetory = UTIL.cleanString(jd.find('.item-type-category').attr('type_category_id'));
31414	        var psubcatetory = UTIL.cleanString(jd.find('.item-type').attr('type_id'));
31415	        
31416	        var jfcategory = jfilter.find('#Filter_Category');
31417	        var fcategory = jfcategory.val();
31418	        
31419	        //Step II-B: if (category filter already exists) or (on saved product brand is empty but category exists)
31420	        if (!UTIL.isEmpty(fcategory) || (UTIL.isEmpty(pbrand) && (pcatetory !== 'c' || psubcatetory !== 't'))) {
31421	        	var categoryProductCount = jtbl.find('.item-type-category[type_category_id="' + pcatetory + '"]').length;
31422	        	var subCategoryProductCount = jtbl.find('.item-type[type_id="' + psubcatetory + '"]').length;
31423	        	var categoryFilter = '';
31424	        	
31425	        	if (subCategoryProductCount > 9 || (subCategoryProductCount > 4 && categoryProductCount > 49) ) {
31426	        		categoryFilter = 't' + psubcatetory;
31427	        	} else if (categoryProductCount > 0) {
31428	        		categoryFilter = 'c' + pcatetory;
31429	        	}
31430	        	
31431	        	jfcategory.find('option[value="' + categoryFilter + '"]').attr('selected', 'selected');
31432	        }
31433	    
31434	    
31435	    //Step III: Filter Product List by Stock Level (gold package only): if has stock level filter + saved product does NOT match filter -> clear stock-level filter
31436	    if (GLO.Info.providerPackage !== 4) {
31437	    	var jfStockLevel = jfilter.find('#Filter_Stock_Level');
31438	    	var fStockLevel = jfStockLevel.val();
31439	    	
31440	    	if (!UTIL.isEmpty(fStockLevel)) {
31441	    		var amount = UTIL.coalesceFloat(jd.find('.item-in-stock').text());
31442	    		var desired = UTIL.coalesceFloat(jd.find('.item-minimum-stock').text());
31443	    		
31444	    		if (!_isInStockLevel(fStockLevel, amount, desired)) {
31445	    			jfStockLevel.val('');
31446	    		}
31447	    	}
31448	    }
31449	    
31450	    //Step IV: Wrap Up
31451	    GLO.Inventory.filterOnChange(jfilter);
31452	}
31453	
31454	function _isInStockLevel(filter, amount, desired) {
31455		if (filter === 'in' && amount > 0) {
31456            return true;
31457        } else if (filter === 'out' && amount <= 0) {
31458            return true;
31459        } else if (UTIL.isNumber(desired)) {
31460            desired = parseFloat(desired);
31461            
31462            if (filter === 'low' && desired > amount) {
31463                return true;
31464            } else if (filter === 'high' && amount > desired) {
31465            	return true;
31466            }
31467        }
31468        
31469        return false;
31470	}
31471	
31472	function _isTrackStock(inventoryId) {
31473		if (!UTIL.isEmpty(inventoryId)) {
31474			var tr = $('#inventory-table tbody tr#' + inventoryId);
31475			
31476			if (GLO.Info.providerPackage === 4) {
31477				if (UTIL.isEmpty(inventoryId)) {
31478					return !GLO.Inventory.doNotTrackStock;
31479				}
31480				
31481				if (tr.legth === 0) {
31482					return !GLO.Inventory.doNotTrackStock;
31483				} else {
31484	        		return UTIL.parseBool(tr.attr('track_stock_fl'));
31485	        	}
31486	        } else if (tr.find('#Track_Stock_fl').prop('checked') || tr.find('#Track_Stock_fl:visible').length === 0) {
31487	        	return true;
31488	        }
31489        } else {
31490        	if (!GLO.Inventory.doNotTrackStock || GLO.Info.providerPackage == 2) {
31491        		return true;
31492        	}
31493        }
31494        
31495        return false;
31496	}
31497	
31498    _conIItem.updateItemRow = function(tr, inventoryId) {
31499        if (tr) {
31500            var tbl = $('#inventory-table tbody');
31501            tr = $(tr);
31502            
31503            //$.tablesorter.clearTableBody(tbl[0]);			//requires latest version of tablesorter
31504            
31505            if (!UTIL.isEmpty(inventoryId)) {
31506                tr.css({ "background-color": "rgba(255,255,0,.4)" }).attr('title', SA.Resource.ProductRecentlyUpdated);
31507
31508                var oldtr = tbl.find('tr#' + inventoryId).attr('id', 'UPDATED');
31509                oldtr.after(tr);
31510                oldtr.addClass('hideXX').remove();            //~ the 'hide' is there so the row isn't re-displayed by the tablesorter plugin when a sort is performed after an update.
31511            } else {
31512                tr.css({ "background-color": "Pink" }).attr('title', SA.Resource.ProductRecentlyAdded);
31513
31514                tbl.find('.no-items').remove();
31515                tbl.prepend(tr);
31516            }
31517            
31518            //var isDoResort = true;						//requires latest version of tablesorter
31519            //tbl.trigger('update', isDoResort);
31520            //tbl.trigger('updateAll', isDoResort);
31521        }
31522    }
31523    
31524    _conIItem.openHelp_NotForSale = function(thisElement) {
31525    	var ojInfo = GLO.UI.openHelp(thisElement);
31526    	var jpop = ojInfo.getPopup();
31527    	
31528    	jpop.css({ "background-color": "#275264" });
31529    	jpop.find('h2').css({ "color": "#4F81BD", "background-color": "#222", "border-radius": "8px", "padding": "9px", "margin-top": "-20px", "margin-bottom": "15px", "margin-left": "-25px" });
31530    	
31531    	jpop.find('.msg p').remove();
31532    	window.setTimeout(function() { ojInfo.realign(); }, 100);
31533    }
31534    
31535    _conIItem.remove = function() {
31536        var trs = $('#inventory-table').find('tbody .item-row-box input:checked').closest('tr:visible');
31537        
31538        if (trs.length == 0) {
31539            GLO.Popup.Warning(SA.Resource.PleaseCheckBox);
31540        } else {
31541            var h2 = 'Delete Product', msg = '', jnm, tr, ids = '';
31542            if (trs.length > 1) { h2 += 's'; }
31543            
31544            for (var i=0; i < trs.length; i++) {
31545                ids += trs.eq(i).attr('id') + ',';
31546                jnm = trs.eq(i).find('.item-name');
31547                
31548                msg += '<li style="float: none; line-height: 180%;">' + UTIL.coalesce(jnm.attr('title'), jnm.text()) + '</li>';
31549            }
31550
31551            ids = ids.substring(0, ids.length-1);
31552            msg = '<div> <h2>' + h2 + '?</h2> <ul style="text-align: center; margin-left: 0; margin-top: 10px; font-weight: bold; font-size: large;">' + msg + '</ul> </div>';
31553            
31554            var ojpop = new GLO.Popup.Confirm(msg, function() {
31555                GLO.Inventory.Item.removeConfirmed(ids);
31556            });
31557            
31558            var jpop = ojpop.getPopup();
31559            
31560            if (jpop.height() > innerHeight * .9) {
31561            	jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) });
31562            	ojpop.realign();
31563            }
31564        }
31565    }
31566    
31567    _conIItem.removeProduct = function() {
31568    	var j = $('#inventory-item-form');
31569        var id = j.find('#Inventory_id').val();
31570        var nm = j.find('#Name_vc').val()
31571        
31572        if (GLO.Info.isMobile()) {
31573        	var msg = 'Delete the product?';
31574        } else {
31575        	var msg = 'Are you sure you want to delete the product?';
31576        }
31577        
31578        msg = '<div class="friendly-msg2">' + msg + '<br/> <b style="color: #4F81BD;">' + nm + '</b></div>';
31579        msg = '<div> <h2 class="friendly-msg2">' + SA.Resource.Delete + ' ' + SA.Resource.Product + '?</h2>' + msg + '</div>';
31580        
31581        var btn = j.find('.btnDelete');
31582        GLO.UI.Form.beginProcessing(btn);
31583        
31584        var fnYes = function() { GLO.Inventory.Item.removeConfirmed(id); };
31585        var fnNo = function() { GLO.UI.Form.resetProcessing(btn); }
31586        
31587        var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup();
31588        
31589        if (jpop.height() > innerHeight * .9) {
31590        	jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) });
31591        }
31592    }
31593    
31594    _conIItem.removeConfirmed = function(ids) {
31595        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemDelete';
31596        //if (UTIL.isEmpty(ids)) { ids = $('#inventory-item-edit #Inventory_id').val(); }
31597        GLO.UI.Form.beginProcessing( $('#inventory-item-edit .btnDelete, #inventory-product-list-buttons .btnDelete') );
31598        
31599        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "ids": ids } })
31600            .success(function(data, textStatus, jqXHR) {
31601                if (UTIL.Validate.hasPermissionError(data)) { return; }
31602                
31603                var arr = ids.split(',');
31604                var tbody = $('#inventory-table tbody');
31605                
31606                for (var i = 0; i < arr.length; i++) {
31607                    tbody.find('tr#' + arr[i]).attr('id', 'REMOVED').addClass('hideXX').remove();            //~ the 'hide' is there so the row isn't re-displayed by the tablesorter plugin when a sort is performed after an update.
31608                }
31609                
31610                GLO.Inventory.setMaximumProductListRows(false);
31611                GLO.Inventory.setFooter(0);
31612                GLO.Inventory.updateHash('product-list');
31613            })
31614            .error(function(jqXHR, textStatus, errorThrown) {
31615                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
31616                GLO.UI.Form.resetProcessing();
31617            });
31618    }
31619
31620    _conIItem.selectAll = function(checkbox) {
31621        var jcheckbox = $(checkbox);
31622        var isChecked = jcheckbox.prop('checked');
31623        var tbl = jcheckbox.closest('table');
31624
31625        tbl.find('.item-row-box:visible input:checkbox').each(function() {
31626            $(this).prop('checked', isChecked);
31627        });
31628    }
31629    
31630    _conIItem.viewHistory = function(event) {
31631    	var uri = GLO.Link.Page.Provider.Home + 'reports/inventory/#tab=product-history&id=' + GLO.Uri.hash('id');
31632    	
31633    	if (event.ctrlKey) {
31634    		var childWindow = UI.openChildWindow(uri, '', true);
31635    	} else {
31636    		document.location = uri;
31637    	}
31638    }
31639
31640	_conIItem.addItemImage = function() {
31641		var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateItemImage';
31642        // GLO.UI.Form.beginProcessing();
31643        var frm = $('#inventory-item-form');
31644		var iid = frm.find('#Inventory_id').val();
31645		var itemImageFilename = $('#item-image-path').val();
31646
31647        var jsonData = {
31648			"Inventory_id": iid, "Item_Image_path_vc": itemImageFilename
31649		};
31650
31651        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData})
31652            .success(function(data, textStatus, jqXHR) {
31653                if (UTIL.Validate.hasPermissionError(data)) { return; }
31654                GLO.Inventory.Item.getItemImages(iid);
31655
31656            })
31657            .error(function(jqXHR, textStatus, errorThrown) {
31658                new GLO.Popup.Error('Unable to save image at this time.  Please try again later.');
31659                GLO.UI.Form.resetProcessing();
31660            });		
31661	}
31662
31663	_conIItem.removeItemImage = function(itemImageId) {
31664		var uri = GLO.Link.Page.Provider.Home + 'Inventory/RemoveItemImage';
31665        // GLO.UI.Form.beginProcessing();
31666        
31667        var frm = $('#inventory-item-form');
31668		var iid = frm.find('#Inventory_id').val();
31669		
31670        var jsonData = {
31671			"Inventory_id": iid,
31672			"Inventory_Image_id": itemImageId
31673		};
31674
31675
31676        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData})
31677            .success(function(data, textStatus, jqXHR) {
31678                if (UTIL.Validate.hasPermissionError(data)) { return; }
31679                GLO.Inventory.Item.getItemImages(iid);
31680
31681            })
31682            .error(function(jqXHR, textStatus, errorThrown) {
31683                new GLO.Popup.Error('Unable to remove image at this time.  Please try again later.');
31684                GLO.UI.Form.resetProcessing();
31685            });		
31686	}
31687
31688	_conIItem.setPrimaryItemImage = function(itemImageId) {
31689		var uri = GLO.Link.Page.Provider.Home + 'Inventory/SetPrimaryItemImage';
31690        // GLO.UI.Form.beginProcessing();
31691        
31692        var frm = $('#inventory-item-form');
31693		var iid = frm.find('#Inventory_id').val();
31694		
31695        var jsonData = {
31696			"Inventory_id": iid,
31697			"Inventory_Image_id": itemImageId
31698		};
31699
31700
31701        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData})
31702            .success(function(data, textStatus, jqXHR) {
31703                if (UTIL.Validate.hasPermissionError(data)) { return; }
31704                GLO.Inventory.Item.getItemImages(iid);
31705
31706            })
31707            .error(function(jqXHR, textStatus, errorThrown) {
31708                new GLO.Popup.Error('Unable to set main image at this time.  Please try again later.');
31709                GLO.UI.Form.resetProcessing();
31710            });		
31711	}	
31712	    
31713    _conIItem.launchImageUpload = function(event) {
31714		$('#inventory-edit-image-upload-container').modal();
31715		var jModal = $('#simplemodal-container #inventory-edit-image-upload-container');
31716		var h = jModal.find('#inventory-edit-image-upload-container').height();
31717        var w = jModal.find('#inventory-edit-image-upload-container').width();
31718        
31719        $.modal.update(h,w);
31720        $(window).resize(); 
31721
31722		if (GLO.Info.isMobile()) {
31723			$('#simplemodal-container').draggable({disable:true});
31724		}
31725    }
31726
31727	_conIItem.launchManageImages= function(event) {
31728
31729		GLO.UI.loadBulkitCss();
31730
31731		$('#inventory-manage-images-container').modal();
31732		var jModal = $('#simplemodal-container #inventory-manage-images-container');
31733		var h = $(window).height() * 0.8;
31734        var w = $(window).width() * 0.8;
31735        
31736        $.modal.update(h,w);
31737        $(window).resize(); 
31738		$('.modalCloseImg').css("margin-top","20px");
31739		$('.modalCloseImg').css("margin-right","20px");
31740		$('.modalCloseImg').on("click",function() { GLO.Inventory.Item.closeManageImages(); });
31741		
31742		if (GLO.Info.isMobile()) {
31743			$('#simplemodal-container').draggable({disable:true});
31744		}
31745		$('#simplemodal-container').css("overflow-y","auto");
31746
31747        var frm = $('#inventory-item-form');
31748		var iid = frm.find('#Inventory_id').val();
31749
31750		GLO.Inventory.Item.getItemImages(iid);
31751    }
31752
31753	_conIItem.closeManageImages = function() {
31754
31755		$('.modalCloseImg').off("click");
31756		GLO.UI.removeBulkitCss();
31757	}
31758
31759
31760	_conIItem.uploadImageAndResize = function () {
31761		//define the width to resize e.g 800px
31762		var resize_width = 800;//without px
31763
31764		//get the image selected
31765		var item = document.querySelector('#uploader').files[0];
31766
31767		//create a FileReader
31768		var reader = new FileReader();
31769
31770		//image turned to base64-encoded Data URI.
31771		reader.readAsDataURL(item);
31772		reader.name = item.name;//get the image's name
31773		reader.size = item.size; //get the image's size
31774		reader.onload = function(event) {
31775			var img = new Image();//create a image
31776			img.src = event.target.result;//result is base64-encoded Data URI
31777			img.name = event.target.name;//set name (optional)
31778			img.size = event.target.size;//set size (optional)
31779			img.onload = function(el) {
31780				var elem = document.createElement('canvas');//create a canvas
31781
31782				//scale the image to 800 (width) and keep aspect ratio
31783				var scaleFactor = resize_width / el.target.width;
31784				elem.width = resize_width;
31785				elem.height = el.target.height * scaleFactor;
31786
31787				//draw in canvas
31788				var ctx = elem.getContext('2d');
31789				ctx.drawImage(el.target, 0, 0, elem.width, elem.height);
31790
31791				//get the base64-encoded Data URI from the resize image
31792				var srcEncoded = ctx.canvas.toDataURL('image/png', 1);
31793
31794				//assign it to thumb src
31795				document.querySelector('#item-image').src = srcEncoded;
31796
31797				//image modal
31798				$.modal.update(1000,1000);
31799				$(window).resize(); 
31800				$('#simplemodal-container').css("overflow-y","auto");
31801				$('#simplemodal-container').draggable();
31802				$('.modalCloseImg').css("margin-top","20px");
31803				$('.modalCloseImg').css("margin-right","20px");
31804				
31805				//hide upload button and show crop button
31806				// $('#uploaderLabel').addClass('hide');
31807				// $('#uploader').addClass('is-hidden');
31808				// $('#btnUploadResize').addClass('is-hidden');
31809				$('#btnCrop').removeClass('is-hidden');
31810				// $('#previewLabel').removeClass('hide');
31811				// $('.image-preview').removeClass('hide');
31812
31813				//init cropper js
31814				var $image = $('#item-image');
31815
31816				$image.cropper({
31817				aspectRatio: 1 / 1,
31818				preview:'.image-preview',
31819				crop: function(event) {
31820					// console.log(event.detail.x);
31821					// console.log(event.detail.y);
31822					// console.log(event.detail.width);
31823					// console.log(event.detail.height);
31824					// console.log(event.detail.rotate);
31825					// console.log(event.detail.scaleX);
31826					// console.log(event.detail.scaleY);
31827				}
31828				});
31829
31830				$image.on({
31831					ready: function (e) {
31832					  console.log(e.type);
31833					  var cropBoxData =  $image.cropper('getCropBoxData');
31834					  cropBoxData.width = 800;
31835					  cropBoxData.height = 800;
31836					  $image.cropper('setCropBoxData', cropBoxData);					  
31837					},
31838					cropstart: function (e) {
31839					  console.log(e.type, e.detail.action);
31840					},
31841					cropmove: function (e) {
31842					  console.log(e.type, e.detail.action);
31843					},
31844					cropend: function (e) {
31845					  console.log(e.type, e.detail.action);
31846					},
31847					crop: function (e) {
31848					  console.log(e.type);
31849					},
31850					zoom: function (e) {
31851					  console.log(e.type, e.detail.ratio);
31852					}
31853				  });		
31854
31855
31856				/*Now you can send "srcEncoded" to the server and
31857				convert it to a png o jpg. Also can send
31858				"el.target.name" that is the file's name.*/
31859				
31860				/*Also if you want to download tha image use this*/
31861				/*
31862				var a = document.createElement("a"); //Create <a>
31863				a.href =  srcEncoded; //set srcEncoded as src
31864				a.download = "myimage.png"; //set a name for the file
31865				a.click();
31866			
31867			*/		
31868			}
31869		}
31870	}
31871    
31872	_conIItem.cropImage = function() {
31873
31874		var $image = $('#item-image');
31875
31876		// Get the Cropper.js instance after initialized
31877		var cropper = $image.data('cropper');
31878		var cropperData = cropper.getData();
31879		var srcCroppedEncoded = cropper.getCroppedCanvas().toDataURL('image/png', 1);
31880		$image.cropper('destroy');
31881		
31882		document.querySelector('#item-image').src = srcCroppedEncoded;
31883
31884		//hide crop button and show save button
31885		$('#btnCrop').addClass('is-hidden');
31886		$('#btnSaveItemImage').removeClass('is-hidden');
31887		$('#btnSaveItemImage').on("click",function() { GLO.Inventory.Item.saveImage(srcCroppedEncoded,cropperData.width); });
31888
31889	}
31890
31891	//used by product page to upload product image for store
31892	_conIItem.saveImage = function(data,width) {
31893
31894		//remove the attached handler
31895		$('#btnSaveItemImage').off("click");
31896		
31897		var jcontainer = $('#uploader');
31898		
31899		//reset error
31900		$('#itemImageUploadErrorMessage').addClass('is-hidden');
31901
31902		var fnCallback = function(jcontainer, fileName, imgId, imgSize) {
31903			if (fileName!=null && fileName.length > 0) {
31904				var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName;
31905				// console.log(img_path);
31906
31907				//clear the image display
31908				document.querySelector('#item-image').src ='';
31909				$('#btnSaveItemImage').addClass('is-hidden');
31910				// $('#btnCloseModal').addClass('is-hidden');			
31911
31912				//set hidden field value
31913				$('#item-image-path').val(fileName);
31914				//close the modal
31915				// $('.simplemodal-close').click();			
31916
31917				//display the image preview
31918				// $('.item-existing-image-preview-container').removeClass('hide');
31919				// $('.item-existing-image-preview').attr("src",img_path);
31920				// $('.item-image-fullsize-link').attr("href",img_path);
31921
31922				GLO.Inventory.Item.addItemImage();
31923			}
31924			else {
31925				//display error
31926				$('#itemImageUploadErrorMessage').removeClass('is-hidden');
31927			}
31928		}
31929		
31930		if (SA.Uploader.uploadImage(data, 'png', width, jcontainer, fnCallback)) {
31931			return true;
31932		}
31933	}
31934
31935	_conIItem.removeImageAskConfirmation= function(itemImageId) {
31936
31937        if (GLO.Info.isMobile()) {
31938        	var msg = 'Remove the image?';
31939        } else {
31940        	var msg = 'Are you sure you want to remove the image?';
31941        }
31942        
31943        msg = '<div class="friendly-msg2">' + msg + '</div>';
31944        msg = '<div> <h2 class="friendly-msg2">Remove Image?</h2>' + msg + '</div>';
31945        
31946        var fnYes = function() { GLO.Inventory.Item.removeImage(itemImageId); };
31947        var fnNo = function() { GLO.UI.Form.resetProcessing(); }
31948        
31949        var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup();
31950        
31951        if (jpop.height() > innerHeight * .9) {
31952        	jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) });
31953        }
31954	}
31955
31956	_conIItem.mainImageAskConfirmation= function(itemImageId) {
31957
31958        if (GLO.Info.isMobile()) {
31959        	var msg = 'Change the main image?';
31960        } else {
31961        	var msg = 'Are you sure you want to change the main image?';
31962        }
31963        
31964        msg = '<div class="friendly-msg2">' + msg + '</div>';
31965        msg = '<div> <h2 class="friendly-msg2">Change Main Product Image?</h2>' + msg + '</div>';
31966        
31967        var fnYes = function() { GLO.Inventory.Item.setPrimaryItemImage(itemImageId); };
31968        var fnNo = function() { GLO.UI.Form.resetProcessing(); }
31969        
31970        var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup();
31971        
31972        if (jpop.height() > innerHeight * .9) {
31973        	jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) });
31974        }
31975	}	
31976
31977	_conIItem.removeImage = function(itemImageId) {
31978
31979		GLO.Inventory.Item.removeItemImage(itemImageId);
31980	}
31981
31982	_conIItem.getItemImages = function(inventoryId) {
31983		var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemImages?id=' + inventoryId;
31984	
31985		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
31986			.done(function(data, textStatus, jqXHR) {
31987				window.onbeforeunload = null;
31988				if(data!=null && data!== '') {
31989					var itemImages = data;
31990					if (itemImages.length > 0) {
31991						generateItemImagesGrid(itemImages);
31992					}
31993					else {
31994						//display blank state
31995						generateItemImagesGridBlankState();
31996					}
31997				  } else {
31998					new GLO.Popup.Error('Could not get the product images');
31999				  }				
32000			})
32001			.fail(function(jqXHR, textStatus, errorThrown) {
32002				GLO.UI.Form.resetProcessing(); 		
32003				new GLO.Popup.Error('Could not get the product images');
32004			});
32005	}	
32006
32007	//render the item images grid
32008	var generateItemImagesGrid = function(itemImages) {
32009		var itemImagesGrid = $('#item-images-grid');
32010		var productPlaceholderImage = 'product-image-placeholder.png';
32011		itemImagesGrid.html("");
32012
32013		itemImages.forEach(function(itemImage) {
32014		  
32015		  var productDescPreview = '';
32016		  var img_path=GLO.Data.cdnDirectory + 'upload-folder/' + productPlaceholderImage;
32017
32018		  if (itemImage.ImagePath.length > 0) {
32019			img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemImage.ImagePath;
32020		  } 
32021		 
32022		  var imageCardEl = document.createElement("div");
32023		  imageCardEl.className = "column is-one-fifth-desktop is-one-quarter-tablet";
32024		  imageCardEl.innerHTML = (`<div class="card" data-id="${itemImage.ItemImageId}">
32025					<div class="card-image">
32026						<figure class="image is-square">
32027							<img src="${img_path}" alt="">
32028						</figure>
32029						<div class="card-content is-overlay is-clipped is-pulled-right is-pulled-top ${itemImage.IsPrimary ? '':'is-hidden'}">
32030							<span class="tag is-info">
32031								Main Image
32032							</span>
32033						</div>
32034					</div>
32035					<footer class="card-footer">
32036						<a class="card-footer-item">
32037							<a href="#" class="card-footer-item is-size-7 ${itemImage.IsPrimary ? 'is-hidden':''}" onclick="GLO.Inventory.Item.mainImageAskConfirmation(${itemImage.ItemImageId})">Set as Main</a>
32038							<a href="#" class="card-footer-item has-text-danger is-size-7" onclick="GLO.Inventory.Item.removeImageAskConfirmation(${itemImage.ItemImageId})">Remove</a>
32039						</a>
32040					</footer>
32041				</div>`);
32042	
32043				itemImagesGrid.append(imageCardEl);
32044		});
32045	}	
32046
32047	var generateItemImagesGridBlankState = function() {
32048
32049		var itemImagesGrid = $('#item-images-grid');
32050		itemImagesGrid.html("");
32051		var imageCardEl = document.createElement("div");
32052		imageCardEl.className = "column";
32053		imageCardEl.innerHTML = (`<span id="item-images-grid-blank-state" class="is-size-3 has-text-grey">Click Upload an image to add a new product image</span>`);
32054		itemImagesGrid.append(imageCardEl);
32055	}
32056
32057	_conIItem.Options = (function() {
32058		function _conIItemOptions() { }
32059		const _MAX_ITEM_OPTIONS = 3;
32060		var _itemId;
32061		var _itemOptionTypesArray = [{"attribute_id":"1","attribute_type_vc":"Choose One - Text"},{"attribute_id":"2","attribute_type_vc":"Choose One - Color"}];
32062		var _itemOptionsArray = [];
32063		var _itemVariantsArray = [];
32064		var _itemSelectedItemOptionColorSwatch;
32065		var _itemSelectedVariant;
32066
32067		var _tagsInputOptions = {
32068			allowDuplicates: false,
32069			caseSensitive: false,
32070			clearSelectionOnTyping: false,
32071			closeDropdownOnItemSelect: true,
32072			delimiter: ',',
32073			freeInput: true,
32074			highlightDuplicate: true,
32075			highlightMatchesString: true,
32076			itemValue: undefined,
32077			itemText: undefined,
32078			maxTags: 20,
32079			maxChars: 99,
32080			minChars: 1,
32081			noResultsLabel: 'No results found',
32082			placeholder: '',
32083			removable: true,
32084			searchMinChars: 1,
32085			searchOn: 'text',
32086			selectable: true,
32087			source: undefined,
32088			tagClass: 'is-link',
32089			trim: true
32090		};
32091
32092		var getItemOptionCsv = function(itemOption) {
32093			var valueArray = [];
32094			itemOption.ItemAttributeValues.forEach(iov => {
32095				valueArray.push(iov.Value);
32096			});
32097			var csv = '';
32098			csv = valueArray.join(',');
32099			return csv;
32100		}
32101
32102		//render the item images grid
32103		var generateItemImagePickerGrid = function(itemImages) {
32104			var itemImagesGrid = $('#item-variation-image-choices');
32105			var productPlaceholderImage = 'product-image-placeholder.png';
32106			itemImagesGrid.html("");
32107
32108			itemImages.forEach(function(itemImage) {
32109			
32110			var productDescPreview = '';
32111			var img_path=GLO.Data.cdnDirectory + 'upload-folder/' + productPlaceholderImage;
32112
32113			if (itemImage.ImagePath.length > 0) {
32114				img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemImage.ImagePath;
32115			} 
32116			
32117			var imageCardEl = document.createElement("div");
32118			imageCardEl.className = "column is-one-fifth-desktop is-one-quarter-tablet";
32119			imageCardEl.innerHTML = (`<div class="card" data-id="${itemImage.ItemImageId}">
32120						<div class="card-image">
32121							<figure class="image is-square">
32122								<img src="${img_path}" alt="">
32123							</figure>
32124							<div class="card-content is-overlay is-clipped is-pulled-right is-pulled-top ${itemImage.IsPrimary ? '':'is-hidden'}">
32125								<span class="tag is-info">
32126									Main Image
32127								</span>
32128							</div>
32129						</div>
32130						<footer class="card-footer">
32131							<a class="card-footer-item">
32132								<a href="#" class="card-footer-item has-text-danger is-size-7" onclick="GLO.Inventory.Item.Options.setImageForVariation(${itemImage.ItemImageId},'${itemImage.ImagePath}')">Select</a>
32133							</a>
32134						</footer>
32135					</div>`);
32136		
32137					itemImagesGrid.append(imageCardEl);
32138			});
32139		}		
32140
32141		var generateItemImagePickerGridBlankState = function() {
32142
32143			var itemImagesGrid = $('#item-variation-image-choices');
32144			itemImagesGrid.html("");
32145			var imageCardEl = document.createElement("div");
32146			imageCardEl.className = "column";
32147			imageCardEl.innerHTML = (`<span id="item-images-grid-blank-state" class="is-size-3 has-text-grey">Please go to product details and upload images for product</span>`);
32148			itemImagesGrid.append(imageCardEl);
32149		}
32150
32151		var attachBulmaTagsInput = function(elem) {
32152			if (typeof elem.BulmaTagsInput == 'undefined') {
32153			
32154				new BulmaTagsInput(elem,_tagsInputOptions);
32155				
32156				//attach handlers
32157				elem.BulmaTagsInput().on('before.remove', function(data) {
32158					console.log(data);
32159					return true;
32160				});
32161				elem.BulmaTagsInput().on('after.add', function(data) {
32162					console.log(data);
32163					return true;
32164				});
32165			}
32166		}
32167
32168		var generateItemVariationsBlankState = function() {
32169
32170			var itemVariationsList = $('#variations-list');
32171
32172			var itemVariationsInner = itemVariationsList.find('.item-variations-inner');
32173			itemVariationsInner.html("<p>Product variations will be auto-generated based on the product options added.</p>");
32174
32175		}
32176
32177		var doVariationsHaveInventoryIds = function() {
32178
32179			var retVal = false;
32180
32181			if (_itemVariantsArray == null || typeof _itemVariantsArray == 'undefined' || _itemVariantsArray.length == 0) {
32182				return false;
32183			}
32184			var variantsWithInventoryIds = _itemVariantsArray.filter(iv=> iv.VariantInventoryId > 0);
32185			if (variantsWithInventoryIds.length > 0) {
32186				retVal = true;
32187			}
32188
32189			return retVal;
32190		}
32191
32192		_conIItemOptions.init = function(itemId) {
32193			_itemId = itemId;
32194			GLO.Inventory.Item.Options.getItemOptions(_itemId);
32195			GLO.Inventory.Item.Options.getItemVariations(_itemId);
32196		}
32197
32198		_conIItemOptions.getOptionType = function(optionTypeName) {
32199			var selectedOptionType;
32200			for (var i = 0; i < _itemOptionTypesArray.length; i++) {
32201				if (_itemOptionTypesArray[i].attribute_type_vc == optionTypeName || _itemOptionTypesArray[i].attribute_id == optionTypeName){
32202					selectedOptionType = _itemOptionTypesArray[i];
32203				  break;
32204				}
32205			  }
32206
32207			return selectedOptionType;
32208		}
32209
32210		_conIItemOptions.generateNewOption = function(elem) {
32211
32212			var itemOptionsList = $('#options-list');
32213
32214			var newOptionEl = document.createElement("div");
32215			newOptionEl.className = "box m-3 item-option";
32216			newOptionEl.innerHTML = (`<div class="option-edit">
32217					<div class="columns">
32218						<div class="column is-half">
32219							<div class="field">
32220								<label class="label is-pulled-left">Name</label>
32221								<div class="control required option-name">
32222									<input class="input item-option-name" placeholder="Option name for store display e.g. Size">
32223								</div>
32224							</div>
32225						</div>
32226						<div class="column is-half">
32227							<div class="field">
32228								<label class="label is-pulled-left">Type</label>
32229								<div class="control required option-type">
32230									<div class="select is-fullwidth">
32231										<select class="select-option-type" onchange="GLO.Inventory.Item.Options.changeOptionType(this)">
32232											<option value="1">Choose One - Text</option>
32233											<option value="2">Choose One - Color</option>
32234										</select>
32235									</div>
32236								</div>
32237							</div>
32238						</div>
32239					</div>
32240					<div class="columns">
32241						<div class="column">
32242							<div class="field">
32243								<label class="label is-pulled-left">Values</label> 
32244							</div>
32245						</div>
32246					</div>
32247					<div class="option-edit-fields">
32248						<div class="columns">
32249							<div class="column">
32250								<div class="field">
32251									<div class="control required text-option-value">
32252										<div class="bulma-tags">
32253												<input class="input item-option-value" type="tags" placeholder="Add values e.g. Small, Medium, Large">
32254											</div>
32255										</div>								
32256									</div>
32257								</div>
32258							</div>					
32259						</div>
32260					</div>
32261					<div class="option-preview is-hidden">
32262						<!-- this is the preview of the option -->
32263					</div>				
32264					<div class="columns option-actions">
32265						<div class="column is-one-fifth">
32266							<div class="buttons is-justify-content-left">
32267								<button class="button is-danger has-text-weight-normal is-light" onclick="GLO.Inventory.Item.Options.removeOptionAskConfirmation(this)">Remove</button>
32268							</div>
32269						</div>
32270						<div class="column">
32271
32272						</div>
32273						<div class="column is-one-third">
32274							<div class="buttons is-justify-content-right">
32275								<button class="button has-text-weight-normal" onclick="GLO.Inventory.Item.Options.cancelOptionEdit(this)">Cancel</button>
32276								<button class="button is-info has-text-weight-normal" onclick="GLO.Inventory.Item.Options.saveOption(this)">Save</button>
32277								<button class="button is-info has-text-weight-normal is-hidden" onclick="GLO.Inventory.Item.Options.saveOption(this)">Edit</button>							
32278							</div>
32279						</div>
32280					</div>`);
32281	
32282			$(newOptionEl).insertBefore($('.create-new-option'));
32283			
32284			GLO.Inventory.Item.Options.checkOptionThreshold();
32285
32286			//attach tags input
32287			var tagEl = $(newOptionEl).find('input[type="tags"]')[0];
32288			attachBulmaTagsInput(tagEl);
32289			
32290		}			
32291
32292		_conIItemOptions.checkOptionThreshold = function() {
32293
32294			var itemOptionsAdded = $('#options-list').find('.item-option').length;
32295			if (itemOptionsAdded < _MAX_ITEM_OPTIONS) {
32296				$('.create-new-option').removeClass("is-hidden");
32297			}
32298			else {
32299				$('.create-new-option').addClass("is-hidden");
32300			}
32301		}
32302
32303		_conIItemOptions.getItemOptions = function(inventoryId) {
32304			var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemAttributes?id=' + inventoryId;
32305		
32306			var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
32307				.done(function(data, textStatus, jqXHR) {
32308					window.onbeforeunload = null;
32309					if(data!=null && data!== '') {
32310						var _itemOptionsArray = JSON.parse(data.data);
32311						if (_itemOptionsArray.length > 0) {
32312							GLO.Inventory.Item.Options.generateItemOptionsList(_itemOptionsArray);
32313						}
32314						else {
32315							//display blank state
32316							//which it does by default
32317						}
32318					  } else {
32319						new GLO.Popup.Error('Could not get the product options. Please refresh page and try again.');
32320					  }				
32321				})
32322				.fail(function(jqXHR, textStatus, errorThrown) {
32323					GLO.UI.Form.resetProcessing(); 		
32324					new GLO.Popup.Error('Could not get the product options. Please refresh page and try again.');
32325				});			
32326		}			
32327
32328		_conIItemOptions.getItemVariations = function(inventoryId) {
32329			var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemVariations?id=' + inventoryId;
32330		
32331			var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
32332				.done(function(data, textStatus, jqXHR) {
32333					window.onbeforeunload = null;
32334					if(data!=null && data!== '') {
32335						_itemVariantsArray = JSON.parse(data.data);
32336						if (_itemVariantsArray.length > 0) {
32337							GLO.Inventory.Item.Options.generateItemVariationsList(_itemVariantsArray);
32338						}
32339						else {
32340							//display blank state
32341							generateItemVariationsBlankState();
32342						}
32343					  } else {
32344						new GLO.Popup.Error('Could not get the product variants. Please refresh page and try again.');
32345					  }				
32346				})
32347				.fail(function(jqXHR, textStatus, errorThrown) {
32348					GLO.UI.Form.resetProcessing(); 		
32349					new GLO.Popup.Error('Could not get the product variants. Please refresh page and try again.');
32350				});			
32351		}
32352
32353		var resetItemOptionsList = function() {
32354
32355			var itemOptionsList = $('#options-list');
32356			itemOptionsList.html("");
32357
32358			var addNewOptionEl = document.createElement("div");
32359			addNewOptionEl.className="box m-3 create-new-option";
32360			addNewOptionEl.innerHTML=(`
32361            <div class="buttons is-justify-content-center">
32362                <button class="button is-light" onclick="GLO.Inventory.Item.Options.addNewOptionAskConfirmation(this)">Add New option</button>
32363            </div>`);
32364
32365			itemOptionsList.append(addNewOptionEl);
32366		}
32367	
32368
32369		_conIItemOptions.generateItemOptionsList = function(itemOptions) {
32370			
32371			resetItemOptionsList();
32372
32373			itemOptions.forEach(itemOption => {
32374				if (itemOption.AttributeTypeCode == 1) {
32375					GLO.Inventory.Item.Options.generateTextOption(itemOption);
32376				}
32377				if (itemOption.AttributeTypeCode == 2) {
32378					GLO.Inventory.Item.Options.generateColorOption(itemOption);
32379				}				
32380			});
32381
32382			GLO.Inventory.Item.Options.checkOptionThreshold();
32383		}		
32384
32385
32386		_conIItemOptions.generateItemVariationsList = function(itemVariations) { 
32387	
32388			console.log('generate variations grid');
32389
32390			var itemVariationsList = $('#variations-list');
32391
32392			var itemVariationsInner = itemVariationsList.find('.item-variations-inner');
32393			itemVariationsInner.html("");
32394
32395			var variationsListHeaderEl = document.createElement("div");
32396			variationsListHeaderEl.className = "columns is-mobile item-variations";
32397
32398			var variationsListFooterEl = document.createElement("div");
32399			variationsListFooterEl.className = "columns is-mobile pt-1";			
32400
32401			//generateVariationEditFields
32402			variationsListHeaderEl.innerHTML = (`<div class="column is-one-fifth">
32403					<div class="field">
32404						<div class="control">
32405							<span class="has-text-weight-bold">Variation</span>
32406						</div>
32407					</div>
32408				</div>
32409				<div class="column is-2">
32410					<div class="field">
32411						<div class="control">
32412							<span class="has-text-weight-bold">Price</span>
32413						</div>
32414					</div>
32415				</div>
32416				<div class="column is-2">
32417					<div class="field">
32418						<div class="control">
32419							<span class="has-text-weight-bold">In Stock</span>
32420						</div>
32421					</div>
32422				</div>
32423				<div class="column is-one-fifth">
32424					<div class="field">
32425						<div class="control">
32426							<span class="has-text-weight-bold">SKU</span>
32427						</div>
32428					</div>
32429				</div>
32430				<div class="column is-1">
32431					<div class="field">
32432						<div class="control">
32433							<span class="has-text-weight-bold">Image</span>
32434						</div>
32435					</div>
32436				</div>`);		
32437				
32438				//column header for active switch
32439				// <div class="column is-1">
32440				// 	<div class="field">
32441				// 		<div class="control">
32442				// 			<span class="has-text-weight-bold">Active</span>
32443				// 		</div>
32444				// 	</div>
32445				// </div>				
32446
32447			itemVariationsInner.append(variationsListHeaderEl);				
32448
32449			//generate variations rows
32450			itemVariations.forEach(itemVariation => {
32451
32452				var variationFieldsEl = document.createElement("div");
32453				variationFieldsEl.className = "columns is-mobile item-variation";
32454	
32455				//generateVariationEditFields
32456				variationFieldsEl.innerHTML = (`<div class="column is-one-fifth">
32457						<div class="field">
32458							<div class="control variation-name">
32459								<span>${itemVariation.Name}</span>
32460								<span class="is-hidden">${itemVariation.ItemVariationId}</span>
32461							</div>
32462						</div>
32463					</div>
32464					<div class="column is-2">
32465						<div class="field">
32466							<div class="control required variation-price">
32467								<input class="input" placeholder="Price" min="0" value="${itemVariation.Price}" onChange="GLO.Inventory.Item.Options.validateVariationPrice(this)">
32468							</div>
32469						</div>
32470					</div>
32471					<div class="column is-2">
32472						<div class="field">
32473							<div class="control required variation-quantity">
32474								<input class="input" type="number" placeholder="Qty" value="${itemVariation.Quantity}">
32475							</div>
32476						</div>
32477					</div>
32478					<div class="column is-one-fifth">
32479						<div class="field">
32480							<div class="control required variation-sku">
32481								<input class="input" placeholder="SKU" value="${itemVariation.Sku}">
32482							</div>
32483						</div>
32484					</div>
32485					<div class="column is-1">
32486						<div class="field">
32487							<div class="control variation-image">
32488								<button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchVariantImagePicker(this)">
32489									<span class="icon is-small">
32490										<i class="fas fa-bold fa-plus-circle ${ (itemVariation.Image !== null) ? 'is-hidden': ''}"></i>
32491										<figure class="image is-24x24 ${ (itemVariation.Image !== null) ? '': 'is-hidden'}">
32492											<img src="${ (itemVariation.Image !== null) ? (GLO.Data.cdnDirectory + 'upload-folder/' + itemVariation.Image.ImagePath):''}">
32493										</figure>		
32494										<input type="hidden" id="item-image-id" name="item-image-id" value="${ (itemVariation.Image !== null) ? itemVariation.Image.ItemImageId:''}"/>																				
32495									</span>
32496								</button>
32497							</div>
32498						</div>
32499					</div>`);				
32500
32501					//field for active switch
32502					// <div class="column is-1">
32503					// 	<div class="field">
32504					// 		<div class="control variation-active">
32505					// 			<input id="${itemVariation.Name}" type="checkbox" name="${itemVariation.Name}" class="switch is-small is-outlined is-info" onclick="GLO.Inventory.Item.Options.enableVariation(this)" checked>
32506					// 			<label for="${itemVariation.Name}"></label>							
32507					// 		</div>						
32508					// 	</div>
32509					// </div>
32510
32511				itemVariationsInner.append(variationFieldsEl);							
32512			
32513			});			
32514
32515			variationsListFooterEl.innerHTML = (`<div class="column is-two-thirds">
32516				&nbsp;
32517				</div>
32518				<div class="column">
32519					<div class="buttons is-justify-content-left">
32520						<button class="button has-text-weight-normal" onclick="GLO.Inventory.Item.Options.cancelVariationEdit(this)">Cancel</button>
32521						<button class="button is-info has-text-weight-normal" onclick="GLO.Inventory.Item.Options.saveVariations(this)">Save</button>					
32522					</div>
32523				</div>`);
32524
32525			itemVariationsInner.append(variationsListFooterEl);
32526		}		
32527
32528
32529		_conIItemOptions.generateTextOption = function(itemOption) {
32530
32531			//generate option container with buttons
32532			var itemOptionsList = $('#options-list');
32533			var itemOptionCsv = getItemOptionCsv(itemOption);
32534			var newOptionEl = document.createElement("div");
32535			newOptionEl.className = "box m-3 item-option";
32536			newOptionEl.setAttribute("data-id",itemOption.ItemAttributeId);
32537			newOptionEl.innerHTML = (`<div class="option-edit">
32538					<div class="columns">
32539						<div class="column is-half">
32540							<div class="field">
32541								<label class="label is-pulled-left">Name</label>
32542								<div class="control required option-name">
32543									<input class="input item-option-name" placeholder="Option name for store display e.g. Size" value="${itemOption.Name}">
32544								</div>
32545							</div>
32546						</div>
32547						<div class="column is-half">
32548							<div class="field">
32549								<label class="label is-pulled-left">Type</label>
32550								<div class="control required option-type">
32551									<div class="select is-fullwidth">
32552										<select class="select-option-type is-disabled">
32553											<option>Choose One - Text</option>
32554											<option>Choose One - Color</option>
32555										</select>
32556									</div>
32557								</div>
32558							</div>
32559						</div>
32560					</div>
32561					<div class="columns">
32562						<div class="column">
32563							<div class="field">
32564								<label class="label is-pulled-left">Values</label> 
32565							</div>
32566						</div>
32567					</div>
32568					<div class="option-edit-fields">
32569						<div class="columns">
32570							<div class="column">
32571								<div class="field">
32572									<div class="control required text-option-value">
32573										<input class="input item-option-value" type="tags" placeholder="Add comma-separated values e.g. Small, Medium, Large" value="${itemOptionCsv}">
32574									</div>
32575								</div>
32576							</div>
32577						</div>					
32578					</div>
32579				</div>
32580				<div class="option-preview is-hidden">
32581                	<!-- this is the preview of the option -->
32582            	</div>				
32583				<div class="columns option-actions">
32584					<div class="column is-one-fifth">
32585						<div class="buttons is-justify-content-left">
32586							<button class="button is-danger has-text-weight-normal is-light btn-remove" onclick="GLO.Inventory.Item.Options.removeOptionAskConfirmation(this)">Remove</button>
32587						</div>
32588					</div>
32589					<div class="column">
32590
32591					</div>
32592					<div class="column is-one-third">
32593						<div class="buttons is-justify-content-right">
32594							<button class="button has-text-weight-normal btn-cancel is-hidden" onclick="GLO.Inventory.Item.Options.cancelOptionEdit(this)">Cancel</button>
32595							<button class="button is-info has-text-weight-normal btn-save is-hidden" onclick="GLO.Inventory.Item.Options.saveOption(this)">Save</button>
32596							<button class="button is-info has-text-weight-normal btn-edit" onclick="GLO.Inventory.Item.Options.editOption(this)">Edit</button>							
32597						</div>
32598					</div>
32599				</div>`);
32600
32601				$(newOptionEl).insertBefore($('.create-new-option'));
32602				// itemOptionsList.append(newOptionEl);
32603
32604			GLO.Inventory.Item.Options.generateTextOptionPreview(itemOption,newOptionEl);
32605
32606		}
32607		
32608		_conIItemOptions.generateTextOptionPreview = function(itemOption,optionEl) {
32609
32610			var itemOptionPreviewEl = $(optionEl).find('.option-preview');
32611
32612			var optionPreviewInnerEl = document.createElement("div");
32613			optionPreviewInnerEl.className = "container has-background-light p-3 m-3";
32614			optionPreviewInnerEl.innerHTML=(`<span class="pull-left">Preview</span><span>${itemOption.Name}</span><span class="is-hidden">${itemOption.Id}</span>`);
32615			
32616			itemOptionPreviewEl.append(optionPreviewInnerEl);
32617
32618			var optionValuesEl = document.createElement("div");
32619			optionValuesEl.className="buttons is-justify-content-center mt-1";
32620
32621			itemOption.ItemAttributeValues.forEach(function(itemOptionValue) {
32622				var optionValueEl = document.createElement("button");
32623				optionValueEl.className="button";
32624				optionValueEl.innerHTML=(`${itemOptionValue.Value}`);
32625				optionValuesEl.append(optionValueEl);
32626			});
32627
32628			optionPreviewInnerEl.append(optionValuesEl);
32629
32630
32631			$(optionEl).find('.option-edit').addClass('is-hidden');
32632			itemOptionPreviewEl.removeClass('is-hidden');
32633		}
32634
32635		_conIItemOptions.generateColorOption = function(itemOption) {
32636
32637			//generate option container with buttons
32638			var itemOptionsList = $('#options-list');
32639			// var itemOptionCsv = getItemOptionCsv(itemOption);
32640			var newOptionEl = document.createElement("div");
32641			newOptionEl.className = "box m-3 item-option";
32642			newOptionEl.setAttribute("data-id",itemOption.ItemAttributeId);
32643			newOptionEl.innerHTML = (`<div class="option-edit">
32644					<div class="columns">
32645						<div class="column is-half">
32646							<div class="field">
32647								<label class="label is-pulled-left">Name</label>
32648								<div class="control required option-name">
32649									<input class="input item-option-name" placeholder="Option name for store display e.g. Color" value="${itemOption.Name}">
32650								</div>
32651							</div>
32652						</div>
32653						<div class="column is-half">
32654							<div class="field">
32655								<label class="label is-pulled-left">Type</label>
32656								<div class="control required option-type">
32657									<div class="select is-fullwidth">
32658										<select class="select-option-type is-disabled">
32659											<option>Choose One - Text</option>
32660											<option selected>Choose One - Color</option>
32661										</select>
32662									</div>
32663								</div>
32664							</div>
32665						</div>
32666					</div>
32667					<div class="columns">
32668						<div class="column">
32669							<div class="field">
32670								<label class="label is-pulled-left">Values</label> 
32671							</div>
32672						</div>
32673					</div>
32674					<div class="option-edit-fields">
32675					<!-- color swatches go here -->
32676					</div>
32677				</div>
32678				<div class="option-preview is-hidden">
32679                	<!-- this is the preview of the option -->
32680            	</div>				
32681				<div class="columns option-actions">
32682					<div class="column is-one-fifth">
32683						<div class="buttons is-justify-content-left">
32684							<button class="button is-danger has-text-weight-normal is-light btn-remove" onclick="GLO.Inventory.Item.Options.removeOptionAskConfirmation(this)">Remove</button>
32685						</div>
32686					</div>
32687					<div class="column">
32688
32689					</div>
32690					<div class="column is-one-third">
32691						<div class="buttons is-justify-content-right">
32692							<button class="button has-text-weight-normal btn-cancel is-hidden" onclick="GLO.Inventory.Item.Options.cancelOptionEdit(this)">Cancel</button>
32693							<button class="button is-info has-text-weight-normal btn-save is-hidden" onclick="GLO.Inventory.Item.Options.saveOption(this)">Save</button>
32694							<button class="button is-info has-text-weight-normal btn-edit" onclick="GLO.Inventory.Item.Options.editOption(this)">Edit</button>							
32695						</div>
32696					</div>
32697				</div>`);
32698
32699				$(newOptionEl).insertBefore($('.create-new-option'));
32700
32701			GLO.Inventory.Item.Options.generateColorSwatchEditFields(itemOption,newOptionEl);
32702			GLO.Inventory.Item.Options.generateColorOptionPreview(itemOption,newOptionEl);
32703
32704		}		
32705
32706		_conIItemOptions.generateColorSwatchEditFields = function(itemOption,optionEl) {
32707
32708			var itemOptionPreviewEl = $(optionEl).find('.option-preview');
32709			var optionEditFieldsEl = $(optionEl).find('.option-edit-fields');
32710			optionEditFieldsEl.html("");
32711
32712			var addNewColorSwatchEl = document.createElement("div");
32713			addNewColorSwatchEl.className = "columns is-mobile create-new-color-swatch";
32714
32715			itemOption.ItemAttributeValues.forEach(function(itemOptionValue) {
32716				 
32717				var optionFieldsEl = document.createElement("div");
32718				optionFieldsEl.className = "columns is-mobile item-option-color-value";
32719				
32720				if (itemOptionValue.IsImage) {
32721					var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemOptionValue.Value;
32722
32723					optionFieldsEl.innerHTML = (`<div class="column is-one-fifth">
32724						<div class="field">
32725							<div class="control required color-swatch-value">
32726								<button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)">
32727									<span class="icon is-small">
32728										<i class="fas fa-bold fa-plus-circle is-hidden"></i>
32729										<figure class="image is-24x24">
32730											<img class="is-rounded" src="${img_path}">
32731										</figure>		
32732										<input type="hidden" id="item-image-path" name="item-image-path" value="${itemOptionValue.Value}" />	
32733										<input type="hidden" id="item-attribute-value-id" name="item-attribute-value-id" value="${itemOptionValue.ItemAttributeValueId}" />																			
32734									</span>
32735								</button>
32736							</div>
32737						</div>
32738					</div>
32739					<div class="column">
32740						<div class="field">
32741							<div class="control required color-swatch-name">
32742								<input class="input" placeholder="Add value e.g. Blue" value="${itemOptionValue.Name}">
32743							</div>
32744						</div>
32745					</div>
32746					<div class="column is-one-fifth">
32747						<div class="field">
32748							<div class="control">
32749								<button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)" data-id="${itemOptionValue.ItemAttributeValueId}">
32750									<span class="icon is-small">
32751										<i class="fas fa-bold fa-times"></i>
32752									</span>
32753								</button>
32754							</div>
32755						</div>
32756					</div>`);						
32757
32758				}
32759				else {
32760					optionFieldsEl.innerHTML = (`<div class="column is-one-fifth">
32761						<div class="field">
32762							<div class="control required color-swatch-value">
32763								<button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)">
32764									<span class="icon is-small" style="background-color:${itemOptionValue.Value}">
32765										<i class="fas fa-bold fa-plus-circle is-hidden"></i>
32766										<figure class="image is-24x24 is-hidden">
32767											<img class="is-rounded" src="">
32768										</figure>		
32769										<input type="hidden" id="item-image-path" name="item-image-path" value="${itemOptionValue.Value}" />	
32770										<input type="hidden" id="item-attribute-value-id" name="item-attribute-value-id" value="${itemOptionValue.ItemAttributeValueId}" />																			
32771									</span>
32772								</button>
32773							</div>
32774						</div>
32775					</div>
32776					<div class="column">
32777						<div class="field">
32778							<div class="control required color-swatch-name">
32779								<input class="input" placeholder="Add value e.g. Blue" value="${itemOptionValue.Name}">
32780							</div>
32781						</div>
32782					</div>
32783					<div class="column is-one-fifth">
32784						<div class="field">
32785							<div class="control">
32786								<button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)" data-id="${itemOptionValue.ItemAttributeValueId}">
32787									<span class="icon is-small">
32788										<i class="fas fa-bold fa-times"></i>
32789									</span>
32790								</button>
32791							</div>
32792						</div>
32793					</div>`);
32794				}
32795				
32796				optionEditFieldsEl.append(optionFieldsEl);
32797			});
32798
32799			addNewColorSwatchEl.innerHTML = (`<div class="column">
32800				<div class="field">
32801					<div class="control">
32802							<button class="button is-link is-inverted" onclick="GLO.Inventory.Item.Options.addBlankColorSwatchOptionValue(this)">Add Color
32803							</button>
32804						</div>
32805					</div>
32806				</div>
32807			</div>`);
32808
32809			optionEditFieldsEl.append(addNewColorSwatchEl);
32810
32811		}		
32812
32813		_conIItemOptions.generateColorOptionPreview = function(itemOption,optionEl) {
32814
32815			var itemOptionPreviewEl = $(optionEl).find('.option-preview');
32816
32817			var optionPreviewInnerEl = document.createElement("div");
32818			optionPreviewInnerEl.className = "container has-background-light p-3 m-3";
32819			optionPreviewInnerEl.innerHTML=(`<span class="pull-left">Preview</span><span>${itemOption.Name}</span><span class="is-hidden">${itemOption.Id}</span>`);
32820			
32821			itemOptionPreviewEl.append(optionPreviewInnerEl);
32822
32823			var productColorsEl = document.createElement("div");
32824			productColorsEl.className="product-colors";
32825
32826			var colorSelectorEl = document.createElement("div");
32827			colorSelectorEl.className="color-selector";
32828
32829			itemOption.ItemAttributeValues.forEach(function(itemOptionValue) {
32830				var optionValueEl = document.createElement("div");
32831				var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemOptionValue.Value;
32832				if (itemOptionValue.IsImage) {
32833					//						
32834					optionValueEl.innerHTML=(`<input type="radio" id="${itemOptionValue.ItemAttributeValueId}" name="color" value="" class="active"></input>
32835					<label for="${itemOptionValue.ItemAttributeValueId}">
32836						<span class="indicator">
32837						<i data-feather="check"></i>
32838						</span>
32839						<span>
32840							<img class="is-rounded image is-36x36" src="${img_path}">
32841						</span>
32842					</label>`);
32843
32844				}
32845				else {
32846					optionValueEl.innerHTML=(`<input type="radio" id="${itemOptionValue.ItemAttributeValueId}" name="color" value="" class="active"></input>
32847					<label for="${itemOptionValue.ItemAttributeValueId}">
32848						<span class="indicator">
32849						<i data-feather="check"></i>
32850						</span>
32851						<span style="background-color:${itemOptionValue.Value}"></span>
32852					</label>`);
32853				}
32854				
32855				colorSelectorEl.append(optionValueEl);
32856			});
32857
32858			productColorsEl.append(colorSelectorEl);
32859			optionPreviewInnerEl.append(productColorsEl);
32860
32861			$(optionEl).find('.option-edit').addClass('is-hidden');
32862			itemOptionPreviewEl.removeClass('is-hidden');
32863
32864		}
32865
32866		_conIItemOptions.changeOptionType = function(elem) {
32867
32868			console.log('Change Option Type');
32869
32870			var newOptionType = elem.value;
32871			var itemOptionsList = $('#options-list');
32872			var optionEditFieldsEl = $(itemOptionsList).find('.option-edit-fields');
32873			optionEditFieldsEl.html("");
32874
32875			var optionFieldsEl = document.createElement("div");
32876			optionFieldsEl.className = "columns is-mobile item-option-color-value";
32877
32878			var addNewColorSwatchEl = document.createElement("div");
32879			addNewColorSwatchEl.className = "columns is-mobile create-new-color-swatch";
32880
32881			//text option
32882			if (newOptionType == 1) {
32883				//generateTextOptionFields
32884				optionFieldsEl.innerHTML = (`<div class="column">
32885						<div class="field">
32886							<div class="control">
32887								<input class="input" placeholder="Add comma-separated values e.g. Small, Medium, Large">
32888							</div>
32889						</div>
32890					</div>`);				
32891			}
32892
32893			//color option
32894			if (newOptionType == 2) {
32895				//generateColorOptionFields
32896				optionFieldsEl.innerHTML = (`<div class="column is-one-fifth">
32897								<div class="field">
32898									<div class="control required color-swatch-value">
32899										<button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)">
32900											<span class="icon is-small">
32901												<i class="fas fa-bold fa-plus-circle"></i>
32902												<figure class="image is-24x24 is-hidden">
32903													<img class="is-rounded" src="https://bulma.io/images/placeholders/24x24.png">
32904												</figure>		
32905												<input type="hidden" id="item-image-path" name="item-image-path" />																				
32906											</span>
32907										</button>
32908									</div>
32909								</div>
32910							</div>
32911							<div class="column">
32912								<div class="field">
32913									<div class="control required color-swatch-name">
32914										<input class="input" placeholder="Add value e.g. Blue">
32915									</div>
32916								</div>
32917							</div>
32918							<div class="column is-one-fifth">
32919								<div class="field">
32920									<div class="control">
32921										<button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)">
32922											<span class="icon is-small">
32923												<i class="fas fa-bold fa-times"></i>
32924											</span>
32925										</button>
32926									</div>
32927								</div>
32928							</div>`);				
32929			}
32930
32931			optionEditFieldsEl.append(optionFieldsEl);
32932
32933			addNewColorSwatchEl.innerHTML = (`<div class="column">
32934				<div class="field">
32935					<div class="control">
32936							<button class="button is-link is-inverted" onclick="GLO.Inventory.Item.Options.addBlankColorSwatchOptionValue(this)">Add Color
32937							</button>
32938						</div>
32939					</div>
32940				</div>
32941			</div>`);
32942
32943			optionEditFieldsEl.append(addNewColorSwatchEl);
32944
32945		}		
32946
32947		_conIItemOptions.addBlankColorSwatchOptionValue = function(elem) {
32948
32949			var optionFieldsEl = document.createElement("div");
32950			optionFieldsEl.className = "columns is-mobile item-option-color-value";			
32951
32952			optionFieldsEl.innerHTML = (`<div class="column is-one-fifth">
32953                            <div class="field">
32954                                <div class="control required color-swatch-value">
32955                                    <button class="button is-info is-outlined is-fullwidth" onclick="GLO.Inventory.Item.Options.launchItemOptionUploadColorSwatch(this)">
32956                                        <span class="icon is-small">
32957                                            <i class="fas fa-bold fa-plus-circle"></i>
32958											<figure class="image is-24x24 is-hidden">
32959												<img class="is-rounded" src="https://bulma.io/images/placeholders/24x24.png">
32960									  		</figure>		
32961											  <input type="hidden" id="item-image-path" name="item-image-path" />																				
32962                                        </span>
32963                                    </button>
32964                                </div>
32965                            </div>
32966                        </div>
32967                        <div class="column">
32968                            <div class="field">
32969                                <div class="control required color-swatch-name">
32970                                    <input class="input" placeholder="Add value e.g. Black">
32971                                </div>
32972                            </div>
32973                        </div>
32974                        <div class="column is-one-fifth">
32975                            <div class="field">
32976                                <div class="control">
32977                                    <button class="button is-danger is-inverted" onclick="GLO.Inventory.Item.Options.removeOptionValue(this)">
32978                                        <span class="icon is-small">
32979                                            <i class="fas fa-bold fa-times"></i>
32980                                        </span>
32981                                    </button>
32982                                </div>
32983                            </div>
32984                        </div>`);				
32985
32986			var createNewColorSwatchEl = $(elem).closest('.create-new-color-swatch');
32987			$(optionFieldsEl).insertBefore(createNewColorSwatchEl);						
32988		}
32989
32990		_conIItemOptions.launchItemOptionUploadColorSwatch = function(elem) {
32991
32992			_itemSelectedItemOptionColorSwatch = elem;
32993
32994			$('#item-option-color-swatches-container').modal();
32995			var jModal = $('#simplemodal-container #item-option-color-swatches-container');
32996			var h = $(window).height() * 0.2;
32997			var w = $(window).width() * 0.3;
32998			
32999			$.modal.update(h,w);
33000			$(window).resize(); 
33001			$('.modalCloseImg').css("margin-top","20px");
33002			$('.modalCloseImg').css("margin-right","20px");
33003			$('.modalCloseImg').on("click",function() { GLO.Inventory.Item.Options.closeItemOptionUploadColorSwatch(); });
33004			
33005			if (GLO.Info.isMobile()) {
33006				$('#simplemodal-container').draggable({disable:true});
33007			}
33008			$('#simplemodal-container').css("overflow-y","auto");
33009		
33010		}
33011
33012		_conIItemOptions.closeItemOptionUploadColorSwatch = function() {
33013
33014			$('.modalCloseImg').off("click");
33015		}		
33016
33017		_conIItemOptions.selectedColorSwatchImage = function(elem) {
33018			console.log('Chose image upload for color swatch');
33019
33020			$('#item-option-color-choices').addClass('is-hidden');
33021			$('#item-option-image-uploader').removeClass('is-hidden');
33022
33023		}	
33024
33025		_conIItemOptions.changeOptionColor = function(elem) {
33026			console.log('Change Option Color Value');
33027		}
33028
33029		_conIItemOptions.addNewOptionAskConfirmation= function(elem) {
33030
33031			var variationsHaveInventoryIds = doVariationsHaveInventoryIds();
33032
33033			if (variationsHaveInventoryIds) {
33034
33035				if (GLO.Info.isMobile()) {
33036					var msg = 'Add new product option?';
33037				} else {
33038					var msg = 'Are you sure you want to add a new product option?';
33039				}
33040
33041				msg = msg + ' Upon saving the new option, products generated for the variations will be deleted and variations will be regenerated.';
33042
33043				msg = '<div class="friendly-msg2">' + msg + '</div>';
33044				msg = '<div> <h2 class="friendly-msg2">Add Product Option?</h2>' + msg + '</div>';
33045				
33046				
33047				var fnYes = function() { GLO.Inventory.Item.Options.generateNewOption(elem); };
33048				var fnNo = function() { GLO.UI.Form.resetProcessing(); }
33049				
33050				var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup();
33051				
33052				if (jpop.height() > innerHeight * .9) {
33053					jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) });
33054				}
33055			}
33056			else {
33057				GLO.Inventory.Item.Options.generateNewOption(elem);
33058			}
33059
33060
33061		}			
33062
33063		_conIItemOptions.removeOptionAskConfirmation= function(elem) {
33064
33065			var variationsHaveInventoryIds = false;
33066
33067			//check if option has an id
33068			var itemAttributeId = $(elem).closest('.item-option').attr('data-id');
33069			//check for variant inventory ids only if option was saved previously
33070			if (itemAttributeId !== undefined && itemAttributeId > 0) {
33071				variationsHaveInventoryIds = doVariationsHaveInventoryIds();
33072			}
33073
33074			if (GLO.Info.isMobile()) {
33075				var msg = 'Remove the product option?';
33076			} else {
33077				var msg = 'Are you sure you want to remove the product option?';
33078			}
33079			
33080			if (variationsHaveInventoryIds) {
33081
33082				msg = msg + ' Products generated for the variations will be deleted and variations will be regenerated.';
33083			}
33084
33085			msg = '<div class="friendly-msg2">' + msg + '</div>';
33086			msg = '<div> <h2 class="friendly-msg2">Remove Product Option?</h2>' + msg + '</div>';
33087			
33088			
33089			var fnYes = function() { GLO.Inventory.Item.Options.removeOption(elem); };
33090			var fnNo = function() { GLO.UI.Form.resetProcessing(); }
33091			
33092			var jpop = new GLO.Popup.Confirm(msg, fnYes, fnNo).getPopup();
33093			
33094			if (jpop.height() > innerHeight * .9) {
33095				jpop.find('.msg').css({ "overflow": "auto", "max-height": (innerHeight * .8) });
33096			}
33097		}	
33098
33099		_conIItemOptions.removeOptionValue = function(elem) {
33100			console.log('Remove Option Color Value');
33101
33102			var optionColorValueX = elem;
33103			var optionDiv = optionColorValueX.closest(".item-option");
33104			var itemOptionsColorValues = $(optionDiv).find('.item-option-color-value').length;
33105
33106
33107			if (itemOptionsColorValues == 1) {
33108				// GLO.Inventory.Item.Options.removeOption(optionDiv);
33109				GLO.Inventory.Item.Options.removeOptionAskConfirmation(optionDiv);
33110			}
33111			else {
33112				optionColorValueX.closest(".item-option-color-value").remove();
33113			}
33114		}		
33115		
33116		_conIItemOptions.cancelOptionEdit = function(elem) {
33117
33118			console.log('Cancel Edit - Option Preview or Remove');
33119
33120			var itemOptionEl = $(elem).closest('.item-option');
33121			if (itemOptionEl.attr('data-id') !== undefined && itemOptionEl.attr('data-id') !== false) {
33122				$(elem).parents('.item-option').find('.option-edit').addClass('is-hidden');
33123				$(elem).parents('.item-option').find('.btn-cancel').addClass('is-hidden');
33124				$(elem).parents('.item-option').find('.btn-save').addClass('is-hidden');			
33125	
33126				$(elem).parents('.item-option').find('.option-preview').removeClass('is-hidden');
33127				$(elem).parents('.item-option').find('.btn-edit').removeClass('is-hidden');				
33128			}
33129			else {
33130				//remove empty option
33131				GLO.Inventory.Item.Options.removeOption(elem);
33132			}
33133
33134		}			
33135
33136		_conIItemOptions.editOption = function(elem) {
33137			console.log('Option Edit Mode');
33138
33139			$(elem).parents('.item-option').find('.option-preview').addClass('is-hidden');
33140			$(elem).parents('.item-option').find('.btn-edit').addClass('is-hidden');
33141
33142			$(elem).parents('.item-option').find('.option-edit').removeClass('is-hidden');
33143			$(elem).parents('.item-option').find('.btn-cancel').removeClass('is-hidden');
33144			$(elem).parents('.item-option').find('.btn-save').removeClass('is-hidden');
33145
33146			//attach tags input
33147			var tagEl = $(elem).parents('.item-option').find('input[type="tags"]')[0];
33148			if (tagEl) {
33149				attachBulmaTagsInput(tagEl);
33150			}
33151
33152		}		
33153
33154		var validateOption = function(itemOptionEl) {
33155			
33156			//foreach variation check if price, qty and sku are valid
33157			//if any row is invalid mark the row or field with css class
33158			//return true if everything looks good
33159			var optionFieldsCompleted = true;
33160
33161			var optionNameField = $(itemOptionEl).find('.control.required.option-name');
33162			var optionNameValue = $(itemOptionEl).find('.item-option-name').val();
33163
33164			if (optionNameValue == '' || typeof optionNameValue == 'undefined') {
33165				$(optionNameField).addClass('has-error');
33166				optionFieldsCompleted = false;
33167			}
33168			else {
33169				$(optionNameField).removeClass('has-error');
33170			}
33171
33172
33173			var attributeTypeName = $(itemOptionEl).find('.select-option-type').val();
33174			var itemAttributeType = GLO.Inventory.Item.Options.getOptionType(attributeTypeName);
33175
33176			//text option
33177			if (itemAttributeType.attribute_id == 1) {
33178				var optionTagsField = $(itemOptionEl).find('.control.required.text-option-value');
33179				var csvValue =  $(itemOptionEl).find('input[type="tags"]')[0].value;
33180				if (csvValue == '' || typeof csvValue == 'undefined') {
33181					$(optionTagsField).addClass('has-error');
33182					optionFieldsCompleted = false;
33183				}
33184				else {
33185					$(optionTagsField).removeClass('has-error');
33186				}
33187			}
33188
33189			//color option
33190			if (itemAttributeType.attribute_id == 2) {
33191				var optionColorSwatchList = $(itemOptionEl).find('.option-edit-fields');
33192				var optionColorSwatchCount = optionColorSwatchList.find('.item-option-color-value').length;
33193				
33194				for (var i=0; i < optionColorSwatchCount; i++) {
33195					var colorSwatchRow = $(optionColorSwatchList).find('.item-option-color-value')[i];
33196					var colorSwatchValueEl = $(colorSwatchRow).find('.control.required.color-swatch-value'); 
33197					var colorSwatchImageButton = $(colorSwatchValueEl).find('.button');
33198					var colorSwatchImageValue = $(colorSwatchValueEl).find('#item-image-path').val();
33199
33200					var colorSwatchNameEl = $(colorSwatchRow).find('.control.required.color-swatch-name'); 
33201					var colorSwatchNameValue = $(colorSwatchNameEl).find('.input').val();
33202
33203					if (colorSwatchImageValue == '' || typeof colorSwatchImageValue == 'undefined') {
33204						// $(colorSwatchValueEl).addClass('has-error');
33205						$(colorSwatchImageButton).removeClass('is-info').addClass('is-danger');
33206						optionFieldsCompleted = false;
33207					}
33208					else {
33209						// $(colorSwatchValueEl).removeClass('has-error');
33210						$(colorSwatchImageButton).removeClass('is-danger').addClass('is-info');
33211					}
33212
33213					if (colorSwatchNameValue == '' || typeof colorSwatchNameValue == 'undefined') {
33214						$(colorSwatchNameEl).addClass('has-error');
33215						optionFieldsCompleted = false;
33216					}
33217					else {
33218						$(colorSwatchNameEl).removeClass('has-error');
33219					}					
33220				}
33221			}			
33222
33223			return optionFieldsCompleted;
33224
33225		}	
33226
33227		_conIItemOptions.saveOption = function(elem) {
33228			console.log('Option Save');
33229			var itemOptionEl = $(elem).closest('.item-option');
33230
33231			var validatOptionResult = validateOption(itemOptionEl);
33232
33233			if (validatOptionResult) {
33234			
33235				var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateItemAttribute';
33236			
33237				//check for data-id
33238				var itemAttributeId = itemOptionEl.attr('data-id');
33239	
33240				if (itemAttributeId == undefined) {
33241					itemAttributeId = 0;//for new options
33242				}
33243	
33244				var itemOption = new Object();
33245				itemOption.ProviderId = GLO.Data.provider.id;
33246				itemOption.Name = $(elem).closest('.item-option').find('.item-option-name').val();
33247				itemOption.InventoryId  = _itemId;
33248				itemOption.ItemAttributeId = itemAttributeId;
33249	
33250				var attributeTypeName = $(elem).closest('.item-option').find('.select-option-type').val();
33251				var itemAttributeType = GLO.Inventory.Item.Options.getOptionType(attributeTypeName);
33252				itemOption.AttributeTypeCode = itemAttributeType.attribute_id;
33253	
33254				itemOption.ItemAttributeValues = [];
33255				
33256				if (itemOption.AttributeTypeCode == 1) {
33257					//text option
33258					var csvValue =  $(elem).closest('.item-option').find('input[type="tags"]')[0].value;
33259					var csvArray = csvValue.split(',');
33260					csvArray.forEach(function(optionVal) {
33261						var itemAttributeValue = {
33262							ItemAttributeId: itemAttributeId,
33263							Name: optionVal,
33264							Value: optionVal, 
33265							IsImage: false};
33266	
33267							itemOption.ItemAttributeValues.push(itemAttributeValue);
33268					});
33269				}
33270				else if (itemOption.AttributeTypeCode == 2) {			
33271					//color option
33272					var colorValueElArray = itemOptionEl.find('.item-option-color-value');
33273					for (var i = 0; i < colorValueElArray.length; i++) { 
33274						var colorSwatchImagePath = $(colorValueElArray[i]).find('#item-image-path').val();
33275						var colorSwatchName = $(colorValueElArray[i]).find('.input').val();
33276	
33277						var itemAttributeValue = {
33278							ItemAttributeId: itemAttributeId,
33279							Name: colorSwatchName,
33280							Value: colorSwatchImagePath, 
33281							IsImage: true
33282						};
33283	
33284						itemOption.ItemAttributeValues.push(itemAttributeValue);
33285					}
33286				}
33287				else {
33288					//nothing to do
33289					console.log('Invalid item option type');
33290					return;
33291				}
33292		
33293				var jsonString= JSON.stringify(itemOption);
33294	
33295				var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: itemOption})
33296				.success(function(data, textStatus, jqXHR) {
33297					if (UTIL.Validate.hasPermissionError(data)) { return; }
33298					GLO.Popup.Success.open('Product Option updated.');
33299					GLO.Inventory.Item.Options.getItemOptions(_itemId);
33300					GLO.Inventory.Item.Options.getItemVariations(_itemId);
33301	
33302				})
33303				.error(function(jqXHR, textStatus, errorThrown) {
33304					new GLO.Popup.Error('Unable to save product option at this time.  Please try again later.');
33305					GLO.UI.Form.resetProcessing();
33306				});		
33307
33308			}
33309
33310		}		
33311
33312		_conIItemOptions.removeOption = function(elem) {
33313			console.log('Option Remove');
33314			var itemOptionEl = $(elem).closest('.item-option');
33315
33316			//check for data-id
33317			var itemAttributeId = itemOptionEl.attr('data-id');
33318
33319			if (itemAttributeId > 0) {
33320				var uri = GLO.Link.Page.Provider.Home + 'Inventory/RemoveItemAttribute';
33321
33322				var itemOption = new Object();
33323				itemOption.ProviderId = GLO.Data.provider.id;
33324				itemOption.Name = $(elem).closest('.item-option').find('.item-option-name').val();
33325				itemOption.InventoryId  = _itemId;
33326				itemOption.itemAttributeId = itemAttributeId;
33327	
33328				var attributeTypeName = $(elem).closest('.item-option').find('.select-option-type').val();
33329				var itemAttributeType = GLO.Inventory.Item.Options.getOptionType(attributeTypeName);
33330				itemOption.AttributeTypeCode = itemAttributeType.attribute_id;
33331	
33332				var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: itemOption})
33333				.success(function(data, textStatus, jqXHR) {
33334					if (UTIL.Validate.hasPermissionError(data)) { return; }
33335					var optionDiv = elem;
33336					optionDiv.closest(".item-option").remove();
33337					GLO.Inventory.Item.Options.checkOptionThreshold();
33338					GLO.Inventory.Item.Options.getItemOptions(_itemId);
33339					GLO.Inventory.Item.Options.getItemVariations(_itemId);
33340	
33341				})
33342				.error(function(jqXHR, textStatus, errorThrown) {
33343					new GLO.Popup.Error('Unable to remove product option at this time.  Please try again later.');
33344					GLO.UI.Form.resetProcessing();
33345				});	
33346			}
33347			else {
33348				//option not saved yet
33349				var optionDiv = elem;
33350				optionDiv.closest(".item-option").remove();
33351				GLO.Inventory.Item.Options.checkOptionThreshold();
33352			}
33353		}	
33354
33355		_conIItemOptions.uploadImageAndResize = function () {
33356			//define the width to resize e.g 180px
33357			var resize_width = 500;//without px
33358	
33359			//get the image selected
33360			var item = document.querySelector('#uploader').files[0];
33361	
33362			//create a FileReader
33363			var reader = new FileReader();
33364	
33365			//image turned to base64-encoded Data URI.
33366			reader.readAsDataURL(item);
33367			reader.name = item.name;//get the image's name
33368			reader.size = item.size; //get the image's size
33369			reader.onload = function(event) {
33370				var img = new Image();//create a image
33371				img.src = event.target.result;//result is base64-encoded Data URI
33372				img.name = event.target.name;//set name (optional)
33373				img.size = event.target.size;//set size (optional)
33374				img.onload = function(el) {
33375					var elem = document.createElement('canvas');//create a canvas
33376	
33377					//scale the image to 600 (width) and keep aspect ratio
33378					var scaleFactor = resize_width / el.target.width;
33379					elem.width = resize_width;
33380					elem.height = el.target.height * scaleFactor;
33381	
33382					//draw in canvas
33383					var ctx = elem.getContext('2d');
33384					ctx.drawImage(el.target, 0, 0, elem.width, elem.height);
33385	
33386					//get the base64-encoded Data URI from the resize image
33387					var srcEncoded = ctx.canvas.toDataURL('image/png', 1);
33388	
33389					//assign it to thumb src
33390					// document.querySelector('#item-image').src = srcEncoded;
33391	
33392					GLO.Inventory.Item.Options.saveItemOptionImage(srcEncoded,resize_width);
33393				}
33394			}
33395		}		
33396
33397		_conIItemOptions.saveItemOptionImage = function(data,width) {
33398
33399			//remove the attached handler
33400			$('#btnSaveItemImage').off("click");
33401			
33402			var jcontainer = $('#uploader');
33403			
33404			//reset error
33405			$('#itemImageUploadErrorMessage').addClass('is-hidden');
33406	
33407			var fnCallback = function(jcontainer, fileName, imgId, imgSize) {
33408				if (fileName!=null && fileName.length > 0) {
33409					var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName;
33410					// console.log(img_path);
33411	
33412					//clear the image display
33413					document.querySelector('#item-image').src ='';
33414		
33415					//set the image on the option
33416					if (_itemSelectedItemOptionColorSwatch) {
33417
33418						//hide the icon
33419						$($(_itemSelectedItemOptionColorSwatch).find('i')[0]).addClass('is-hidden');
33420
33421						//set the filename
33422						$($(_itemSelectedItemOptionColorSwatch).find('#item-image-path')[0]).val(fileName);
33423						//display the image
33424						$($(_itemSelectedItemOptionColorSwatch).find('img')[0]).attr('src',img_path);
33425						//unhide the image container
33426						$($(_itemSelectedItemOptionColorSwatch).find('figure')[0]).removeClass('is-hidden');
33427
33428						_itemSelectedItemOptionColorSwatch = null;
33429					}
33430
33431					//close the modal
33432					$('.simplemodal-close').click();		
33433					// closeItemOptionUploadColorSwatch	
33434					
33435				}
33436				else {
33437					//display error
33438					$('#itemImageUploadErrorMessage').removeClass('is-hidden');
33439				}
33440			}
33441			
33442			if (SA.Uploader.uploadImage(data, 'png', width, jcontainer, fnCallback)) {
33443				return true;
33444			}
33445		}		
33446
33447		//launchVariantImagePicker
33448		_conIItemOptions.getItemImages = function(inventoryId) {
33449			var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetItemImages?id=' + inventoryId;
33450		
33451			var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
33452				.done(function(data, textStatus, jqXHR) {
33453					window.onbeforeunload = null;
33454					if(data!=null && data!== '') {
33455						var itemImages = data;
33456						if (itemImages.length > 0) {
33457							generateItemImagePickerGrid(itemImages);
33458						}
33459						else {
33460							//display blank state
33461							generateItemImagePickerGridBlankState();
33462						}
33463					  } else {
33464						new GLO.Popup.Error('Could not get the product images');
33465					  }				
33466				})
33467				.fail(function(jqXHR, textStatus, errorThrown) {
33468					GLO.UI.Form.resetProcessing(); 		
33469					new GLO.Popup.Error('Could not get the product images');
33470				});
33471		}		
33472
33473		_conIItemOptions.launchVariantImagePicker = function(elem) {
33474
33475			_itemSelectedVariant = elem;
33476
33477			$('#item-variation-image-picker-container').modal();
33478			var jModal = $('#simplemodal-container #item-variation-image-picker-container');
33479			var h = $(window).height() * 0.8;
33480			var w = $(window).width() * 0.8;
33481			
33482			$.modal.update(h,w);
33483			$(window).resize(); 
33484			$('.modalCloseImg').css("margin-top","20px");
33485			$('.modalCloseImg').css("margin-right","20px");
33486			$('.modalCloseImg').on("click",function() { GLO.Inventory.Item.Options.closeVariantImagePicker(); });
33487			
33488			if (GLO.Info.isMobile()) {
33489				$('#simplemodal-container').draggable({disable:true});
33490			}
33491			$('#simplemodal-container').css("overflow-y","auto");
33492
33493			GLO.Inventory.Item.Options.getItemImages(_itemId);
33494		
33495		}
33496
33497		_conIItemOptions.setImageForVariation = function(itemImageId,itemImageFilename) {
33498			
33499			var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + itemImageFilename;
33500
33501			//set the image on the variation
33502			if (_itemSelectedVariant) {
33503
33504				//hide the icon
33505				$($(_itemSelectedVariant).find('i')[0]).addClass('is-hidden');
33506
33507				//set the imageId
33508				$($(_itemSelectedVariant).find('#item-image-id')[0]).val(itemImageId);
33509				//display the image
33510				$($(_itemSelectedVariant).find('img')[0]).attr('src',img_path);
33511				//unhide the image container
33512				$($(_itemSelectedVariant).find('figure')[0]).removeClass('is-hidden');
33513
33514				_itemSelectedVariant = null;
33515			}
33516
33517			//close the modal
33518			$('.simplemodal-close').click();	
33519
33520		}
33521		
33522
33523		_conIItemOptions.closeVariantImagePicker = function() {
33524
33525			$('.modalCloseImg').off("click");
33526		}		
33527
33528		_conIItemOptions.validateVariationPrice = function(elem) {
33529			var priceVal = parseFloat(elem.value);
33530
33531			if (isNaN(priceVal)) {
33532				elem.value = '';
33533			} else {
33534				elem.value = priceVal.toFixed(2);
33535			}
33536		}		
33537
33538		var validateVariations = function() {
33539			
33540			//foreach variation check if price, qty and sku are valid
33541			//if any row is invalid mark the row or field with css class
33542			//return true if everything looks good
33543			var variationsFieldsCompleted = true;
33544			var itemVariationsList = $('#variations-list');
33545			var itemVariationsCount = itemVariationsList.find('.item-variations-inner').find('.item-variation').length;
33546			for (var i=0; i < itemVariationsCount; i++) {
33547				var itemVariationRow = itemVariationsList.find('.item-variations-inner').find('.item-variation')[i];
33548				var itemVariationPriceField = $(itemVariationRow).find('.control.required.variation-price');
33549				var itemVariationQuantityField = $(itemVariationRow).find('.control.required.variation-quantity');
33550				var itemVariationSkuField = $(itemVariationRow).find('.control.required.variation-sku');
33551
33552				var itemVariationPriceValue = $(itemVariationPriceField).find('.input').val();
33553				if (itemVariationPriceValue == '' || isNaN(itemVariationPriceValue) || itemVariationPriceValue <= 0) {
33554					$(itemVariationPriceField).addClass('has-error');
33555					variationsFieldsCompleted = false;
33556				}
33557				else {
33558					$(itemVariationPriceField).removeClass('has-error');
33559				}
33560
33561				var itemVariationQuantityValue = $(itemVariationQuantityField).find('.input').val();
33562				if (itemVariationQuantityValue == '' || isNaN(itemVariationQuantityValue)) {
33563					$(itemVariationQuantityField).addClass('has-error');
33564					variationsFieldsCompleted = false;
33565				}
33566				else {
33567					$(itemVariationQuantityField).removeClass('has-error');
33568				}
33569
33570
33571				var itemVariationSkuValue = $(itemVariationSkuField).find('.input').val();
33572				if (itemVariationSkuValue == '') {
33573					$(itemVariationSkuField).addClass('has-error');
33574					variationsFieldsCompleted = false;
33575				}
33576				else {
33577					$(itemVariationSkuField).removeClass('has-error');
33578				}
33579
33580			}
33581
33582			return variationsFieldsCompleted;
33583
33584		}		
33585
33586		_conIItemOptions.saveVariations = function(elem) {
33587						
33588			console.log('save variations');
33589
33590			var itemVariationsArray = [];
33591
33592			var validateVariationResult = validateVariations();
33593
33594			if (validateVariationResult) {
33595
33596				var itemVariationsList = $('#variations-list');
33597				var itemVariationsCount = itemVariationsList.find('.item-variations-inner').find('.item-variation').length;
33598				for (var i=0; i < itemVariationsCount; i++) {
33599					var itemVariationRow = itemVariationsList.find('.item-variations-inner').find('.item-variation')[i];
33600					var itemVariationNameField = $(itemVariationRow).find('.control.variation-name');
33601					var itemVariationPriceField = $(itemVariationRow).find('.control.required.variation-price');
33602					var itemVariationQuantityField = $(itemVariationRow).find('.control.required.variation-quantity');
33603					var itemVariationSkuField = $(itemVariationRow).find('.control.required.variation-sku');
33604					var itemVariationImageField = $(itemVariationRow).find('.control.variation-image');
33605	
33606					var itemVariationNameValue = $($(itemVariationNameField).find('span')[0]).text();
33607					var itemVariationIdValue = $($(itemVariationNameField).find('span')[1]).text();
33608
33609					var itemVariationPriceValue = $(itemVariationPriceField).find('.input').val();
33610					var itemVariationQuantityValue = $(itemVariationQuantityField).find('.input').val();
33611					var itemVariationSkuValue = $(itemVariationSkuField).find('.input').val();
33612					var itemVariationImageId = $(itemVariationImageField).find('#item-image-id').val();
33613
33614					var itemVariation = new Object();
33615					itemVariation.ItemVariationId = itemVariationIdValue;
33616					itemVariation.PrimaryInventoryId = _itemId;
33617					itemVariation.ProviderId = GLO.Data.provider.id;
33618					itemVariation.Name = itemVariationNameValue;
33619					itemVariation.Price  = itemVariationPriceValue;
33620					itemVariation.Quantity = itemVariationQuantityValue;
33621					itemVariation.Sku = itemVariationSkuValue;
33622
33623					var itemImage = new Object();
33624					itemImage.ItemImageId = itemVariationImageId;
33625					itemImage.InventoryId = _itemId;
33626
33627					itemVariation.Image = itemImage;
33628					itemVariation.IsAvailableInStore = true;
33629					itemVariation.IsValid = true;
33630
33631					itemVariationsArray.push(itemVariation);
33632
33633				}
33634
33635				var jsonString= JSON.stringify(itemVariationsArray);
33636
33637				var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateItemVariations';
33638
33639				var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonString, contentType: "application/json"})
33640				.success(function(data, textStatus, jqXHR) {
33641					if (UTIL.Validate.hasPermissionError(data)) { return; }
33642					// GLO.Inventory.Item.Options.getItemVariations(_itemId);
33643					GLO.Popup.Success.open('Product Variations updated.');
33644	
33645				})
33646				.error(function(jqXHR, textStatus, errorThrown) {
33647					new GLO.Popup.Error('Unable to save product variations.  Please try again.');
33648					GLO.UI.Form.resetProcessing();
33649				});					
33650
33651			}
33652		}
33653
33654		_conIItemOptions.cancelVariationEdit = function(elem) { 
33655			//reload variations list
33656			GLO.Inventory.Item.Options.getItemVariations(_itemId);
33657		}
33658
33659		return _conIItemOptions;
33660	})();
33661
33662	_conIItem.launchItemOptions = function(event) {
33663    	var uri = GLO.Link.Page.Provider.Home + 'Inventory/itemoptions?id=' + GLO.Uri.hash('id');
33664    	
33665    	if (event.ctrlKey) {
33666    		var childWindow = UI.openChildWindow(uri, '', true);
33667    	} else {
33668    		document.location = uri;
33669    	}
33670    }
33671
33672    _conIItem.lookup = function() {
33673    	var htm = $('<div> <h1 class="friendly-msg2" style="padding-top: 6px; font-size: larger;">' + SA.Resource.ProductLookup + '</h1>'
33674    			+ '<div class="friendly-msg2" style="min-width: 300px;">' 
33675    			+ '<div style="margin-top: 20px; margin-bottom: 12px; padding-left: 20px; padding-right: 20px;">' + SA.Resource.LookupProduct + '</div>'
33676    			+ '<input type="text" id="inventory-product-lookup-autocomplete" style="padding: 8px; letter-spacing: 1px; font-size: 16px;"/>'
33677    			+ '</div> </div>');
33678        
33679        var ojpop = new GLO.Popup.Custom(htm);
33680        var jpop = ojpop.getPopup().addClass('no-persist');
33681		var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" });				//.addClass('pop-buttons2');
33682		jbtns.find('.btnSave').remove();
33683		jbtns.find('.btnCancel').css({ "letter-spacing": "1px" });
33684		
33685		var top = UTIL.coalesceInt(jpop.css('top').replace('px', ''), 200);
33686		
33687		if (top > 200) {
33688			jpop.css({ "top": "100px" });
33689		}
33690		
33691		var jsearch = jpop.find('#inventory-product-lookup-autocomplete');
33692		
33693		jsearch.autocomplete({
33694            source: GLO.Link.Object.Provider.Ajax + 'ProductSearch',
33695            minLength: 2,
33696            select: function(event, ui) {
33697                ojpop.close();
33698                GLO.Inventory.updateHash('edit-product', ui.item.id);
33699            }
33700        });
33701        
33702        jsearch.focus();
33703    }
33704
33705	_conIItem.openAddBundleChildProduct = function(event) {
33706		//GLO.Mobile.getViewport(); return;			//DEBUG ONLY.
33707		if (GLO.Sale.Keypad.mustOpenKeypad()) { return; }
33708		
33709		$("#pop-quick-sell").modal();
33710		
33711		var jmodal = $("#simplemodal-container").css({ "top": "4px", "padding": "0", "border-radius": "20px" });
33712		var jtxt = jmodal.find('#quick-sell-product-name');
33713		
33714		jmodal.find('a.modalCloseImg').css({ "top": "4px", "right": "6px" });
33715		
33716		if (GLO.Info.isMobile()) {
33717			var w = 360;
33718			
33719			if (innerWidth < 370) { w = innerWidth * .96; }
33720			
33721			var left = parseInt((innerWidth - w)/2) - 4 + 'px';
33722			
33723			$.modal.update(140, w);
33724			jmodal.css({ "top": "4px", "left": left });
33725			jmodal.find('.modalCloseImg').attr("style", "top: 5px !important;");
33726		} else {
33727			$.modal.update(150, 450);
33728			jmodal.css({ "top": "100px" });
33729			jmodal.draggable({ "handle": "h1" }).find('h1').css({ "cursor": "move" });
33730		}
33731		
33732		jtxt.autocomplete({
33733			source: GLO.Link.Object.Provider.Ajax + 'ProductSearch',
33734			minLength: 2,
33735			autoFocus: true,
33736			open: function(event, ui) {
33737				$('.ui-autocomplete.auto-select-first-item').find('li:first').click();
33738			},
33739			select: function(event, ui) {
33740				var bundleChildProductEl = '<div data-id="' + ui.item.id + '" style="background-color: #ADD8E6;color: #000;border-radius: 5px;padding: 10px;font-size: 100%;">' + ui.item.value + ' - $' + ui.item.price_mn +  '</div>'
33741				$('#bundle-product-items').append(bundleChildProductEl);
33742				GLO.Inventory.Item.addProductToBundle(ui.item.id)
33743				GLO.UI.Form.resetProcessing();
33744				$.modal.close();
33745
33746			}
33747		});
33748		
33749		jtxt.data("ui-autocomplete")._renderMenu = function(ul, items) {
33750			  var that = this;
33751			  
33752			  $.each(items, function(index, item) {
33753				that._renderItemData(ul, item);
33754			  });
33755			  
33756			$(ul).find("li:odd").addClass("odd");
33757			
33758			if (items.length === 1 && items[0].is_sku_upc_match_fl == 1) {
33759				$(ul).addClass('auto-select-first-item', true);
33760			}
33761		};
33762		
33763		jtxt.focus();
33764	}
33765
33766	_conIItem.addProductToBundle = function(childInventoryId) {
33767		var uri = GLO.Link.Page.Provider.Home + 'Inventory/UpdateBom';
33768        // GLO.UI.Form.beginProcessing();
33769        
33770        var frm = $('#inventory-item-form');
33771		var iid = frm.find('#Inventory_id').val();
33772		
33773        var jsonData = {
33774			"ParentInventoryId": iid,
33775			"ChildInventoryId": childInventoryId,
33776			"Quantity":1
33777		};
33778
33779
33780        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData})
33781            .success(function(data, textStatus, jqXHR) {
33782                if (UTIL.Validate.hasPermissionError(data)) { return; }
33783                // TODO:disable price and calculate total price
33784				$('#Price_mn').attr('disabled','disabled');
33785				$('#Employee_Price_mn').attr('disabled','disabled')
33786
33787
33788
33789            })
33790            .error(function(jqXHR, textStatus, errorThrown) {
33791                new GLO.Popup.Error('Unable to add child product at this time.  Please try again later.');
33792                GLO.UI.Form.resetProcessing();
33793            });		
33794	}	
33795    
33796
33797	_conIItem.removeProductsFromBundle = function(parentInventoryId) {
33798		var uri = GLO.Link.Page.Provider.Home + 'Inventory/DeleteBom';
33799        // GLO.UI.Form.beginProcessing();
33800        
33801        var frm = $('#inventory-item-form');
33802		var iid = frm.find('#Inventory_id').val();
33803		
33804        var jsonData = {
33805			"ParentInventoryId": iid,
33806			"ChildInventoryId": 0,
33807			"Quantity":1
33808		};
33809
33810
33811        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonData})
33812            .success(function(data, textStatus, jqXHR) {
33813                if (UTIL.Validate.hasPermissionError(data)) { return; }
33814                GLO.Inventory.Item.getBundleProducts(iid);
33815
33816            })
33817            .error(function(jqXHR, textStatus, errorThrown) {
33818                new GLO.Popup.Error('Unable to delete child products at this time.  Please try again later.');
33819                GLO.UI.Form.resetProcessing();
33820            });		
33821	}	
33822
33823	_conIItem.getBundleProducts = function(inventoryId) {
33824		var uri = GLO.Link.Page.Provider.Home + 'Inventory/GetBom?id=' + inventoryId;
33825	
33826		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
33827			.done(function(data, textStatus, jqXHR) {
33828				window.onbeforeunload = null;
33829				if(data!=null && data!== '') {
33830					var childProducts = data;
33831					if (childProducts.length > 0) {
33832						$('#Price_mn').attr('disabled','disabled');
33833						$('#Employee_Price_mn').attr('disabled','disabled');
33834						$('#Avg_Cost_mn').attr("onclick","");
33835						GLO.Inventory.Item.generateBundleProductChildProductsGrid(childProducts);
33836					}
33837					else {
33838						//display blank state
33839						resetChildProductsGrid();
33840						$('#Price_mn').removeAttr('disabled');
33841						$('#Employee_Price_mn').removeAttr('disabled');
33842						$('#Avg_Cost_mn').attr("onclick","GLO.Inventory.Item.openCostPopup()");
33843					}
33844				  } else {
33845					new GLO.Popup.Error('Could not get the child products. Please try again later.');
33846				  }				
33847			})
33848			.fail(function(jqXHR, textStatus, errorThrown) {
33849				GLO.UI.Form.resetProcessing(); 		
33850				new GLO.Popup.Error('Could not get the product images');
33851			});
33852	}
33853
33854	var resetChildProductsGrid = function() {
33855		var childProductsGrid = $('#bundle-product-items');
33856		childProductsGrid.html("");
33857	}
33858
33859	_conIItem.generateBundleProductChildProductsGrid = function(childProducts) {
33860
33861
33862		resetChildProductsGrid();
33863
33864		childProducts.forEach(childProduct => {
33865			var productMeta = '';
33866			if (childProduct.Size) {
33867				productMeta = childProduct.Size + ' ' + childProduct.UnitofMeasure;
33868			}
33869			if (childProduct.VendorName) {
33870				productMeta = productMeta + ' (' + childProduct.VendorName + ')';
33871			}
33872			var bundleChildProductEl = '<div data-id="' + childProduct.ChildInventoryId + '" style="background-color: #ADD8E6;color: #000;border-radius: 5px;padding: 10px;font-size: 100%;">' + childProduct.Name + ' ' + productMeta + ' - $' + childProduct.Price +  '</div>'
33873			$('#bundle-product-items').append(bundleChildProductEl);			
33874		});
33875	}
33876	
33877    return _conIItem;
33878})();
33879
33880
33881GLO.Inventory.Location = (function() {
33882    function _cILocation() { }
33883	
33884	_cILocation.initProductSummary = function(jpop) {
33885		var uls = jpop.find('ul.shipment-location-list');
33886		
33887		for (var i=0; i < uls.length; i++) {
33888			if (uls.eq(i).find('.event-location').length > 1) {
33889				uls.eq(i).sortable({ "update": GLO.Inventory.Location.updateSortOrder }).find('.ui-icon,.btnMove').disableSelection();
33890			}
33891		}
33892	}
33893	
33894	_cILocation.updateSortOrder = function(ev, dropObj) {
33895        //var id = dropObj.item.attr('id');
33896        //var old_sort_sr = parseInt(dropObj.item.attr('sort_sr'));
33897        
33898        var xml = '', ul = dropObj.item.closest('ul.shipment-location-list');
33899        var list = ul.find('>li');
33900        var parentEventId = ul.parent().attr('event_id');
33901        var iid = $('#inventory-item-summary').find('h1').attr('inventory_id');
33902        
33903        for (var i=0; i < list.length; i++) {
33904            var id = list.eq(i).attr('sub_event_id');
33905            
33906            xml += '<li sub_event_id="' + id + '" sort_sr="' + (i + 100) + '"/>';
33907        }
33908        
33909        var uri = GLO.Link.Page.Provider.Home + 'Inventory/SortMoveProduct';
33910		var ol = UTIL.htmlEncode('<ol>' + xml + '</ol>');
33911		var jd = { "inventory_id": iid, "parent_event_id": parentEventId, "sort_xml": ol }
33912		
33913        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
33914            .success(function(data, textStatus, jqXHR) {
33915                //alert("success:" + data + '\n\ndivID = ' + jDiv.html());
33916            })
33917            .error(function(jqXHR, textStatus, errorThrown) {
33918                //alert("error: updateSortOrder()\n" + textStatus);
33919                var abc = 123;
33920            });
33921    }
33922	
33923	_cILocation.openMove = function(btn) {
33924		var jPopItem = $('#inventory-item-summary');
33925		var h1 = jPopItem.find('h1');
33926        var iid = h1.attr('inventory_id');
33927        var h1 = UTIL.coalesce($.trim(h1.text()), 'Product') + ' Location';
33928		
33929		var liMoveEvent = $(btn).closest('li.event-move');
33930		var liOrderEvent = liMoveEvent.closest('li.recent-activity-order');
33931		
33932		var moveCount = UTIL.coalesceInt(liMoveEvent.find('.event-stock-count').text(), 0);
33933		var subEventId = UTIL.cleanString(liMoveEvent.attr('sub_event_id'));
33934		var sort = UTIL.cleanString(liMoveEvent.attr('sort_sr'));
33935		var note = UTIL.cleanString(liMoveEvent.find('.event-note').text());
33936		var locationId = liMoveEvent.attr('location_id');		//create_dt, update_by_staff_id
33937		var isle = UTIL.cleanString(liMoveEvent.find('.event-isle > i').text());
33938		var shelf = UTIL.cleanString(liMoveEvent.find('.event-shelf > i').text());
33939		var rack = UTIL.cleanString(liMoveEvent.find('.event-rack > i').text());
33940		
33941		var orderCount = UTIL.coalesceInt(liOrderEvent.find('.event-count').text(), 0);
33942		var parentEventId = liOrderEvent.attr('event_id');
33943		
33944		var div = '<div id="pop-edit-move-event" inventory_id="' + iid + '" parent_event_id="' + parentEventId + '" sub_event_id="' + subEventId + '" sort_sr="' + sort + '">';
33945		var htm = div + $('#item-move-location-edit').outerHTML() + '</div>';
33946		
33947		var jpop = GLO.Popup.Custom.openSimple(htm, h1, GLO.Inventory.Location.saveMove);
33948		jpop.find('#Move_Count_sr').val(moveCount).attr('max', orderCount);
33949		jpop.find('#Event_Note_vc').val(note);
33950		
33951		jpop.find('#Location_id').val(locationId);
33952		jpop.find('#Isle_vc').val(isle);
33953		jpop.find('#Shelf_vc').val(shelf);
33954		jpop.find('#Rack_vc').val(rack);
33955	}
33956	_cILocation.saveMove = function() {
33957        var uri = GLO.Link.Page.Provider.Home + 'Inventory/MoveProduct';
33958        var jpop = $('#pop-edit-move-event');
33959        
33960        var iid = jpop.attr('inventory_id'), parentEventId = jpop.attr('parent_event_id'), subEventId = jpop.attr('sub_event_id'), sort = jpop.attr('sort_sr');
33961        var moveCount = UTIL.coalesceInt(jpop.find('#Move_Count_sr').val(), 0);
33962        
33963        var locationId = jpop.find('#Location_id').val();
33964        var isle = UTIL.htmlEncode(jpop.find('#Isle_vc').val());
33965        var shelf = UTIL.htmlEncode(jpop.find('#Shelf_vc').val());
33966        var rack = UTIL.htmlEncode(jpop.find('#Rack_vc').val());
33967        var note = UTIL.htmlEncode(jpop.find('#Event_Note_vc').val());
33968        
33969        var jd = { "inventory_id": iid, "parent_event_id": parentEventId, "sub_event_id": subEventId, "count": moveCount
33970        			, "location_id": locationId, "isle": isle, "shelf": shelf, "rack": rack, "note": note };
33971        
33972        jpop = jpop.closest('.glopop');
33973        GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
33974
33975        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
33976            .success(function(data, textStatus, jqXHR) {
33977                if (UTIL.Validate.hasPermissionError(data)) { return; }
33978                
33979                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
33980                	GLO.Popup.Warning.open(data, 'Move Invalid');
33981                	return;
33982                }
33983                
33984                GLO.Popup.close(jpop);
33985                var jPopItem = $('#inventory-item-summary').closest('.simplemodal-container');
33986                
33987                if (jPopItem.length) {
33988                	$.modal.close();
33989                }
33990                
33991                GLO.Popup.Success.open('Location Saved');
33992                //jpop.find('.btnSave a').css({ "border": "3px solid transparent" });
33993            })
33994            .error(function(jqXHR, textStatus, errorThrown) {
33995                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
33996                GLO.UI.Form.resetProcessing();
33997            });
33998    }
33999    _cILocation.removeMove = function(btn) {
34000    	var fnYes = function() {
34001    		GLO.Inventory.Location.removeMoveConfirmed(btn);
34002    	}
34003    	var htm = 'Remove these products from this location?';
34004    	GLO.Popup.Confirm.open(htm, 'Remove From Location?', fnYes);
34005    }
34006    _cILocation.removeMoveConfirmed = function(btn) {
34007        var uri = GLO.Link.Page.Provider.Home + 'Inventory/RemoveMoveProduct';
34008        var liMoveEvent = $(btn).closest('li.event-move');
34009        
34010        var iid = $('#inventory-item-summary').closest('.simplemodal-container').find('h1').attr('inventory_id');
34011        var subEventId = liMoveEvent.attr('sub_event_id');
34012        var parentEventId = liMoveEvent.closest('li.recent-activity-order').attr('event_id');
34013        var jd = { "inventory_id": iid, "parent_event_id": parentEventId, "sub_event_id": subEventId };
34014        
34015        var jprocessing = GLO.Popup.Processing.open('Remove products...', 'Product Location');
34016
34017        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
34018            .success(function(data, textStatus, jqXHR) {
34019                if (UTIL.Validate.hasPermissionError(data)) { return; }
34020                
34021                if (!UTIL.isEmpty($(data).attr('warning_cd'))) {
34022                	GLO.Popup.Warning.open(data, 'Move Invalid');
34023                	return;
34024                }
34025                
34026                jprocessing.close();
34027                var jPopItem = $('#inventory-item-summary').closest('.simplemodal-container');
34028                
34029                if (jPopItem.length) {
34030                	$.modal.close();
34031                }
34032                
34033                GLO.Popup.Success.open('Products Removed from Location');
34034                //jpop.find('.btnSave a').css({ "border": "3px solid transparent" });
34035            })
34036            .error(function(jqXHR, textStatus, errorThrown) {
34037                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34038                GLO.UI.Form.resetProcessing();
34039            });
34040    }
34041	
34042	_cILocation.openBasicHelp = function(id) {
34043    	var msg = 'The order location fields (location, isle, shelf, rack) allow you to enter where you stocked this order so you can easily locate it when needed';
34044    	GLO.Popup.Info.open(msg, 'Order Location');
34045    }
34046    
34047	_cILocation.openList = function() {
34048        var list = '', jd = $('#order-editable-fields select#Location_id option');
34049
34050        if (jd.length > 1) {
34051            for (var i=1; i < jd.length; i++) {
34052                list += '<li location_id="' + jd.eq(i).attr('value') + '">' + jd.eq(i).text() + '</li>';
34053            }
34054
34055            $('#inventory-location-list').removeClass('hide').find('ul').html(list);
34056        } else {
34057            GLO.Inventory.updateHash('new-location')
34058        }
34059    }
34060
34061    _cILocation.openEdit = function(id, name) {
34062        var j = $('#inventory-location-edit');
34063        
34064        if (!UTIL.isEmpty(id)) {
34065            var h2 = 'Edit Location';
34066            j.find('.btnDelete').removeClass('hide');
34067        } else {
34068            var h2 = 'New Location';
34069            j.find('.btnDelete').addClass('hide');
34070            id = name = '';
34071        }
34072
34073        j.find('#Location_Name_vc').val(name);
34074        j.attr('location_id', id);
34075        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34076        j.removeClass('hide');
34077        j.find('input:first').focus();
34078    }
34079	
34080    _cILocation.back = function(isEdit) {
34081        if (isEdit && $('#order-editable-fields select#Location_id option').length > 0) {
34082        	GLO.Inventory.updateHash('location-list');
34083        	return;
34084        } else if (!UTIL.isEmpty(GLO.Inventory.prevHash)) {
34085        	var prev = GLO.Inventory.prevHash.toLowerCase();
34086        	
34087        	if (prev.indexOf('new-location') === -1 && prev.indexOf('edit-location') === -1) {
34088	        	GLO.Inventory.updateHash(GLO.Inventory.prevHash);
34089	        	return;
34090        	}
34091        }
34092        
34093        GLO.Inventory.updateHash('order-create');
34094    }
34095    
34096    _cILocation.save = function() {
34097        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Location';
34098        var j = $('#inventory-location-edit');
34099        
34100        var id = j.attr('location_id');
34101        var nm = j.find('#Location_Name_vc').val();
34102        
34103        if (UTIL.isEmpty(nm)) {
34104            GLO.Popup.Warning('Please enter a location name', function() { $('#inventory-location-edit #Location_Name_vc').focus(); });
34105            return;
34106        }
34107        
34108        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34109
34110        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id, "name": nm } })
34111            .success(function(data, textStatus, jqXHR) {
34112                if (UTIL.Validate.hasPermissionError(data)) { return; }
34113                
34114                GLO.Popup.Success.open('Location Saved');
34115                j.find('.btnSave a').css({ "border": "3px solid transparent" });
34116                
34117                if (UTIL.isEmpty(id)) {
34118                    var newOption = '<option value="' + $(data).attr('location_id') + '">' + nm + '</option>';
34119                    $('select#Location_id').find('option:first').after(newOption);
34120                } else {
34121                    $('select#Location_id option[value="' + id + '"]').text(nm);
34122                    location.reload();
34123                }
34124
34125                GLO.Inventory.updateHash('location-list');
34126            })
34127            .error(function(jqXHR, textStatus, errorThrown) {
34128                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34129                GLO.UI.Form.resetProcessing();
34130            });
34131    }
34132    
34133    _cILocation.remove = function() {
34134        var uri = GLO.Link.Page.Provider.Home + 'Inventory/LocationDelete';
34135        var id = $('#inventory-location-edit').attr('location_id');
34136        GLO.UI.Form.beginProcessing( $('#inventory-location-edit .btnDelete') );
34137
34138        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
34139            .success(function(data, textStatus, jqXHR) {
34140                if (UTIL.Validate.hasPermissionError(data)) { return; }
34141                
34142                var jdata = $(data);
34143
34144                if (jdata.attr('error_cd')) {
34145                    GLO.Popup.Warning.open(jdata, 'Delete Location');
34146                } else {
34147                    GLO.Popup.Success.open('Location Deleted');
34148                    $('select#Location_id option[value="' + id + '"]').remove();
34149
34150                    GLO.Inventory.updateHash('location-list');
34151                }
34152            })
34153            .error(function(jqXHR, textStatus, errorThrown) {
34154                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
34155                GLO.UI.Form.resetProcessing();
34156            });
34157    }
34158
34159    return _cILocation;
34160})();
34161
34162
34163GLO.Inventory.Vendor = (function() {
34164    function _conVendor() { }
34165
34166    _conVendor.back = function() {
34167        GLO.Inventory.Item.unHide();
34168    }
34169
34170    _conVendor.openEdit = function(id, name, distributorId, distributorName) {
34171        //$('#inventory-item-form:visible').addClass('hide');
34172        //$('#inventory-vendor-list:visible').addClass('hide');
34173
34174        var j = $('#inventory-vendor-edit');
34175        
34176        if (!UTIL.isEmpty(id)) {
34177            var h2 = SA.Resource.EditBrand;
34178            j.find('.btnDelete').removeClass('hide');
34179
34180            if (!UTIL.isEmpty(distributorId)) { distributorName = ''; }
34181        } else {
34182            var h2 = SA.Resource.NewBrand;
34183            j.find('.btnDelete').addClass('hide');
34184
34185            id = name = distributorId = distributorName = '';
34186        }
34187
34188        j.find('#Vendor_Name_vc').val(name);
34189        j.find('#Vendor_id').val(id);
34190
34191        j.find('#Distributor_id').val(distributorId);
34192        j.find('#New_Distributor_vc').val(distributorName);
34193
34194        if (j.find('#Distributor_id option').length > 0) {
34195            j.find('#inventory-distributor-existing').removeClass('hide');
34196            j.find('#inventory-distributor-or').removeClass('hide');
34197        } else {
34198            j.find('#inventory-distributor-existing').addClass('hide');
34199            j.find('#inventory-distributor-or').addClass('hide');
34200        }
34201
34202        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34203        j.removeClass('hide');
34204        j.find('input:first').focus();
34205    }
34206
34207    _conVendor.openList = function() {
34208        var jd = $('select#Vendor_id option');
34209
34210        if (jd.length > 0) {
34211            var dlist = '';
34212            
34213            for (var i=1; i < jd.length; i++) {
34214                var vid = jd.eq(i).attr('value');
34215                var did = $.trim(jd.eq(i).attr('distributor_id'));
34216                var liCSS = '', vendorMerchantId = jd.eq(i).attr('vendor_merchant_id');
34217                var vname = jd.eq(i).text();
34218                
34219                if (vendorMerchantId > 0) {
34220                	var merchant = UserPortal.Price.Payment.getMerchant(vendorMerchantId);
34221                	
34222                	if (merchant && merchant.name) {
34223                		var merchantName = UTIL.coalesceString(merchant.friendly_name, merchant.name);
34224                		liCSS = 'has-custom-product-merchant';
34225                		vname += '<span class="merchant-name-icon"><b>' + merchantName + '</b></span>';
34226                	}
34227                }
34228                
34229                dlist += '<li class="' + liCSS + '" vendor_id="' + vid + '" distributor_id="' + did + '">' + vname + '</li>';
34230            }
34231
34232            $('#inventory-vendor-list').removeClass('hide').find('ul').html(dlist);
34233        } else {
34234            _conVendor.openEdit();
34235        }
34236    }
34237
34238    _conVendor.openDistributorList = function() {
34239        var jd = $('select#Distributor_id option');
34240
34241        if (jd.length > 0) {
34242            var dlist = '';
34243            
34244            for (var i=1; i < jd.length; i++) {
34245                dlist += '<li distributor_id="' + jd.eq(i).attr('value') + '">' + jd.eq(i).text() + '</li>';
34246            }
34247
34248            $('#inventory-distributor-list').removeClass('hide').find('ul').html(dlist);
34249        } else {
34250            _conVendor.openEdit();
34251        }
34252    }
34253
34254    _conVendor.openDistributorEdit = function(id, nm) {
34255        var j = $('#inventory-distributor-edit');
34256
34257        if (!UTIL.isEmpty(id)) {
34258            j.find('.btnDelete').removeClass('hide');
34259
34260            j.find('tr').attr('distributor_id', id);
34261            j.find('#Distributor_Name_vc').val(nm);         //$('select#Distributor_id option[value="' + id + '"]').text()
34262        } else {
34263            j.find('.btnDelete').addClass('hide');
34264
34265            j.find('tr').attr('distributor_id', '');
34266            j.find('#Distributor_Name_vc').val('');
34267        }
34268
34269        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34270        j.removeClass('hide');
34271        j.find('input:first').focus();
34272    }
34273
34274    _conVendor.backFromDistributor = function() {
34275        GLO.Inventory.Item.unHide();
34276    }
34277
34278    _conVendor.saveDistributor = function() {
34279        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Distributor';
34280        var j = $('#inventory-distributor-edit');
34281        
34282        var distributorId = j.find('tr').attr('distributor_id');
34283        var distributorName = j.find('#Distributor_Name_vc').val();
34284
34285        if (UTIL.isEmpty(distributorName)) {
34286            GLO.Popup.Warning(SA.Resource.PleaseDistributorName, function() { $('#inventory-distributor-edit #Distributor_Name_vc').focus(); });
34287            return;
34288        }
34289        
34290        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34291
34292        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": distributorId, "name": distributorName } })
34293            .success(function(data, textStatus, jqXHR) {
34294                if (UTIL.Validate.hasPermissionError(data)) { return; }
34295                
34296                new GLO.Popup.Success(SA.Resource.DistributorSaved);
34297                j.find('.btnSave a').css({ "border": "3px solid transparent" });
34298                
34299                if (UTIL.isEmpty(distributorId)) {
34300                    distributorId = $(data).attr('distributor_id');
34301
34302                    $('#inventory-vendor-edit').find('#Distributor_id').find('option:first').after('<option value="' + distributorId + '">' + distributorName + '</option>');
34303                    $('#Filter_Company').find('option:first').after('<option class="d-option" value="d' + distributorId + '">' + distributorName + '</option>');
34304                } else {
34305                    $('#inventory-vendor-edit').find('#Distributor_id option[value="' + distributorId + '"]').text(distributorName);
34306                    $('#Filter_Company').find('option[value="d' + distributorId + '"]').text(distributorName);
34307                }
34308
34309                GLO.Inventory.updateHash('distributor-list');
34310            })
34311            .error(function(jqXHR, textStatus, errorThrown) {
34312                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34313                GLO.UI.Form.resetProcessing();
34314            });
34315    }
34316
34317    _conVendor.removeDistributor = function() {
34318        var uri = GLO.Link.Page.Provider.Home + 'Inventory/DistributorDelete';
34319        var j = $('#inventory-distributor-edit');
34320        
34321        var distributorId = j.find('tr').attr('distributor_id');
34322        var distributorName = j.find('#Distributor_Name_vc');
34323        GLO.UI.Form.beginProcessing(j.find('.btnDelete'));
34324        
34325        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": distributorId } })
34326            .success(function(data, textStatus, jqXHR) {
34327                if (UTIL.Validate.hasPermissionError(data)) { return; }
34328                
34329                var jdata = $(data);
34330
34331                if (jdata.attr('error_cd')) {
34332                    var ojpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Delete Distributor');
34333                    ojpop.addScrollBar();
34334                } else {
34335                    new GLO.Popup.Success(SA.Resource.DistributorRemoved);
34336                    $('select#Distributor_id option[value="' + distributorId + '"]').remove();
34337                    $('#Filter_Company').find('option[value="d' + distributorId + '"]').remove();
34338
34339                    GLO.Inventory.updateHash('distributor-list');
34340                }
34341            })
34342            .error(function(jqXHR, textStatus, errorThrown) {
34343                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
34344                GLO.UI.Form.resetProcessing();
34345            });
34346    }
34347
34348    _conVendor.save = function() {
34349        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Vendor';
34350        var j = $('#inventory-vendor-edit');
34351        
34352        var vid = j.find('#Vendor_id').val();
34353        var vnm = j.find('#Vendor_Name_vc').val();
34354
34355        var did = j.find('#Distributor_id').val();
34356        var dnm = j.find('#New_Distributor_vc').val();
34357
34358        if (UTIL.isEmpty(vnm)) {
34359            GLO.Popup.Warning(SA.Resource.PleaseEnterBrandName, function() { $('#inventory-vendor-edit #Vendor_Name_vc').focus(); });
34360            return;
34361        }
34362
34363        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34364        
34365        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "vid": vid, "vname": vnm, "did": did, "dname": dnm } })
34366            .success(function(data, textStatus, jqXHR) {
34367                if (UTIL.Validate.hasPermissionError(data)) { return; }
34368                
34369                new GLO.Popup.Success(SA.Resource.BrandSaved);
34370                j.find('.btnSave a').css({ "border": "3px solid transparent" });
34371
34372                var jdata = $(data);
34373
34374                if (!UTIL.isEmpty(vid)) {
34375                    document.location = GLO.Link.Page.Provider.Home + 'inventory#action=vendor-list';
34376                    new GLO.Popup.Processing('Loading Update...');
34377                    location.reload();
34378                    return;
34379                } else {
34380                    var newOption = '<option value="' + jdata.attr('vendor_id') + '" distributor_id="' + jdata.attr('distributor_id') + '">' + vnm + '</option>';
34381                    
34382                    $('select#Vendor_id').find('option:first').after(newOption);
34383                    $('select#Existing_Vendor_id').find('option:first').after(newOption);
34384                    
34385                    var filterOption = '<option class="v-option" value="v' + jdata.attr('vendor_id') + '">' + GLO.Inventory.filterIndent + vnm + '</option>';
34386                    $('select#Filter_Company').find('option:first').after(filterOption);
34387                }
34388
34389                if (UTIL.isEmpty(did) && !UTIL.isEmpty(dnm)) {
34390                    $('select#Distributor_id').prepend('<option value="' + jdata.attr('distributor_id') + '">' + dnm + '</option>');
34391                    $('select#Filter_Company').prepend('<option class="d-option" value="d' + jdata.attr('distributor_id') + '">' + dnm + '</option>');
34392                }
34393
34394                GLO.Inventory.updateHash('vendor-list');
34395            })
34396            .error(function(jqXHR, textStatus, errorThrown) {
34397                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34398                GLO.UI.Form.resetProcessing();
34399            });
34400    }
34401
34402    _conVendor.remove = function() {
34403        var uri = GLO.Link.Page.Provider.Home + 'Inventory/VendorDelete';
34404        var j = $('#inventory-vendor-edit');
34405        var id = j.find('#Vendor_id').val();
34406        GLO.UI.Form.beginProcessing(j.find('.btnDelete'));
34407
34408        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
34409            .success(function(data, textStatus, jqXHR) {
34410                if (UTIL.Validate.hasPermissionError(data)) { return; }
34411                
34412                var jdata = $(data);
34413
34414                if (jdata.attr('error_cd')) {
34415                    var ojpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Delete Brand');
34416                    ojpop.addScrollBar();
34417                } else {
34418                    new GLO.Popup.Success(SA.Resource.BrandRemoved);
34419                    $('#inventory-item-edit').find('#Vendor_id option[value="' + id + '"]').remove();
34420                    $('#inventory-product-line-edit').find('#Existing_Vendor_id option[value="' + id + '"]').remove();
34421                    $('select#Filter_Company').find('option[value="v' + id + '"]').remove();
34422
34423                    GLO.Inventory.updateHash('vendor-list');
34424                }
34425            })
34426            .error(function(jqXHR, textStatus, errorThrown) {
34427                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
34428                GLO.UI.Form.resetProcessing();
34429            });
34430    }
34431
34432    _conVendor.openProductLineEdit = function(id, name, vendorId, vendorName) {
34433        var j = $('#inventory-product-line-edit');
34434        
34435        if (!UTIL.isEmpty(id)) {
34436            var h2 = SA.Resource.EditProductLine;
34437            j.find('.btnDelete').removeClass('hide');
34438
34439            if (!UTIL.isEmpty(vendorId)) {
34440                var vname = $('select#Vendor_id option[value="' + vendorId + '"]').text();
34441                vendorName = '';
34442            } else {
34443                var vname = vendorName;
34444            }
34445
34446            name = name.replace(vname + ' - ', '');
34447        } else {
34448            var h2 = SA.Resource.NewProductLine;
34449            j.find('.btnDelete').addClass('hide');
34450
34451            id = name = vendorId = vendorName = '';
34452        }
34453
34454        j.find('#Product_Line_Name_vc').val(name);
34455        j.find('#Product_Line_id').val(id);
34456
34457        j.find('#Existing_Vendor_id').val(vendorId);
34458        j.find('#New_PL_Vendor_vc').val(vendorName);
34459
34460        if (j.find('#Existing_Vendor_id option').length > 0) {
34461            j.find('#inventory-vendor-existing').removeClass('hide');
34462            j.find('#inventory-vendor-or').removeClass('hide');
34463        } else {
34464            j.find('#inventory-vendor-existing').addClass('hide');
34465            j.find('#inventory-vendor-or').addClass('hide');
34466        }
34467
34468        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34469        j.removeClass('hide');
34470        j.find('input:first').focus();
34471    }
34472
34473    _conVendor.openProductLineList = function(isBackground) {
34474        var jpl = $('select#Product_Line_id option');
34475
34476        if (jpl.length > 0) {
34477            var vname, vendorId, pllist = '';
34478            var jv = $('select#Vendor_id');
34479
34480            for (var i=1; i < jpl.length; i++) {
34481                vendorId = jpl.eq(i).attr('vendor_id');
34482                vname = jv.find('option[value="' + vendorId + '"]').text();
34483                
34484                if (!UTIL.isEmpty(vname)) { vname = vname + ' - '; } else { vname = ''; }
34485
34486                pllist += '<li product_line_id="' + jpl.eq(i).attr('value') + '" vendor_id="' + vendorId + '">' + vname + jpl.eq(i).text() + '</li>';
34487            }
34488
34489            var plines = $('#inventory-product-line-list');
34490            plines.find('ul').html(pllist);
34491            
34492            if (!isBackground) {
34493            	plines.removeClass('hide');
34494            }
34495        } else if (!isBackground) {
34496            _conVendor.openProductLineEdit();
34497        }
34498    }
34499
34500    _conVendor.removeProductLine = function() {
34501        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ProductLineDelete';
34502        var j = $('#inventory-product-line-edit');
34503        var id = j.find('#Product_Line_id').val();
34504        GLO.UI.Form.beginProcessing(j.find('.btnDelete'));
34505
34506        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
34507            .success(function(data, textStatus, jqXHR) {
34508                if (UTIL.Validate.hasPermissionError(data)) { return; }
34509                
34510                var jdata = $(data);
34511
34512                if (jdata.attr('error_cd')) {
34513                    var ojpop = GLO.Popup.Warning.open(jdata.outerHTML(), 'Delete Product Line');
34514                    ojpop.addScrollBar();
34515                } else {
34516                    new GLO.Popup.Success(SA.Resource.ProductLineRemoved);
34517                    $('#inventory-item-edit').find('#Product_Line_id option[value="' + id + '"]').remove();
34518                    $('select#Filter_Company').find('option[value="p' + id + '"]').remove();
34519
34520                    GLO.Inventory.updateHash('product-line-list');
34521                }
34522            })
34523            .error(function(jqXHR, textStatus, errorThrown) {
34524                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
34525                GLO.UI.Form.resetProcessing();
34526            });
34527    }
34528
34529    _conVendor.saveProductLine = function() {
34530        var uri = GLO.Link.Page.Provider.Home + 'Inventory/ProductLine';
34531        var j = $('#inventory-product-line-edit');
34532        
34533        var plid = j.find('#Product_Line_id').val();
34534        var plnm = j.find('#Product_Line_Name_vc').val();
34535
34536        var vid = j.find('#Existing_Vendor_id').val();
34537        var vnm = j.find('#New_PL_Vendor_vc').val();
34538
34539        if (UTIL.isEmpty(plnm)) {
34540            GLO.Popup.Warning(SA.Resource.PleaseEnterProductLineName, function() { $('#inventory-product-line-edit #Product_Line_Name_vc').focus(); });
34541            return;
34542        } else if (UTIL.isEmpty(vnm) && UTIL.isEmpty(vid)) {
34543            GLO.Popup.Warning(SA.Resource.PleaseSelectBrand, function() { $('#inventory-product-line-edit #Existing_Vendor_id').focus(); });
34544            return;
34545        }
34546
34547        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34548        
34549        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "plid": plid, "plname": plnm, "vid": vid, "vname": vnm } })
34550            .success(function(data, textStatus, jqXHR) {
34551                if (UTIL.Validate.hasPermissionError(data)) { return; }
34552                
34553                new GLO.Popup.Success(SA.Resource.ProductLineSaved);
34554                j.find('.btnSave a').css({ "border": "3px solid transparent" });
34555
34556                var jdata = $(data);
34557
34558                if (!UTIL.isEmpty(plid)) {
34559                    document.location = GLO.Link.Page.Provider.Home + 'inventory#action=product-line-list';
34560                    new GLO.Popup.Processing('Loading Update...');
34561                    location.reload();
34562                    return;
34563
34564                    /*
34565                    $('select#Product_Line_id option[value="' + plid + '"]').text(plnm).attr('vendor_id', UTIL.cleanString(jdata.attr('vendor_id')));
34566                    $('select#Filter_Company').find('option[value="p' + plid + '"]').text(GLO.Inventory.filterIndent + GLO.Inventory.filterIndent + plnm);
34567                    
34568                    var jtds = $('#inventory-table').find('.item-product-line[product_line_id="' + plid + '"]');
34569
34570                    for (var i=0; i < jtds.length; i++) {
34571                        jtds.eq(i).text(plnm).attr('title', '');
34572                    }
34573                    */
34574                } else {
34575                    var vid = jdata.attr('vendor_id');
34576                    var plOption = '<option class="pl-option" value="p' + jdata.attr('product_line_id') + '">' + GLO.Inventory.filterIndent + plnm + '</option>';
34577                    
34578                    $('select#Product_Line_id').find('option:first').after('<option value="' + jdata.attr('product_line_id') + '" vendor_id="' + vid + '">' + plnm + '</option>');
34579                    $('select#Filter_Company').find('option[value="v' + vid + '"]').after(plOption);
34580                }
34581
34582                if (UTIL.isEmpty(vid) && !UTIL.isEmpty(vnm)) {
34583                    $('select#Vendor_id').find('option:first').after('<option value="' + jdata.attr('vendor_id') + '">' + vnm + '</option>');
34584                    $('select#Existing_Vendor_id').find('option:first').after('<option value="' + jdata.attr('vendor_id') + '">' + vnm + '</option>');
34585
34586                    $('select#Filter_Company').find('option:first').after('<option class="v-option" value="v' + jdata.attr('vendor_id') + '">' + GLO.Inventory.filterIndent + vnm + '</option>');
34587                }
34588
34589                GLO.Inventory.updateHash('product-line-list');
34590            })
34591            .error(function(jqXHR, textStatus, errorThrown) {
34592                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34593                GLO.UI.Form.resetProcessing();
34594            });
34595    }
34596    
34597    _conVendor.getSelected = function(jHead) {
34598    	var obj = {}, co = jHead.find('#Filter_Company').val();
34599        
34600        if (!UTIL.isEmpty(co)) {
34601            if (co.substring(0, 1) === 'v') {
34602                obj.vendor_id = co.substring(1);
34603            } else if (co.substring(0, 1) === 'd') {
34604                obj.distributor_id = co.substring(1);
34605            } else if (co.substring(0, 1) === 'p') {
34606                obj.vendor_id = $('select#Product_Line_id option[value="' + co.substring(1) + '"]').attr('vendor_id');
34607            }
34608        }
34609        
34610        return obj;
34611	}
34612    
34613    return _conVendor;
34614})();
34615
34616
34617GLO.Inventory.Type = (function() {
34618    function _conType() { }
34619
34620    _conType.back = function() {
34621        GLO.Inventory.Item.unHide();
34622    }
34623
34624    _conType.openEdit = function(id, name, categoryId, categoryName) {
34625        var j = $('#inventory-type-edit');
34626        
34627        if (!UTIL.isEmpty(id)) {
34628            j.find('.btnDelete').removeClass('hide');
34629
34630            if (!UTIL.isEmpty(categoryId)) { categoryName = ''; }
34631        } else {
34632            j.find('.btnDelete').addClass('hide');
34633
34634            id = name = categoryId = categoryName = '';
34635        }
34636
34637        j.find('#Type_Category_id').val(categoryId);
34638        j.find('#New_Type_Category_Name_vc').val(categoryName);
34639
34640        if (UTIL.isEmpty(categoryName)) { categoryName = j.find('#Type_Category_id option:selected').text(); }
34641        name = name.replace(categoryName + " - ", "")
34642
34643        j.find('#Type_Name_vc').val(name);
34644        j.find('tr').attr('inventory_type_id', id);
34645        
34646        if (j.find('#Type_Category_id option').length > 0) {
34647            j.find('#inventory-type-category-existing').removeClass('hide');
34648            j.find('#inventory-type-category-or').removeClass('hide');
34649        } else {
34650            j.find('#inventory-type-category-existing').addClass('hide');
34651            j.find('#inventory-type-category-or').addClass('hide');
34652        }
34653
34654        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34655        j.removeClass('hide');
34656        j.find('input:first').focus();
34657    }
34658
34659    _conType.openList = function() {
34660        var jd = $('select#Inventory_Type_id option');
34661
34662        if (jd.length > 0) {
34663            var dlist = '';
34664            
34665            for (var i=1; i < jd.length; i++) {
34666                var otherAttributes = '', defaultTypeId = jd.eq(i).attr('default_type_id'), defaultCategoryId = jd.eq(i).attr('default_type_category_id');
34667                
34668                if (UTIL.isNumber(defaultTypeId)) {
34669                	otherAttributes += ' default_type_id="' + defaultTypeId + '"';
34670                }
34671                if (UTIL.isNumber(defaultCategoryId)) {
34672                	otherAttributes += ' default_type_category_id="' + defaultCategoryId + '"';
34673                }
34674                
34675                dlist += '<li inventory_type_id="' + jd.eq(i).attr('value') + '" type_category_id="' + jd.eq(i).attr('type_category_id') + '"' + otherAttributes + '>' + jd.eq(i).text() + '</li>';
34676            }
34677
34678            $('#inventory-type-list').removeClass('hide').find('ul').html(dlist);
34679        } else {
34680            _conType.openEdit();
34681        }
34682    }
34683
34684    _conType.openCategoryList = function() {
34685        var jd = $('select#Type_Category_id option');
34686
34687        if (jd.length > 0) {
34688            var dlist = '';
34689            
34690            for (var i=1; i < jd.length; i++) {
34691                var otherAttributes = '', defaultCategoryId = jd.eq(i).attr('default_type_category_id');
34692                
34693                if (UTIL.isNumber(defaultCategoryId)) {
34694                	otherAttributes += ' default_type_category_id="' + defaultCategoryId + '"';
34695                }
34696                
34697                dlist += '<li type_category_id="' + jd.eq(i).attr('value') + '"' + otherAttributes + '>' + jd.eq(i).text() + '</li>';
34698            }
34699
34700            $('#inventory-type-category-list').removeClass('hide').find('ul').html(dlist);
34701        } else {
34702            _conType.openEdit();
34703        }
34704    }
34705
34706    _conType.openCategoryEdit = function(id, nm) {
34707        var j = $('#inventory-type-category-edit');
34708
34709        if (!UTIL.isEmpty(id)) {
34710            j.find('.btnDelete').removeClass('hide');
34711
34712            j.find('tr').attr('type_category_id', id);
34713            j.find('#Type_Category_Name_vc').val(nm);
34714        } else {
34715            j.find('.btnDelete').addClass('hide');
34716
34717            j.find('tr').attr('type_category_id', '');
34718            j.find('#Type_Category_Name_vc').val('');
34719        }
34720
34721        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34722        j.removeClass('hide');
34723        j.find('input:first').focus();
34724    }
34725	
34726	_conType.getGiftCardCategory = function() {
34727		var jcat = $('select#Type_Category_id option[default_type_category_id = 41]');
34728		return jcat.attr('value');
34729	}
34730	_conType.getGiftCardSubCategory = function(isVoucher) {
34731		if (isVoucher) {
34732			var typeId = 116;
34733		} else {
34734			var typeId = 115;
34735		}
34736		
34737		var jtype = $('select#Inventory_Type_id option[default_type_id = ' + typeId + ']');
34738		return jtype.attr('value');
34739	}
34740	
34741    _conType.saveCategory = function() {
34742        var j = $('#inventory-type-category-edit');
34743        var id = j.find('tr').attr('type_category_id');
34744        var nm = j.find('#Type_Category_Name_vc').val();
34745
34746        if (UTIL.isEmpty(nm)) {
34747            GLO.Popup.Warning(SA.Resource.PleaseEnterCategoryName, function() { $('#inventory-type-category-edit #Type_Category_Name_vc').focus(); });
34748            return;
34749        }
34750
34751        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34752        _saveCategory(j, nm, id, 'type-category-list');
34753    }
34754	
34755	function _saveCategory(jContainer, categoryName, categoryId, gotoHash) {
34756        var uri = GLO.Link.Page.Provider.Home + 'Inventory/TypeCategory';
34757        
34758        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": categoryId, "name": categoryName } })
34759            .success(function(data, textStatus, jqXHR) {
34760                if (UTIL.Validate.hasPermissionError(data)) { return; }
34761                
34762                new GLO.Popup.Success(SA.Resource.CategorySaved);
34763                jContainer.find('.btnSave a').css({ "border": "3px solid transparent" });
34764
34765                if (UTIL.isEmpty(categoryId)) {
34766                    categoryId = $(data).attr('type_category_id');
34767                    $('select#Type_Category_id').find('option:first').after('<option value="' + categoryId + '">' + categoryName + '</option>');
34768                    $('select#Filter_Category').find('option:first').after('<option class="c-option" value="c' + categoryId + '">' + categoryName + '</option>');
34769                } else {
34770                    $('select#Type_Category_id option[value="' + categoryId + '"]').text(categoryName);
34771                    $('select#Filter_Category').find('option[value="c' + categoryId + '"]').text(categoryName);
34772
34773                    var jtds = $('#inventory-table').find('.item-type-category[type_category_id="' + categoryId + '"]');
34774
34775                    for (var i=0; i < jtds.length; i++) {
34776                        jtds.eq(i).text(categoryName).attr('title', '');
34777                    }
34778                }
34779                
34780                GLO.Inventory.updateHash(gotoHash);
34781            })
34782            .error(function(jqXHR, textStatus, errorThrown) {
34783                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34784                GLO.UI.Form.resetProcessing();
34785            });
34786    }
34787	
34788    _conType.removeCategory = function() {
34789        var j = $('#inventory-type-category-edit tr');
34790        var id = j.attr('type_category_id');
34791        var nm = $('#Type_Category_Name_vc').val();
34792        
34793        new GLO.Popup.Confirm(SA.Resource.ConfirmDeleteCategory + ' <b style="color: #4F81BD">' + nm + '</b>', function(){
34794            GLO.Inventory.Type.removeCategoryConfirmed(id);
34795        });
34796    }
34797
34798    _conType.removeCategoryConfirmed = function(id) {
34799        var uri = GLO.Link.Page.Provider.Home + 'Inventory/TypeCategoryDelete';
34800        GLO.UI.Form.beginProcessing( $('#inventory-type-category-edit .btnDelete') );
34801
34802        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
34803            .success(function(data, textStatus, jqXHR) {
34804                if (UTIL.Validate.hasPermissionError(data)) { return; }
34805                
34806                var jdata = $(data);
34807
34808                if (jdata.attr('error_cd')) {
34809                    new GLO.Popup.Warning(jdata.outerHTML());
34810                } else {
34811                    new GLO.Popup.Success(SA.Resource.CategoryDeleted);
34812                    $('select#Type_Category_id option[value="' + id + '"]').remove();
34813                    $('select#Filter_Category').find('option[value="c' + id + '"]').remove();
34814
34815                    GLO.Inventory.updateHash('type-category-list');
34816                }
34817            })
34818            .error(function(jqXHR, textStatus, errorThrown) {
34819                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
34820                GLO.UI.Form.resetProcessing();
34821            });
34822    }
34823
34824    _conType.save = function() {
34825        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Type';
34826        var j = $('#inventory-type-edit');
34827        
34828        var tid = j.find('tr').attr('inventory_type_id');
34829        var tnm = j.find('#Type_Name_vc').val();
34830
34831        var tcid = j.find('#Type_Category_id').val();
34832        var tcnm = j.find('#New_Type_Category_Name_vc').val();
34833
34834        if (UTIL.isEmpty(tnm)) {
34835            GLO.Popup.Warning(SA.Resource.PleaseEnterTypeName, function() { $('#inventory-type-edit #Type_Name_vc').focus(); });
34836            return;
34837        } else if (UTIL.isEmpty(tcid) && UTIL.isEmpty(tcnm)) {
34838            tcnm = tnm;
34839            var label = tcnm + " - " + tnm;
34840        } else if (UTIL.isEmpty(tcnm)) {
34841            var label = j.find('#Type_Category_id option:selected').text() + " - " + tnm;
34842        } else {
34843            var label = tcnm + " - " + tnm;
34844        }
34845        
34846        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34847
34848        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "tid": tid, "tname": tnm, "tcid": tcid, "tcname": tcnm } })
34849            .success(function(data, textStatus, jqXHR) {
34850                if (UTIL.Validate.hasPermissionError(data)) { return; }
34851                
34852                new GLO.Popup.Success(SA.Resource.TypeSaved);
34853                j.find('.btnSave a').css({ "border": "3px solid transparent" });
34854
34855                var jdata = $(data);
34856
34857                if (!UTIL.isEmpty(tid)) {
34858                    document.location = GLO.Link.Page.Provider.Home + 'inventory#action=type-list';
34859                    new GLO.Popup.Processing('Loading Update...');
34860                    location.reload();
34861                    return;
34862                } else {
34863                    var newOption = '<option value="' + jdata.attr('inventory_type_id') + '" type_category_id="' + jdata.attr('type_category_id') + '">' + label + '</option>';
34864                    $('select#Inventory_Type_id').find('option:first').after(newOption);
34865                    
34866                    var filterOption = '<option class="t-option" value="t' + jdata.attr('inventory_type_id') + '">' + GLO.Inventory.filterIndent + label + '</option>';
34867                    $('select#Filter_Category').find('option:first').after(filterOption);
34868                }
34869
34870                if (UTIL.isEmpty(tcid) && !UTIL.isEmpty(tcnm)) {
34871                    var newOption = '<option value="' + jdata.attr('type_category_id') + '">' + tcnm + '</option>';
34872                    $('select#Type_Category_id').find('option:first').after(newOption);
34873                    
34874                    var filterOption = '<option class="c-option" value="c' + jdata.attr('type_category_id') + '">' + tcnm + '</option>';
34875                    $('select#Filter_Category').find('option:first').after(filterOption);
34876                }
34877
34878                GLO.Inventory.updateHash('type-list');
34879            })
34880            .error(function(jqXHR, textStatus, errorThrown) {
34881                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
34882                GLO.UI.Form.resetProcessing();
34883            });
34884    }
34885
34886    _conType.remove = function() {
34887        var id = $('#inventory-type-edit tr').attr('inventory_type_id');
34888        var nm = $('#inventory-type-edit #Type_Name_vc').val();
34889        
34890        new GLO.Popup.Confirm(SA.Resource.DeleteTypeConfirm + ' <b style="color: #4F81BD">' + nm + '</b>', function(){
34891            GLO.Inventory.Type.removeConfirmed(id);
34892        });
34893    }
34894
34895    _conType.removeConfirmed = function(id) {
34896        var uri = GLO.Link.Page.Provider.Home + 'Inventory/TypeDelete';
34897        GLO.UI.Form.beginProcessing($('#inventory-type-edit .btnDelete'));
34898
34899        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
34900            .success(function(data, textStatus, jqXHR) {
34901                if (UTIL.Validate.hasPermissionError(data)) { return; }
34902                
34903                var jdata = $(data);
34904
34905                if (jdata.attr('error_cd')) {
34906                    new GLO.Popup.Warning(jdata);
34907                } else {
34908                    new GLO.Popup.Success(SA.Resource.TypeRemoved);
34909                    
34910                    $('select#Inventory_Type_id option[value="' + id + '"]').remove();
34911                    $('select#Filter_Category option[value="t' + id + '"]').remove();
34912
34913                    GLO.Inventory.updateHash('type-list');
34914                }
34915            })
34916            .error(function(jqXHR, textStatus, errorThrown) {
34917                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
34918                GLO.UI.Form.resetProcessing();
34919            });
34920    }
34921
34922    return _conType;
34923})();
34924
34925
34926GLO.Inventory.Unit = (function() {
34927    function _conUnit() {}
34928
34929    _conUnit.openList = function() {
34930        var ju = $('select#Unit_id option');
34931
34932        if (ju.length > 0) {
34933            var ulist = '';
34934            
34935            for (var i=1; i < ju.length; i++) {
34936                ulist += '<li unit_id="' + ju.eq(i).attr('value') + '" title="' + ju.eq(i).attr('title') + '">' + ju.eq(i).text() + '</li>';
34937            }
34938
34939            $('#inventory-unit-list').removeClass('hide').find('ul').html(ulist);
34940        } else {
34941            _conUnit.openEdit();
34942        }
34943    }
34944
34945    _conUnit.openEdit = function(id, nm, ab) {
34946        var j = $('#inventory-unit-edit');
34947
34948        if (!UTIL.isEmpty(id)) {
34949            j.find('.btnDelete').removeClass('hide');
34950
34951            j.find('tr').attr('unit_id', id);
34952            j.find('#Unit_Name_vc').val(nm);
34953            j.find('#Unit_Abbreviation_vc').val(ab);
34954        } else {
34955            j.find('tr').attr('unit_id', '');
34956
34957            j.find('.btnDelete').addClass('hide');
34958            j.find('#Unit_Name_vc').val('');
34959            j.find('#Unit_Abbreviation_vc').val('');
34960        }
34961
34962        //$('#inventory-unit-list, #inventory-item-form:visible').addClass('hide');
34963        j.find('.btnSave a').css({ "border": "3px solid transparent" });
34964        j.removeClass('hide');
34965        j.find('input:first').focus();
34966    }
34967
34968    _conUnit.save = function() {
34969        var uri = GLO.Link.Page.Provider.Home + 'Inventory/Unit';
34970        var j = $('#inventory-unit-edit');
34971        
34972        var id = j.find('tr').attr('unit_id');
34973        var nm = j.find('#Unit_Name_vc').val();
34974        var ab = j.find('#Unit_Abbreviation_vc').val();
34975
34976        if (UTIL.isEmpty(nm)) {
34977            GLO.Popup.Warning(SA.Resource.PleaseEnterUnitName, function() { $('#inventory-unit-edit #Unit_Name_vc').focus(); });
34978            return;
34979        }
34980        
34981        GLO.UI.Form.beginProcessing(j.find('.btnSave'));
34982
34983        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id, "name": nm, "abbreviation": ab } })
34984            .success(function(data, textStatus, jqXHR) {
34985                if (UTIL.Validate.hasPermissionError(data)) { return; }
34986                
34987                new GLO.Popup.Success(SA.Resource.UnitSizeSaved);
34988                j.find('.btnSave a').css({ "border": "3px solid transparent" });
34989                
34990                if (UTIL.isEmpty(id)) {
34991                    var newOption = '<option value="' + $(data).attr('unit_id') + '" title="' + ab + '">' + nm + '</option>';
34992                    $('select#Unit_id').find('option:first').after(newOption);
34993                } else {
34994                    $('select#Unit_id option[value="' + id + '"]').text(nm).attr('title', ab);
34995
34996                    location.reload();
34997                }
34998
34999                GLO.Inventory.updateHash('unit-list');
35000            })
35001            .error(function(jqXHR, textStatus, errorThrown) {
35002                new GLO.Popup.Error('Unable to save at this time.  Please try again later.');
35003                GLO.UI.Form.resetProcessing();
35004            });
35005    }
35006    
35007    _conUnit.remove = function() {
35008        var uri = GLO.Link.Page.Provider.Home + 'Inventory/UnitDelete';
35009        var id = $('#inventory-unit-edit tr').attr('unit_id');
35010        GLO.UI.Form.beginProcessing( $('#inventory-unit-edit .btnDelete') );
35011
35012        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
35013            .success(function(data, textStatus, jqXHR) {
35014                if (UTIL.Validate.hasPermissionError(data)) { return; }
35015                
35016                var jdata = $(data);
35017
35018                if (jdata.attr('error_cd')) {
35019                    new GLO.Popup.Warning(jdata);
35020                } else {
35021                    new GLO.Popup.Success(SA.Resource.UnitSizeDeleted);
35022                    $('select#Unit_id option[value="' + id + '"]').remove();
35023
35024                    GLO.Inventory.updateHash('unit-list');
35025                }
35026            })
35027            .error(function(jqXHR, textStatus, errorThrown) {
35028                new GLO.Popup.Error('Unable to delete at this time.  Please try again later.');
35029                GLO.UI.Form.resetProcessing();
35030            });
35031    }
35032
35033    _conUnit.back = function() {
35034        GLO.Inventory.Item.unHide();
35035    }
35036
35037    return _conUnit;
35038})();
35039
35040
35041GLO.Inventory.Invoice = (function() {
35042    function _conInventoryInvoice() {}
35043	
35044    _conInventoryInvoice.createUsageInvoice = function() {
35045        _closeHelp();
35046        
35047        var htm = '<p>Usage Invoice Tickets allow you to mark Internal Use products <small style="letter-spacing: 0;">(products not allowed for retail sale)</small> as used</>';
35048        var jprocessing = GLO.Popup.Processing.open(htm, 'Creating Usage Invoice Ticket');
35049        
35050        setTimeout(function() {
35051	        var jPayInfo = $('<h2 event_cd="800"/>');
35052	        UserPortal.Price.open(false, true, jPayInfo);
35053	        
35054	        jprocessing.close();
35055	        setTimeout(UserPortal.Price.addProductRow, 400);
35056	    }, 100);
35057    }
35058	
35059    _conInventoryInvoice.recentUsageInvoices = function(count) {
35060        _closeHelp();
35061        
35062        var btn = '<div id="recent-usage-invoice-button"><span class="btnAdd btnCreateUsageInvoice"><a onclick="GLO.Inventory.Invoice.createUsageInvoice()">Create Product Usage Invoice</a></span></div>';
35063        
35064        SA.Menu.recentSales(10, 800, btn);
35065    }
35066    
35067    _conInventoryInvoice.createInternalProduct = function() {
35068        _closeHelp();
35069        GLO.Inventory.gotoHash('new-product&internal-use=1');
35070    }
35071	
35072	function _closeHelp() {
35073		var jpop = $('#pop-inventory-invoice-usage-help').closest('.glopop');
35074        
35075        if (jpop.length) {
35076        	GLO.Popup.close(jpop);
35077        }
35078	}
35079	
35080    _conInventoryInvoice.openHelp = function() {
35081        var msg1 = 'Do you buy products that you and your staff use, but are not sold to clients?';
35082        var msg2 = 'Keep track of these products\' cost and count by:';
35083        var msgcss = 'line-height: 1.4;';
35084        var msg = '<p style="' + msgcss + '">' + msg1 + '</p> <p style="' + msgcss + 'text-align: left;">' + msg2 + '</p>';
35085        
35086        var l1 = '<a onclick="GLO.Inventory.Invoice.createInternalProduct()">Create Products</a> <b>for Internal Use</b>';
35087        var l2 = '<a onclick="GLO.Inventory.updateHash(\'order-create\')">Create Order</a> for these products and include the cost';
35088        var l3 = 'As these products are used <a onclick="GLO.Inventory.Invoice.createUsageInvoice()">Create Product Usage Invoice</a> so you can record the used product cost and count';
35089        
35090        var l3a = 'You might want to create a generic client like "Internal Usage" for these invoices';
35091        l3 += '<ul> <li>' + l3a + '</li></ul>';
35092        
35093        var ol = '<ol class="reset-list"> <li>' + l1 + '</li> <li>' + l2 + '</li> <li>' + l3 + '</li> </ol>';
35094        var htm = '<div id="pop-inventory-invoice-usage-help">' + msg + ol + '</div>';
35095        
35096        GLO.Popup.Info.open(htm, 'Product Usage Invoice');
35097    }
35098	
35099    return _conInventoryInvoice;
35100})();
35101
35102
35103GLO.Inventory.Reports = (function() {
35104    function _conInventoryRpt() {}
35105
35106    _conInventoryRpt.currentTab = 1;
35107    _conInventoryRpt.MAX_TAB = 4;
35108    
35109    _conInventoryRpt.init = function() {
35110    	var tab = GLO.Report.Template.init();
35111        var jsonShipmentLookup = _lookupShipmentFromUrl();
35112        
35113        _initReturns();
35114        _initProductHistory();
35115        
35116        _conInventoryRpt.goToTab(tab, true);
35117        
35118        //$('#report-sales-trends').find('#rpt-filter-pay-method').remove();
35119        $('#report-shipment-history').find('#rpt-filter-pay-method').remove();
35120        
35121        _initAuditHistory();
35122        _initOrderHistory();
35123        
35124        if (UTIL.isEmpty(GLO.Uri.query('sfilter'))) {
35125        	jdd = $('#header-navigation-links #staff-filter').addClass('hide');
35126        	
35127        	GLO.Info.init();
35128        	var msg = '<span style="padding-right: 10px; color: Black;">' + SA.Resource.Hi + ' ' + UserPortal.lookupStaffName(GLO.Info.StaffId) + '</span>';
35129        	jdd.after(msg);
35130        }
35131        
35132        $(window).hashchange(function() { GLO.Inventory.Reports.hashOnChange(); });
35133        $('#header-navigation-links').find('#hd-report-order-history > a, #hd-report-audit-history > a, #hd-report-product-history > a, #hd-report-return-history > a').addClass('ignore-animate');
35134        
35135        _initInventoryReportUri(jsonShipmentLookup);
35136        GLO.Report.enableFullPageCheck();
35137    }
35138    function _initInventoryReportUri(jsonShipmentLookup) {
35139    	if (!_conInventoryRpt.findShipmentInReportSummary(jsonShipmentLookup.shipment)) {
35140    		if (jsonShipmentLookup.hasPendingSearch) {
35141	    		var jhead = $('#report-main').find('.report-search-header-table:visible');
35142	    		var isProductHistory = $('#bd #report-product-history:visible').length;
35143	    		var isReturnHistory = $('#bd #report-returns-exchanges:visible').length;
35144	    		
35145	    		/* not necessary, this is now set on server
35146	    		if (UTIL.isDate(jsonShipmentLookup.begin)) {
35147	    			jhead.find('.Report_Begin_dt').val(new Date(jsonShipmentLookup.begin).toGloDate());
35148	    		}
35149	    		
35150	    		if (UTIL.isDate(jsonShipmentLookup.end)) {
35151	    			jhead.find('.Report_End_dt').val(new Date(jsonShipmentLookup.end).toGloDate());
35152	    		}
35153	    		*/
35154	    		
35155	    		if (!UTIL.isEmpty(jsonShipmentLookup.inventoryFilter)) {
35156		    		jhead.find('.Inventory_Filter').val(jsonShipmentLookup.inventoryFilter).change();
35157		    		
35158		    		if (isProductHistory) {
35159		    			return;
35160		    		}
35161		    	}
35162		    	
35163		    	if (isReturnHistory) {
35164	    			jhead.find('.btnSearch > a').click();
35165	    		}
35166    		}
35167    	}
35168    }
35169    
35170    function _lookupShipmentFromUrl(hasPendingSearch) {
35171    	var shipment = UTIL.coalesceString(GLO.Uri.hash('shipment'), GLO.Uri.hash('shipmentId'));
35172    	var order = UTIL.coalesceString(GLO.Uri.hash('order'), GLO.Uri.hash('orderId'));
35173    	var audit = UTIL.coalesceString(GLO.Uri.hash('audit'), GLO.Uri.hash('auditId'));
35174    	
35175    	var inventoryFilter = $.trim(GLO.Uri.hash('id'));
35176    	//not neccessary, now set on server			var begin = GLO.Uri.url('begin'), end = GLO.Uri.url('end');
35177    	
35178    	var hasPendingSearch = !UTIL.isEmpty(inventoryFilter);
35179    	var json = { "hasPendingSearch": hasPendingSearch, "searchHeader": "Report", "inventoryFilter": inventoryFilter }; //only auto-run search from client on product-history or return-history report
35180    	
35181    	if (!UTIL.isEmpty(shipment)) {
35182    		json.shipment = shipment;
35183    	} else if (!UTIL.isEmpty(order)) {
35184    		json.shipment = order;
35185    		json.isOrder = true;
35186    		json.searchHeader = "Order";
35187    	} else if (!UTIL.isEmpty(audit)) {
35188    		json.shipment = audit;
35189    		json.isAudit = true;
35190    		json.searchHeader = "Audit";
35191    	}
35192    	
35193    	return json;
35194    }
35195    
35196    _conInventoryRpt.findShipmentInReportSummary = function(shipment) {
35197    	if (UTIL.isEmpty(shipment)) { return; }
35198    	
35199    	var jrpt = $('#bd #report-main .inventory-report:visible .tablesorter');
35200    	var tr = jrpt.find('tr[shipment_id="' + shipment + '"]');
35201    	
35202    	if (tr.length) {
35203    		tr.click();
35204    		return true;
35205    	} else {
35206    		tr = jrpt.find('tr[shipment_nr="' + shipment + '"]');
35207    		
35208    		if (tr.length) {
35209	    		tr.click();
35210	    		return true;
35211	    	}
35212	    }
35213	    
35214	    return false;
35215    }
35216    function _initAuditHistory() {
35217    	var style = 'display: block; margin-right: 40px; padding: 6px;';
35218    	var title = SA.Resource.InventoryAuditHelp;
35219    	var auditButton = '<span id="inventory-audit-button" class="btnAdd btnAction2" style="' + style + '" title="' + title + '">'
35220					    	+ '<a href="/inventory#action=audit" style="white-space: nowrap;">' + SA.Resource.NewCheck + '</a>'
35221					    + '</span>';
35222    	
35223    	var jaudit = $('#report-audit-history');
35224        var jhead = jaudit.find('.report-search-header');
35225        
35226        jaudit.find('#rpt-filter-pay-method').remove();
35227        
35228        //jhead.find('table').css({ "": "" });
35229        jhead.find('table td:first').append(auditButton);
35230    }
35231    
35232    function _initOrderHistory() {
35233    	var style = 'display: block; margin-right: 40px; padding: 6px;';
35234    	var newOrderButton = '<span id="inventory-create-order-button" class="btnAdd btnAction2" style="' + style + '">'
35235					    	+ '<a href="/inventory#action=order-create" style="white-space: nowrap;">' + SA.Resource.New + ' ' + SA.Resource.Order + '</a>'
35236					    + '</span>';
35237    	
35238    	$('#report-shipment-history').find('.report-search-header').find('table td:first').append(newOrderButton);
35239    }
35240    
35241    _conInventoryRpt.hashOnChange = function() {
35242        var tab = GLO.Uri.hash('tab');
35243        var id = GLO.Uri.hash('id');
35244        
35245        if (tab === 'product-history') {
35246        	if (!UTIL.isEmpty(id) && !UTIL.isEmpty(_conInventoryRpt.currentTab) && id != _conInventoryRpt.currentTab) {
35247        		_conInventoryRpt.goToTab(tab, false);
35248        	}
35249        } else {
35250        	_conInventoryRpt.goToTab(tab, false);
35251        }
35252    }
35253    
35254    _conInventoryRpt.loadReturnReport = function(jrpt) {
35255    	GLO.Report.CellSummary.initReport(jrpt, true, true);
35256    	GLO.Report.initIcons(jrpt);
35257    }
35258    
35259    function _initReturns() {
35260    	var jrptReturnExchange = $('#report-returns-exchanges');
35261        jrptReturnExchange.find('#rpt-filter-pay-method').remove();
35262        jrptReturnExchange.find('.service-filter-container').remove();
35263        
35264        jrptReturnExchange.find('.inventory-filter-container').find('option[value="-1"]').remove();
35265        
35266        jrptReturnExchange.find('.inventory-filter-container').css({ "margin-left": "-50px", "margin-right": "150px" });
35267        jrptReturnExchange.find('.btnSearch').css({ "margin-left": "100px" });
35268        
35269        GLO.Inventory.Reports.loadReturnReport(jrptReturnExchange);
35270        
35271        var ifilter = GLO.Uri.query('inventoryfilter');
35272        
35273        if (!UTIL.isEmpty(ifilter)) {
35274        	$('#report-returns-exchanges .report-search-header .Inventory_Filter').val(ifilter);
35275        }
35276    }
35277    
35278    function _initProductHistory() {
35279    	var jrpt = $('#report-product-history');
35280        jrpt.find('#rpt-filter-pay-method').remove();
35281        jrpt.find('.service-filter-container').remove();
35282        
35283        jrpt.find('.btnSearch').click(GLO.Inventory.Reports.productSearchUpdateUrlHash);
35284        var tmp = jrpt.find('#product-history-inventory-dd');
35285        
35286        var dd = jrpt.find('.Inventory_Filter');
35287        //var len = tmp.find('option').length;
35288        
35289        dd = dd.html(tmp.html());
35290        dd.change(function() { $('#report-product-history').find('.report-inventory-header-search:visible').click(); });
35291        tmp.html('');
35292        
35293        _addProductAutocomplete(jrpt, dd);
35294        
35295        dd.addClass('required');
35296	    dd.css({ "width": "300px" });
35297	    
35298	    if (innerWidth < 600) {
35299	    	$('#report-tab-product-history span').html('<b>1</b>' + SA.Resource.History);
35300	    	$('#report-tab-audit-history span').html('<b>3</b>' + SA.Resource.Audit);
35301	    	$('#report-tab-returns-exchanges span').html('<b>4</b>' + SA.Resource.Returns);
35302	    }
35303    }
35304    
35305    function _addProductAutocomplete(jrpt, dd) {
35306    	dd.before('<input type="text" id="product-history-autocomplete" placeholder="' + SA.Resource.ProductName + '" style="width: 140px;"/>');
35307    	
35308    	jrpt.find('#product-history-autocomplete').autocomplete({
35309            source: GLO.Link.Object.Provider.Ajax + 'ProductSearch?retailonly=0',
35310            minLength: 2,
35311            select: function(event, ui) {
35312                //var productName = ui.item.value;
35313                var jrpt = $('#report-product-history');
35314                
35315                jrpt.find('.Inventory_Filter').val(ui.item.id);
35316                jrpt.find('#product-history-autocomplete').val('');
35317                jrpt.find('.report-inventory-header-search:visible').click();
35318                
35319                window.setTimeout(function() {
35320                	$('#product-history-autocomplete').val('');
35321                }, 200);
35322                
35323                GLO.Report.CellSummary.initReport(jrpt, true, true);
35324            }
35325        });
35326    }
35327    
35328    _conInventoryRpt.productSearchUpdateUrlHash = function() {
35329    	var id = $('#report-product-history').find('.Inventory_Filter').val();
35330    	document.location.hash = 'tab=product-history&id=' + UTIL.cleanString(id);
35331    }
35332    
35333    function _getTab(tab, id) {
35334    	GLO.Info.init();
35335    	
35336    	if (GLO.Info.providerPackage == 4) {
35337    		if (tab === 'product-history' || tab == '1') {
35338                GLO.Info.isRequireGold(false, 'Product Detail History report');
35339            } else if (tab === 'order-and-restock' || tab == '2') {
35340                GLO.Info.isRequireGold(false, 'Product Order report');
35341            } else if (tab === 'audit-history' || tab == '3') {
35342                GLO.Info.isRequireGold(false, 'Audit History report');
35343            }
35344    		
35345    		tab = 4;
35346    	} else if (!UTIL.isEmpty(tab)) {
35347            tab = String(tab).toLowerCase();
35348            
35349            if (tab === 'product-history' || tab == '1') {
35350                tab = 1;
35351            } else if (tab === 'order-and-restock' || tab == '2') {
35352                tab = 2;
35353            } else if (tab === 'audit-history' || tab == '3') {
35354                tab = 3;
35355            } else if (tab === 'returns-exchanges' || tab == '4') {
35356                tab = 4;
35357            }
35358        } else {
35359            tab = _conInventoryRpt.currentTab;
35360        }
35361        
35362        return tab;
35363    }
35364    
35365    _conInventoryRpt.goToTab = function(tab, isInit) {
35366        var id = GLO.Uri.hash('id');
35367        tab = _getTab(tab, id)
35368        
35369        if (tab == _conInventoryRpt.currentTab && !isInit && tab != 4) {
35370        	return;			//avoids infinite recursion;
35371        } else if (tab != _conInventoryRpt.currentTab && !isInit) {
35372        	id = '';
35373        }
35374        
35375        if (tab > _conInventoryRpt.MAX_TAB) {
35376            tab = _conInventoryRpt.MAX_TAB;
35377        } else if (tab < 1) {
35378            tab = 1;
35379        }
35380        
35381        $('#report-returns-exchanges').addClass('hide');
35382        $('#report-shipment-history').addClass('hide');
35383        $('#report-audit-history').addClass('hide');
35384        $('#report-product-history').addClass('hide');
35385        
35386        if (tab === 1) {
35387            var currentReport = $('#report-product-history').removeClass('hide');
35388        } else if (tab === 2) {
35389            var currentReport = $('#report-shipment-history').removeClass('hide');
35390        } else if (tab === 3) {
35391            var currentReport = $('#report-audit-history').removeClass('hide');
35392        } else if (tab === 4) {
35393            var currentReport = $('#report-returns-exchanges').removeClass('hide');
35394        }
35395        
35396        var backColor = $('.shadow-content0').css('backgroundColor');
35397        var jhead = $('#report-portal-header');
35398        var oj = jhead.find('table tr td span b');
35399        
35400        oj.each(function() {
35401            $(this).parent().parent().removeClass('report-tab').css('backgroundColor', 'transparent');
35402        });
35403        
35404        //oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent();			//didn't work if not all tabs were displayed.
35405        oj = jhead.find('table td[tab="' + tab + '"]');
35406        
35407        oj.addClass('report-tab');
35408        oj.css('backgroundColor', backColor);
35409        
35410        _conInventoryRpt.currentTab = tab;
35411        var hashTab = '';
35412
35413        if (tab == '1') {
35414            hashTab = 'product-history';
35415            
35416            if (isInit) {
35417            	var start = UTIL.coalesce(GLO.Uri.hash('start'), GLO.Uri.query('start'));
35418            	var end = UTIL.coalesce(GLO.Uri.hash('end'), GLO.Uri.query('end'));
35419            	
35420            	if (UTIL.isDate(start)) {
35421            		currentReport.find('.Report_Begin_dt').val( new Date(start).toGloDate() );
35422            	}
35423            	
35424            	if (UTIL.isDate(end)) {
35425            		currentReport.find('.Report_End_dt').val( new Date(end).toGloDate() );
35426            	}
35427            	
35428            	if (!UTIL.isEmpty(id)) {
35429            		$('.Inventory_Filter').val(id).change();
35430            	}
35431            }
35432        } else if (tab == '2') {
35433            hashTab = 'order-and-restock';
35434        } else if (tab == '3') {
35435            hashTab = 'audit-history';
35436        } else if (tab == '4') {
35437            hashTab = 'returns-exchanges';
35438            
35439            if (!UTIL.isEmpty(id)) {
35440            	var jrpt = $('#report-product-history');
35441            	jrpt.find('.Inventory_Filter').val(id);
35442	        	jrpt.find('.report-inventory-header-search:visible').click();
35443	        }
35444        }
35445        
35446        _setHashUrl(hashTab, id);
35447    }
35448    
35449    function _setHashUrl(hashTab, id) {
35450    	var hash = 'tab=' + hashTab;
35451        begin = GLO.Uri.hash('begin'), end = GLO.Uri.hash('end');
35452        
35453        if (!UTIL.isEmpty(id)) {
35454        	hash += '&id=' + id;
35455        }
35456        
35457        if (UTIL.isDate(begin)) {
35458        	hash += '&begin=' + begin;
35459        }
35460        
35461        if (UTIL.isDate(end)) {
35462        	hash += '&begin=' + end;
35463        }
35464        
35465        document.location.hash = hash;
35466    }
35467    
35468    _conInventoryRpt.backFromShipmentDetail = function(isAudit) {
35469        if (isAudit) {
35470        	var jrpt = $('#report-audit-history');
35471        } else {
35472        	var jrpt = $('#report-shipment-history');
35473        }
35474        
35475        jrpt.find('.inventory-report-container').remove();
35476
35477        var jHistory = jrpt.find('.inventory-report-container-hide').addClass('inventory-report-container').removeClass('inventory-report-container-hide');
35478    }
35479
35480    _conInventoryRpt.editShipment = function(id, editButton) {
35481        document.location = GLO.Link.WebsiteDomain + 'inventory/index?EditShipmentId=' + id;        //toDo: Need to optimize so ajax doesn't re-request order detail or just use --> "/inventory/index#action=order&id=66" ~~> "/inventory/index#action=order&id=" + id
35482        GLO.UI.Form.beginProcessing( $(editButton).parent() );
35483    }
35484    _conInventoryRpt.exportShipment = function(shipmentId) {
35485        if (UTIL.isEmpty(shipmentId)) {
35486        	shipmentId = GLO.Inventory.Restock.getShipmentId();
35487        }
35488        
35489        if (UTIL.isEmpty(shipmentId)) {
35490        	GLO.Popup.Warning.open('Please Save Order before Exporting', 'Export Order');
35491        	return;
35492        }
35493        
35494        var url = GLO.Link.WebsiteDomain + 'report/ShipmentDetail?isExportToExcel=1&id=' + shipmentId;
35495        var btnExport = $('#shipment-detail-header').find('.btnExportToExcel');
35496        GLO.UI.Form.beginProcessing(btnExport);
35497        
35498        window.setTimeout(function() { GLO.UI.Form.resetProcessing(btnExport); }, 2500);
35499    	
35500    	UI.openChildWindow(url, '', true);
35501    }
35502    _conInventoryRpt.viewShipment = function(id, thisRow, isAudit) {
35503        if (isAudit === 0 && $('h2.inventory-header:visible').length === 1) {
35504            GLO.Inventory.updateHash('order', id, 'order-list');                                  //GLO.Inventory.Order.openEdit(id);
35505            return;
35506        }
35507
35508        var url = GLO.Link.WebsiteDomain + 'report/ShipmentDetail?id=' + id;
35509        if (isAudit === 1) { url += '&isAudit=1'; }
35510        
35511        var btnSearch = $('.report-search-header:visible').find('.btnSearch');
35512        GLO.UI.Form.beginProcessing( btnSearch );
35513        
35514        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
35515            .success(function(data, textStatus, jqXHR) {
35516                GLO.UI.Form.resetProcessing();
35517                var word = 'shipment';
35518                if (isAudit === 1) { word = 'audit'; }
35519                
35520                if (!UTIL.isEmpty(data)) {
35521                	var j = $('#report-' + word + '-history');
35522                    
35523                    j.find('.inventory-report-container-hide').remove();
35524                    var jrpt = j.find('.inventory-report-container').addClass('inventory-report-container-hide').removeClass('inventory-report-container');
35525                    
35526                    jrpt.before('<div class="inventory-report-container"/>');
35527                    jrpt = $('#report-' + word + '-history').find('.inventory-report-container').html(data);
35528                    
35529                    UI.initTableSorter( $('table.tablesorter:visible') );
35530                    
35531                    if (isAudit === 1) {
35532                    	if (GLO.Info.isMobile()) {
35533                    		var strID = '';
35534                    	} else {
35535                    		var strID = '<span id="audit-number-container"> <b id="audit-number-label">Audit #</b> <span id="audit-number">' + $(thisRow).find('td.shipment-number').text() + '</span> </span>';
35536                    	}
35537                    	
35538                    	var div = '<div id="audit-detail-header">'
35539                    				+ '<span class="btnBack" onclick="GLO.Inventory.Reports.backFromShipmentDetail(1)"><a>' + SA.Resource.Back + '</a></span>'
35540                    				+ strID
35541                    				+ '<span id="audit-date-container"> <b id="audit-date-label">' + SA.Resource.AuditDate + ':</b> <span id="audit-date">' + $(thisRow).find('td.shipment-create-dt').text() + '</span> </span>'
35542                    			+ '</div>';
35543                    	
35544                    	jrpt.prepend(div);
35545                    }
35546                } else {
35547                    GLO.Popup.Info('No ' + word + ' was found.  Please try again.');
35548                }
35549            })
35550            .error(function(jqXHR, textStatus, errorThrown) {
35551                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
35552                GLO.UI.Form.resetProcessing();
35553            });
35554    }
35555    
35556    _conInventoryRpt.openReturnUsedHelp = function(element, isUsed, isUnopened) {
35557    	var msgUsed = '<p>Returned product so will not be returned to the inventory stock and the cost of the product will be subtracted from your profitability</p>';
35558    	var msgUnUsed = '<p>Returned product added product back to the inventory stock; the existing inventory count for the product increases by 1 when returned</p>';
35559    	
35560    	var msgUsed2 = 'If you are returning this product to the vendor (or distributor) for a refund then create an invoice (via "Sell Product") for the vendor/distributor where ths product is sold at cost';
35561    	var htmUsed2 = '<p style="margin-top: 12px;">' + msgUsed2 + '</p>';
35562    	var h1 = 'Returning Products Used vs Not Used';
35563    	
35564    	if (isUsed) {
35565    		h1 = 'Product Returned Opened / Used';
35566    		var msg = '<p>' + $(element).parent().attr('helptext') + '</p>' + htmUsed2;
35567    	} else if (isUnopened) {
35568    		h1 = 'Product Returned Un-Opened / Un-Used';
35569    		var msg = '<p>' + $(element).parent().attr('helptext') + '</p>';
35570    	} else {
35571    		var msg = '<div><h3 style="margin-top: 0;">Product Returned Opened/Used:</h3>' + msgUsed + htmUsed2 + '</div>';
35572    		msg += '<div><h3>Product Returned Un-Opened / Un-Used:</h3>' + msgUnUsed + '</div>';
35573    	}
35574    	
35575    	var htm = '<div id="pop-return-used-help">' + msg + '</div>';
35576        var ojInfo = new GLO.Popup.Info.open(htm, h1);
35577    }
35578    
35579    return _conInventoryRpt;
35580})();
35581
35582
35583
35584WIZ = (function() {
35585    //var jsURL = '/outGlo/wizard/index.php?page=';
35586    _constructor.numberInputType = "text";
35587    _constructor.pageContext;
35588    _constructor.isAjaxTab = false;
35589    _constructor.Update_By_Staff_By_Password_id = null;
35590    _constructor.Update_By_Role_Type_By_Password_cd = null;
35591    _constructor.Update_By_Password_interval = null;
35592
35593    _constructor.Popup = {};
35594    _constructor.Popup.urlOnSave;
35595    _constructor.Popup.onSave;
35596
35597    //_constructor.prevPage = '';
35598    //_constructor.nextPage = '';
35599    _constructor.page;
35600
35601    _constructor.isWizard;
35602
35603    _constructor.modalAdjustHeight = 0;
35604    _constructor.modalAdjustWidth = 0;
35605    _constructor.modalDefaultHeight = 360;
35606    _constructor.modalDefaultWidth = 555;
35607
35608    function _constructor(name) {
35609        var that = this;
35610        var args = Array.prototype.slice.apply(arguments);
35611    }
35612
35613    var goToPage = function(e, page) {
35614        //$('.shadow-content').slideUp('slow');
35615        //$('.shadow-content').fadeOut('normal');
35616
35617        //document.location = jsURL + page;
35618        //GLO.Uri.query('page', page);
35619    }
35620    
35621    _constructor.initWizard = function(fname, mi, lname, email, phone, username, password, language) {
35622    	var jwiz = $('#wiz1-form');
35623    	
35624    	if (!UTIL.isEmpty(fname)) { jwiz.find('#First_Name_vc').val(fname); }
35625    	if (!UTIL.isEmpty(mi)) { jwiz.find('#Middle_Initial_c').val(mi); }
35626    	if (!UTIL.isEmpty(lname)) { jwiz.find('#Last_Name_vc').val(lname); }
35627    	
35628    	if (!UTIL.isEmpty(email)) { jwiz.find('#Email_vc').val(email); }
35629    	
35630    	if (!UTIL.isEmpty(phone) && phone.length === 10) {
35631    		setTimeout(function() {
35632    			jwiz.find('#Mobile_Phone_vc').val(phone).blur();
35633    		}, 80);
35634    	}
35635    	
35636    	if (!UTIL.isEmpty(username)) {
35637    		jwiz.find('#Username_vc').val(username).change();
35638    	} else if (!UTIL.isEmpty(email)) {
35639    		jwiz.find('#Username_vc').val(email).change();
35640    	}
35641    	
35642    	if (!UTIL.isEmpty(password)) {
35643    		jwiz.find('#Password_vc').val(password);
35644    		jwiz.find('#Password2_vc').val(password);
35645    	}
35646    	
35647    	//if (!UTIL.isEmpty(language)) { jwiz.find('#Language_cd').val(language); }
35648    	//if (!UTIL.isEmpty(mprovider)) { jwiz.find('#Mobile_Provider_cd').val(mprovider); }
35649    }
35650    
35651    _constructor.addScrollBarsToSimpleModal = function() {
35652    	if (GLO.Info.isMobile()) { return; }
35653    	
35654    	var isRealign = false;
35655    	var jmodal = $('#simplemodal-container');
35656    	var jwrap = jmodal.find('.simplemodal-wrap');
35657        
35658        if (jwrap.height() > innerHeight - 20) {
35659        	var headerHeight = UTIL.coalesceInt(jmodal.find('> h1, > h2').height(), 0);
35660        	var footerHeight = UTIL.coalesceInt(jmodal.find('#wiz1-popupNext, #wiz5-popupStatus-buttons-div, #wiz5-popupButtons').height(), 0);
35661        	var maxWrapHeight = (innerHeight - 20 - headerHeight - footerHeight);
35662        	
35663        	jwrap.addClass('friendly-mini-scroll').css({ "max-height": maxWrapHeight + 'px' });
35664        	isRealign = true;
35665        }
35666        
35667    	if (jmodal.height() > innerHeight - 20) {
35668    		jmodal.css({ "max-height": (innerHeight - 20) + 'px' });
35669    		isRealign = true;
35670    	}
35671    	
35672    	if (isRealign) {
35673    		$.modal.update();
35674    	}
35675    }
35676    
35677    _constructor.clickPrev = function(e) {
35678        if (GLO.Info.isIosApp) {
35679        	var msg = '<div class="friendly-msg2">'
35680            			+ '<h1 class="friendly-msg2">Go To Previous Page</h1>'
35681            			+ '<div>Do you want to go to the previous page?</div>'
35682            		'</div>';
35683        	new GLO.Popup.Confirm(msg, WIZ.clickPrevConfirmed);
35684        } else {
35685        	_constructor.clickPrevConfirmed();
35686        }
35687    }
35688    
35689    _constructor.clickPrevConfirmed = function() {
35690    	if ( (GLO.Info.providerPackage == 1 || WIZ.isWizard) && WIZ.page === 6) { WIZ.page--; }
35691        
35692        return _constructor.goToPage(--WIZ.page, false);
35693    }
35694    
35695    _constructor.goToPageFromHeader = function(page) {
35696        //if (GLO.Info.isIosApp && page == 6) { SA.App.openLinkInBrowser(GLO.Link.WebsiteDomain + 'provider/profile/' + page, true); }
35697        
35698        if (WIZ.isWizard && page - 1 > $.cookies.get('pstatus')) {
35699            return false;
35700        } else {
35701            return _constructor.goToPage(page);
35702        }
35703    }
35704
35705    _constructor.goToPage = function(page, mustPost) {
35706        var jform = $('form').eq(0);
35707        var url = "wizard/";
35708        if (!_constructor.isWizard) { url = "provider/profile/"; }
35709        if (supports_history_api()) { url = url + "part/"; }
35710        url = GLO.Link.WebsiteDomain + url + page;
35711        
35712        if (mustPost) {
35713            var type = "POST";
35714        } else {
35715            var type = "GET";
35716        }
35717        
35718        if (supports_history_api() && false) {
35719        	GLO.UI.Form.beginProcessing(jform.find('#btnNext, .btnSave'));
35720        	
35721            var jqxhr = $.ajax({ type: type, url: url, "cache": false, data: $("form").serialize() })
35722                .success(function(data, textStatus, jqXHR) {
35723                    pushState('wiz', "yo");     //CHANGE (very low priority): this changes the URL, but I cannot get the context to change in the history (like it does with the hash change event).
35724                    $('#wizBody').html(data);
35725                    
35726                    //                    //If switch to push state will have to manually set these values for each new state:
35727                    //                        WIZ.pageContext
35728                    //                        WIZ.page
35729                    //                        WIZ.modalAdjustHeight / WIZ.modalAdjustWidth / WIZ.modalDefaultHeight / WIZ.modalDefaultWidth
35730                    //                        //how change URL: document.location.pathname.substring(document.location.pathname.length-1)
35731
35732                })
35733                .error(function(jqXHR, textStatus, errorThrown) { 
35734                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
35735                })
35736            
35737            //$.ajax({ type: type, url: url, data: null, success: WIZ.editCallback, dataType: "html" });
35738        } else {
35739            if (mustPost) {
35740             	GLO.UI.Form.beginProcessing(jform.find('#btnNext, .btnSave'));
35741                UTIL.DefaultText.deInit($("#wizBody"));
35742                
35743                setTimeout(function() {
35744	                $('form').attr('action', '');
35745	                document.forms[0].submit();
35746                }, 100);
35747            } else {
35748            	GLO.UI.Form.beginProcessing($('#btnPrev'));
35749                
35750                if (page == 0) { url = GLO.Link.WebsiteDomain + 'login'; }
35751                
35752                setTimeout(function() {
35753                	document.location = url;
35754                }, 400);
35755            }
35756        }
35757    }
35758    
35759    _constructor.UsernameIsUnique = function(jContext, isPopup) {							//WIZ
35760        var url = GLO.Link.Object.Provider.Ajax + "UsernameIsUnique";
35761        var user = jContext.find('#Username_vc').val();
35762        var sid = jContext.find('#Staff_id').val();
35763        
35764        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { 'Username_vc': user, 'Staff_id': sid} })
35765            .success(function(data, textStatus, jqXHR) {
35766                var jdata = $(data);
35767                
35768                if (!UTIL.parseBool(jdata.attr('is_unique_fl'))) {
35769                    var msg = '<div class="friendly-msg2">'
35770                    			+ '<h1 class="friendly-msg2">' + SA.Resource.UsernameAlreadyTaken2 + '</h1>'
35771                    			+ '<div>' + SA.Resource.Username + '<b style="color: #4F81BD;">' + user + '</b> ' + SA.Resource.NotUnique + '</div>'
35772                    			+ '<div style="margin-top: 12px;">' + SA.Resource.PleasePickDifferentUsername + '</div>'
35773                    		'</div>';
35774                    
35775                    GLO.Popup.Warning(msg);
35776                    GLO.UI.Form.resetProcessing();
35777                    return;
35778                }
35779
35780                if (isPopup) {
35781                    if ( $('#Password2_vc').length === 1 ) {
35782                        if (!UTIL.isValidPassword(true)) {			//if (!_passwordsMatch()) {
35783                        	GLO.UI.Form.resetProcessing();
35784                        	return;
35785                        }
35786                    }
35787
35788                    popupSave2($('#simplemodal-container'));
35789                } else {
35790                    save3();
35791                }
35792            })
35793            .error(function(jqXHR, textStatus, errorThrown) {
35794            	GLO.UI.Form.resetProcessing();
35795            });
35796    }
35797    
35798    _constructor.verifyRequireEditPassword = function(fnSave) {
35799    	var jpop = $('#pop-require-edit-password').closest('.glopop');
35800    	var saveForStaff = UTIL.cleanString(jpop.find('#Save_For_Staff_id').val());
35801    	var pass = jpop.find('#Edit_Password_vc').val();
35802    	var urlLookup = GLO.Link.Object.Provider.Ajax + "VerifyStaffPassword?password=" + pass + '&save-staff=' + saveForStaff;
35803        
35804        var jsave = jpop.find('.btnSave');
35805        GLO.UI.Form.beginProcessing(jsave);
35806        
35807        $.ajax({ type: "GET", url: urlLookup, "cache": false })
35808            .success( function(data, textStatus, jqXHR) {
35809                GLO.UI.Form.resetProcessing();
35810                var jdata = $(data);
35811                
35812                if (!UTIL.isEmpty(jdata.attr('error_cd'))) {
35813                	new GLO.Popup.Error(jdata);
35814                } else if (!UTIL.isEmpty(jdata.attr('warning_cd'))) {
35815                	new GLO.Popup.Warning(jdata);
35816                } else {
35817                	GLO.Popup.close(jpop);
35818                	_setUpdateByPassword(jdata);
35819                	fnSave();
35820                }
35821            })
35822            .error( function(jqXHR, textStatus, errorThrown) { 
35823                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
35824            });
35825    }
35826    
35827    function _setUpdateByPassword(jdata) {
35828    	clearTimeout(_constructor.Update_By_Password_interval);
35829    	
35830    	_constructor.Update_By_Staff_By_Password_id = UTIL.coalesceInt(jdata.attr('update_by_staff_id'));
35831		_constructor.Update_By_Role_Type_By_Password_cd = UTIL.coalesceInt(jdata.attr('update_by_role_type_cd'));
35832		
35833		_constructor.Update_By_Password_interval = setTimeout(function() {
35834			_constructor.Update_By_Password_interval = _constructor.Update_By_Staff_By_Password_id = _constructor.Update_By_Role_Type_By_Password_cd = null;
35835		}, 90000);
35836    }
35837    
35838    _constructor.openRequireEditPassword = function(fnSaveOnComplete, saveForStaff) {
35839    	var htm = $('<div id="pop-require-edit-password"> <h1 class="friendly-msg4">Enter Your Password or PIN Code</h1>'
35840    				+ '<div class="friendly-msg4" style="min-width: 300px; margin-top: 12px;">'
35841						+ '<label for="Edit_Password_vc">Password or PIN Code</label>'
35842						+ '<input id="Edit_Password_vc" type="password" autocomplete="new-password" style="width: 100px; letter-spacing: 1px;"/>'
35843						+ '<input id="Save_For_Staff_id" type="hidden" value="' + UTIL.cleanString(saveForStaff) + '"/>'
35844				+ '</div> </div>');
35845		
35846		var fnSave = function() { _constructor.verifyRequireEditPassword(fnSaveOnComplete); }
35847		
35848		var ojpop = new GLO.Popup.Custom(htm, fnSave);
35849    	var jpop = ojpop.getPopup().addClass('no-persist');
35850    	var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2').css({ "margin-top": "20px" });
35851    	
35852    	ojpop.saveOnEnter();
35853    }
35854    
35855    _constructor.clickNext = function(e) {
35856        if ($('.btnCreateServices:visible').length > 0) {
35857        	$('.btnCreateServices:visible:first > a').click();
35858        	return;
35859        }
35860        
35861        save2();
35862        return UTIL.cancelEvent(e);
35863    }
35864
35865    _constructor.save = function(e) {
35866        if (e) { UTIL.cancelEvent(e); }
35867        
35868        if (GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) {
35869        	_constructor.openRequireEditPassword(save2);
35870        } else {
35871        	save2();
35872        }
35873        
35874        return false;
35875    }
35876
35877    function save2() {
35878        if (_constructor.page == 1) {
35879            $('#Image_Path_vc').val($('#newUploadedFilePath').attr('src'));
35880            
35881            //if (Wiz1.displayTextAlertConfirm()) { return; }
35882            
35883            if ($('#portal').val() === 'wizard') {
35884                var sid = GLO.Info.getStaffId();
35885                var jStaffId = $('#Staff_id');
35886                if (UTIL.isEmpty(jStaffId.val()) && !UTIL.isEmpty(sid)) { jStaffId.val(sid); }           //Fixes problem, if user used back button during wizard to go back to wiz-1.
35887            }
35888        } else if (_constructor.page == 3) {
35889        	if (!WIZ.validateHours()) { return false; }
35890        }
35891        
35892        return save3();
35893    }
35894
35895    function save3() {
35896        if (!$('#btnNext').prop('disabled')) {
35897            if (_constructor.page == 1) {
35898                if (!UTIL.isValidPassword(true)) {
35899                	return false;
35900                } else if ($('#UsernameUniqueStatus').hasClass('bad')) {				// .text().toLowerCase() == SA.Resource.already_taken
35901                    var u = $('#Username_vc');
35902                    var fn = function() { $('#client-form').find('#Username_vc').focus(); };
35903	            	
35904		            var msg1 = '<p>The username <b style="white-space: nowrap; color: red;">' + u.val() + '</b> ' + SA.Resource.is_already_taken + '</p>';
35905		            var msg2 = '<p style="text-align: center;">' + SA.Resource.PleaseUseDiffUsername + '</p>';
35906		            var htm = '<div id="pop-warning-bad-username">' + msg1 + msg2 + '</div>';
35907	            	
35908	            	GLO.Popup.Warning.open(htm, 'Username Not Valid', fn);
35909                    //GLO.Popup.Warning('<p style="white-space: nowrap;">' + SA.Resource.TheUsername + ' <b style="color:red;">' + u.val() + '</b> ' + SA.Resource.is_already_taken + '.</p><p style="text-align: center;">' + SA.Resource.PleaseUseDiffUsername + '</p>');
35910                    return false;
35911                } else if (!UTIL.isValidPIN(null, true)) {
35912                	return false;
35913                }
35914                
35915                if (SA.Parent.processProfileUpdateFromMe()) {
35916                	return;
35917                }
35918            }
35919
35920            _constructor.saveProfile();
35921        }
35922    }
35923    
35924    _constructor.saveProfile = function() {
35925    	if (UTIL.Validate.run(_constructor.pageContext)) {
35926            $('#btnNext').addClass('positive-active').prop('disabled', true);
35927            _constructor.goToPage(_constructor.page, true);
35928
35929            UTIL.Validate.changeReset();
35930            $('#btnNext').removeClass('positive-active').prop('disabled', false);
35931            return true; 	//note: the WIZ.save fn can't return true because that causes a postback.
35932        }
35933    }
35934    
35935    function _passwordsMatch() {
35936        var wiz1 = $('#wiz1-password');
35937        var p1 = wiz1.find('#Password2_vc').val();
35938        var p2 = wiz1.find('#Password_vc').val();
35939        
35940        if (p1 !== p2 && !(p1 === 'yyyyyyyyyy' && p2 === 'xxxxxxxxxx')) {
35941            if (wiz1.find('#Password_vc, #Password2_vc').length === 2) {			//= hidden for independent-staff on free + basic plans.
35942	            GLO.Popup.Warning(SA.Resource.TwoPasswordsMustMatch);
35943	            wiz1.find('#Password2_vc').focus();
35944	            return false;
35945            }
35946        }
35947        
35948        return true;
35949    }
35950
35951    function pushState(title, localPath, data) {
35952        window.history.pushState(data, title, localPath);
35953        document.title = title;
35954    }
35955
35956    function supports_history_api() {
35957        return false; //CHANGE (very low priority): this changes the URL, but I cannot get the context to change in the history (like it does with the hash change event).
35958        //return !!(window.history && history.pushState);
35959    }
35960
35961    _constructor.closePopup = function() {
35962        $.modal.close();
35963    }
35964
35965    _constructor.popupSave = function(isOverride) {
35966        var jPopup = $('#simplemodal-container');
35967        var isWiz1 = jPopup.find('#wiz1-header').length;
35968        
35969        if (!isOverride && GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) {
35970        	var fnSave = function() { _constructor.popupSave(true); };
35971        	var saveForStaff = UTIL.cleanString(jPopup.find('#Staff_id').val());
35972        	
35973        	_constructor.openRequireEditPassword(fnSave, saveForStaff);
35974        	return;
35975        }
35976        
35977        //if (isWiz1 && Wiz1.displayTextAlertConfirm()) { return; }
35978        
35979        if ($('#simplemodal-container #wizNormalHours').length > 0) {
35980    		if (!WIZ.validateHours()) {
35981    			return false;
35982    		} else if (GLO.Info.roleType > 169) {
35983    			var editSID = jPopup.find('form').attr('edit_staff_id');
35984    			var manualAdjustCount = UTIL.coalesceInt($('#wizNormalHours').attr('startOrEndTimeAdjustCount'), 0);
35985    			Wiz5.askResetHourManualAdjust(editSID, manualAdjustCount);
35986    		}
35987    	}
35988        
35989        if (WIZ.page == 5) {
35990        	Wiz5.processingCellUpdate();
35991        }
35992        
35993        if (isWiz1 && !UTIL.isEmpty(jPopup.find('#Username_vc').val())) {
35994            var jsave = $('#simplemodal-container .btnSave, #wiz1-Save');
35995            GLO.UI.Form.beginProcessing(jsave);
35996            
35997            _constructor.UsernameIsUnique(jPopup, true);
35998        } else {
35999            return popupSave2(jPopup);
36000        }
36001    }
36002
36003    function popupSave2(jPopup) {
36004        if (UTIL.Validate.run('#simplemodal-container')) {
36005            UTIL.DefaultText.deInit(jPopup);
36006
36007            var jForm = jPopup.find('form');
36008            var frmAction = jForm.attr('action');
36009            var allowedPaymentType = null, staffName = null;
36010            var isAddStaff = false, editStaffId = jPopup.find('#Staff_id').val();
36011            
36012            if (jForm.attr('id') === 'wiz1-form') {
36013            	_verifyMerchantType(jForm);
36014            	staffName = jForm.find('#First_Name_vc').val() + ' ' + jForm.find('#Last_Name_vc').val();
36015            	
36016            	if (UTIL.isEmpty(jForm.find('#Staff_id').val())) {
36017            		isAddStaff = true;
36018            	}
36019            } else if (jPopup.find('#wiz5-popupPermission').length > 0 && GLO.Info.StaffId == editStaffId) {
36020            	allowedPaymentType = jPopup.find('#wiz5-popupPermission #Allowed_Payment_cd').val();
36021            }
36022            
36023            if (_constructor.Update_By_Staff_By_Password_id) {
36024            	if (frmAction.indexOf("?") === -1) { frmAction += '?'; } else { frmAction += '&'; }
36025            	
36026            	frmAction += 'Update_By_Staff_By_Password_id=' + _constructor.Update_By_Staff_By_Password_id;
36027            	frmAction += '&Update_By_Role_Type_By_Password_cd=' + _constructor.Update_By_Role_Type_By_Password_cd;
36028            }
36029            
36030            var jqxhr = $.ajax({ type: "POST", url: frmAction, "cache": false, data: jForm.serialize() })
36031	            .success(function(data, textStatus, jqXHR) {
36032	                GLO.UI.Form.resetProcessing();
36033	                
36034	                if ($(data).hasClass('warning')) {
36035			        	GLO.Popup.Warning.open(jqXHR.responseText, 'Save Not Completed');
36036			        	return;
36037			        }
36038	                
36039	                if (_saveOnStaffReport()) { return; }
36040	                
36041	                if (UTIL.isNumber(allowedPaymentType)) {
36042	                	GLO.Data.Staff.allowedPaymentType = parseInt(allowedPaymentType);
36043	                }
36044	                
36045	                if (isAddStaff) {
36046	                	_displayAddStaffMessage(data);
36047	                } else if (!_processData(data)) {
36048	                	return;
36049	                }
36050	                
36051	                if (!UTIL.isEmpty(_constructor.Popup.onSave)) {
36052	                    _constructor.Popup.onSave(data, staffName);
36053	                } else if (!UTIL.isEmpty(_constructor.Popup.urlOnSave)) {
36054	                    document.location = _constructor.Popup.urlOnSave;
36055	                }
36056	            })
36057			    .error(function(jqXHR, textStatus, errorThrown) {
36058			        GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
36059			    });
36060
36061            _constructor.closePopup();
36062        } else {
36063        	GLO.UI.Form.resetProcessing();
36064        }
36065    }
36066    
36067    function _saveOnStaffReport() {
36068    	return;
36069    	/*
36070    	if (location.pathname.toLowerCase() === '/reports/staffprofile') {
36071    		var msg = '<div><div style="margin-bottom: 24px;">Changes Saved</div><div>Refreshing Report</div></div>';
36072    		GLO.Popup.Processing.open(msg, 'Refreshing Report...');
36073    		
36074    		setTimeout(function() {
36075    			location.reload();
36076    		}, 200);
36077    	}
36078    	*/
36079    }
36080    
36081    function _displayAddStaffMessage(data) {
36082    	var sname = $(data).find('.wiz5-column-name').text();
36083    	
36084    	GLO.Popup.Success.open(sname + ' Created', 'New Staff');
36085    }
36086	
36087	function _processData(data) {
36088		if (UTIL.isEmpty(data)) { return; }
36089		
36090		var jd = $(data);
36091		var msg = '<div id="pop-success-wizard">';
36092		
36093		if (!UTIL.isEmpty(jd.attr('error_cd'))) {
36094			GLO.Popup.Error.open(jd.html(), 'Save Error');
36095			return false;
36096		} else if (!UTIL.isEmpty(jd.attr('warning_cd'))) {
36097			GLO.Popup.Warning.open(jd.html(), 'Save Warning');
36098			return false;
36099		} else if (data === 'good' || data == 1) {
36100			msg += 'Update Successful';
36101		} else {
36102			msg += UTIL.coalesceString(jd.html(), 'Update Successful');
36103		}
36104		
36105		GLO.Popup.Success.open(msg + '</div>', 'Save Successful', 12000);
36106		return true;
36107	}
36108	
36109	function _verifyMerchantType(jform) {
36110		var juse = jform.closest('#wiz5-popupStaffProfile').parent().find('#Use_House_Merchant_fl');
36111		if (juse.length === 0) { return; }
36112		
36113		var useHouse = juse.prop('checked');
36114		var jmt = jform.find('#Merchant_Type_cd');
36115		
36116		if (!useHouse && (!UTIL.isEmpty(jmt.val()) && GLO.Info.roleType > 219)) {
36117			jmt.val(99);
36118		} else if (useHouse) {
36119			jmt.val(GLO.Data.provider.merchant_type_cd);
36120		}
36121	}
36122	
36123    /* _constructor.textMe_OnClick = function(me) {
36124        MobileProviderPopup.originalValue = $('#Mobile_Provider_cd').val();
36125        
36126        if (WIZ.page == 1) {
36127            if (me.checked) {
36128                $('#mobileProvider').val($('#Mobile_Provider_cd').val());
36129                $('#other-desc').val($('#Mobile_Provider_vc').val());
36130                
36131                UTIL.DefaultText.init($('#text-me-popup'));
36132                $("#text-me-popup").modal({ onClose: MobileProviderPopup.close });
36133                
36134                if (GLO.Info.isMobile()) {
36135                	var jpop = $('#text-me-popup');
36136                	jpop.find('label[for="mobileProvider"]').css({ "margin-top": "-11px", "display": "block", "text-align": "center" });
36137                	
36138                	var jbtns = $('#mobile-provider-buttons')
36139                	jbtns.css({ "margin-bottom": "30px", "margin-top": "10px", "padding-left": "20px", "padding-right": "20px" });
36140                	jbtns.find('.btnCancel').css({ "width": "90px", "margin-left": "0" });
36141                	jbtns.find('.btnOk').css({ "float": "right", "width": "50px", "margin-left": "0" });
36142                	
36143                	$.modal.update(220, 285);
36144                } else {
36145                	$.modal.update(185, 450);
36146                }
36147                
36148                MobileProviderPopup.onChange(document.getElementById('mobileProvider'));
36149            }
36150        } else {			// if (WIZ.page == 5 || is staff profile report
36151            if (me.checked) {
36152                $('#labelTextReminders').text('');
36153                $('#mobileProviderInfo').removeClass('hide');
36154                $('#Mobile_Provider_cd').removeClass('hide').focus();
36155            } else {
36156                $('#Mobile_Provider_cd').addClass('hide');
36157                $('#mobileProviderInfo').addClass('hide');
36158                $('#labelTextReminders').text(SA.Resource.TextMeScheduleChanges);
36159            }
36160        }
36161        
36162        $('#mobileProvider-faq').parent().remove();
36163    } */
36164
36165    _constructor.toolTip_OnHover = function(tip) {
36166        if (WIZ.page == 4) {
36167            var price = this.attr('price_vc'), hourlyRate = this.attr('hourly_mn');
36168            
36169            if (UTIL.isNumber(price, true)) {
36170            	price = UTIL.displayMoney(price);
36171            } else if (UTIL.isNumber(hourlyRate, true)) {
36172            	price = UTIL.displayMoney(hourlyRate) + '/hour';
36173            }
36174            
36175            tip.find('#desc').text(this.attr('description_tx') ? this.attr('description_tx') : '');
36176            tip.find('#wiz4-tip-Price').text(price);
36177            
36178            var tm = this.attr('time_nr');
36179            
36180            if (!UTIL.isEmpty(tm)) {
36181                var p = this.attr('process_nr');
36182                var f = this.attr('finish_nr');
36183
36184                if (!UTIL.isEmpty(p) && p != '0') { tm += '+ ' + p + ' (' + SA.Resource.Processing.toLowerCase() + ')'; }
36185                if (!UTIL.isEmpty(f) && f != '0') { tm += '+ ' + f + ' (' + SA.Resource.FinishOut.toLowerCase() + ')'; }
36186            } else {
36187                tm = '';
36188            }
36189            
36190            tip.find('#wiz4-tip-Time').text(tm);
36191            return true;
36192        } else {
36193            var tmp = $(this).parent().find('span').text();
36194            if (tmp.length == '') {
36195                return false;
36196            } else {
36197                tip.find('p').text(tmp);
36198                return true;
36199            }
36200        }
36201    }
36202
36203    _constructor.genericUserPage = function(jContext) {
36204        jContext.find('#wiz1-body #labelTextReminders').text(SA.Resource.TextMeScheduleChanges);
36205        jContext.find('#wiz1-body #labelEmailReminders').text(SA.Resource.EmailAppointmentReminders);
36206        jContext.find('#wiz1-header').addClass('hide');
36207        jContext.find('#wiz1-body').css('marginTop', '15px');
36208    }
36209
36210    _constructor.openUserLogin = function(staffId, pop, isMinimal) {
36211        pop = _constructor.minimalUserLogin(pop, isMinimal);
36212        UTIL.DefaultText.init(pop);
36213        pop.modal();
36214
36215        _constructor.updateModal();
36216        $('#wiz1-body #wiz1-Save').click(function() { WIZ.popupSave(); });
36217        _constructor.genericUserPage(pop);
36218    }
36219
36220    _constructor.minimalUserLogin = function(pop, isMinimal) {
36221        var row = 0;
36222        pop = pop ? pop : '#wiz1-body';
36223        pop = $(pop);
36224
36225        if (isMinimal) {
36226            pop.find(".widegap > tbody > tr").each(function(i) {
36227                if (++row > 4) {
36228                    $(this).addClass('hide');
36229                }
36230            });
36231
36232            $('#wiz1-showMore-container').removeClass('hide').css('margin-left', '130px');
36233        } else {
36234            pop.find(".widegap > tbody > tr").each(function(i) {
36235                if (++row > 4) {
36236                    $(this).removeClass('hide');
36237                }
36238            });
36239
36240            $('#wiz1-showMore-container').addClass('hide').css('margin-left', '70px');
36241        }
36242
36243        //$('table.widegap').css('margin-left', '10px');
36244        $('#wiz1-EmailReminders').addClass('hide');
36245        $('#wiz1-popupNext').removeClass('hide');
36246        return pop;
36247    }
36248	
36249    _constructor.init = function(page, context) {					//= WIZ.init
36250        if (GLO.Info.portal === undefined) { GLO.Info.init(); }
36251
36252        if (GLO.Info.portal === 'wizard') {
36253            _constructor.isWizard = true;
36254        } else {
36255            _constructor.isWizard = false;
36256        }
36257        
36258        if (GLO.Info.isAndroid) { _constructor.numberInputType = "number"; }
36259        
36260        _constructor.page = page;
36261        _constructor.pageContext = context ? context : 'body';
36262
36263        var backColor = $('.shadow-content0').css('backgroundColor');
36264        
36265        if (!WIZ.isWizard && WIZ.page == 21) {                                  // = manage web template.
36266            var jHeader = $('#wiz-status-header');
36267            jHeader.removeClass('hide');
36268            jHeader.find('#wiz-h21').addClass('wiz-tab').css('backgroundColor', backColor);
36269            
36270            _loadSetupWebsite();
36271        } else if ((WIZ.isWizard && WIZ.page !== 0) || (!WIZ.isWizard)) {
36272            $('#wiz-status-header').removeClass('hide');
36273            
36274            /*
36275            var individual5bonus = 0;
36276            var packageType = $.cookies.get('package');
36277
36278            if (_constructor.page === 6 && packageType == 1) {
36279                individual5bonus = -1;
36280            } else if (!WIZ.isWizard && parseInt(GLO.Info.roleType) < 200) {
36281                individual5bonus = -1;
36282            }
36283            */
36284            
36285            var packageTabAdjust = 0;
36286            
36287            if (WIZ.isWizard && page == 6) { packageTabAdjust = -1; }
36288            
36289            /* 		//Jan 2016: if !WIZ.isWizard --> always display 'Staff' tab.
36290            if (!WIZ.isWizard && parseInt(GLO.Info.roleType) > 189) {
36291            	if (GLO.Info.providerPackage !== 1) {
36292            		//packageTabAdjust = -1;
36293            	} else if (GLO.Info.providerPackage === 1 && GLO.Data.provider.signup == 50 && _constructor.page > 4) {
36294            		packageTabAdjust = -1;
36295            	}
36296            }
36297            */
36298            
36299            var oj = $('#wiz-status-header table tr td span b').eq(_constructor.page - 1 + packageTabAdjust).parent().parent();
36300            oj.addClass('wiz-tab');
36301            oj.css('backgroundColor', backColor);
36302        }
36303
36304        if (WIZ.isWizard) {
36305            //if ($.cookies.get('package') != '1') { $('#wiz-h4').removeClass('hide'); }
36306
36307            if (WIZ.page !== 0) { $('#btnPrev, #wiz-arrowLeft').click(WIZ.clickPrev).removeClass('hide'); }
36308
36309            if (WIZ.page === 6) {
36310                $('#btnNext').click(WIZ.clickNext).removeClass('hide');
36311                $(context).find('input.required, select.required').removeClass('required');
36312            } else {
36313                $('#btnNext, #wiz-arrowRight').click(WIZ.clickNext).removeClass('hide');
36314            }
36315
36316            UI.setAccessKey('form.wizard', null, WIZ.clickNext);
36317
36318            var j = $('#wiz-status-header');
36319            j.find('#wiz-h1').attr('title', SA.Resource.Step + ' #1');
36320            j.find('#wiz-h2').attr('title', SA.Resource.Step + ' #2');
36321            j.find('#wiz-h3').attr('title', SA.Resource.Step + ' #3');
36322            j.find('#wiz-h4').attr('title', SA.Resource.Step + ' #4');
36323
36324            if ($.cookies.get('package') != "1") {
36325                j.find('#wiz-h5').attr('title', SA.Resource.Step + ' #5');
36326                j.find('#wiz-h6').attr('title', SA.Resource.Step + ' #6 (' + SA.Resource.LastStep.toLowerCase() + ')');
36327            } else {
36328                j.find('#wiz-h6').attr('title', SA.Resource.Step + ' #5 (' + SA.Resource.LastStep.toLowerCase() + ')');
36329            }
36330
36331            var pstatus = $.cookies.get('pstatus');
36332
36333            if (UTIL.isEmpty(pstatus)) {
36334                pstatus = 0;
36335            } else {
36336                pstatus = parseInt(pstatus);
36337            }
36338
36339            if (pstatus < 5) { j.find('#wiz-h6').addClass('not-yet'); }
36340            if (pstatus < 4) { j.find('#wiz-h5').addClass('not-yet'); }
36341            if (pstatus < 3) { j.find('#wiz-h4').addClass('not-yet'); }
36342            if (pstatus < 2) { j.find('#wiz-h3').addClass('not-yet'); }
36343            if (pstatus < 1) { j.find('#wiz-h2').addClass('not-yet'); }
36344
36345            if (WIZ.page == 2 && pstatus == 1) {
36346                $('#Create_Appt_Hr_nr').val(1);
36347                $('#Update_Appt_Hr_nr').val(24);
36348            }
36349        } else {
36350            //if ($.cookies.get('package') != '1') { $('#wiz-h4').removeClass('hide').find('span').html('<b>4</b>Alerts'); }
36351
36352            if (WIZ.page === 1 || WIZ.page === 2 || WIZ.page == 3 || WIZ.page === 6) {
36353                if (GLO.Info.roleType > 169 || !UTIL.parseBool($('#wiz1-main').find('#Hide_Client_Contact_fl').val())) {
36354                	$('#btnNext').css("margin-left", "").removeClass('hide').find('a').html(SA.Resource.Save).click(WIZ.save);
36355                }
36356                
36357                if (WIZ.page === 2 || WIZ.page === 3) {
36358                	$('#btnNext').css({ "position": "relative", "right": "inherit", "width": "60px", "margin": "auto" });
36359                }
36360                
36361                var jWizForm = $('form.wizard');
36362                jWizForm.find('input, select, textarea').change(UTIL.Validate.changeUnsaved);
36363                UI.setAccessKey('form.wizard', null, WIZ.save);
36364                window.setTimeout(function() { UTIL.Validate.saveButton = $('#btnNext').find('a'); }, 10);
36365            }
36366
36367            $('#search-bar').removeClass('hide');
36368            var tab = GLO.Uri.hash('tab');
36369            
36370            if (parseInt(GLO.Info.roleType) > 219) {
36371            	if (tab === 'website') {
36372	            	_constructor.isAjaxTab = true;
36373	            	$('#wiz-h21').click();
36374	            } else if (tab === 'security') {
36375            		_constructor.isAjaxTab = true;
36376            		$('#wiz-h22').click();
36377            	} else if (tab === 'client-config') {
36378            		$('.wiz5-column-client-config').click();
36379            		
36380            		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
36381    				var popuptab = UTIL.cleanString(GLO.Uri.url('popuptab')).toLowerCase();
36382    				
36383    				if (highlight.toLowerCase() == 'confirmation' || popuptab === 'client-messages') {
36384		    			Wiz5.initPopupUrlAction(popuptab, highlight, 1);
36385		    		}
36386            	}
36387            }
36388        }
36389        
36390        //if (GLO.Info.isMobile() && WIZ.page !== 5) { GLO.Mobile.setPageHeader(); }
36391        
36392        if (GLO.Info.isMobile(true)) {
36393        	GLO.Info.setupFastClick($('#bd')[0]);
36394        }
36395        
36396        if (page == 4 && !WIZ.isAjaxTab) {
36397            $('#wiz4-btnAddBox').click(Wiz4.Popup.Edit.newBox);
36398            
36399            if (WIZ.isWizard && $('#primary-select-container').length > 0) {
36400            	if ($('#boxContainer .shadow2').length > 0) {
36401            		_constructor.initWiz4();
36402            	} else {
36403            		$('#wiz4-top-buttons').addClass('hide');
36404	            	$('#wiz-button-top-padding').css({ "height": "40px" });
36405	            	$('.shadow0, .shadow-content0').css({ "height": "" });
36406            		
36407            		var btnCSS = 'position: absolute; right: 8px; width: 140px;';
36408            		var btnCreateSvc = '<span class="btnCreateServices btnSave" style="' + btnCSS + '"> <a onclick="WIZ.generateServiceList()">' + SA.Resource.CreateServices + '</a> </span>';
36409            		$('#btnNext').addClass('hide').after(btnCreateSvc);
36410            	}
36411            } else {
36412            	_constructor.initWiz4();
36413            }
36414        }
36415        
36416        _initPage2();
36417        _initIsCompanyDevice();
36418        _initWizUrl();
36419    }
36420    function _initIsCompanyDevice() {
36421    	if (!UTIL.isEmpty($.cookies.get('pcg'))) {
36422    		$('#wiz-status-header').addClass('is-company-device');
36423    	}
36424    }
36425    function _initPage2() {
36426    	if (_constructor.page !== 2) { return; }
36427    	
36428    	if (!_constructor.isWizard && GLO.Info.providerPackage != 1) {
36429    		$('#wiz2-main #wiz2-email').removeClass('hide');
36430    	} else if (_constructor.isWizard) {
36431    		$('#wiz2-staff-type').removeClass('hideX');
36432    	}
36433    }
36434    function _initWizUrl() {
36435    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
36436    	
36437    	if (!UTIL.isEmpty(highlight)) {
36438			var jhigh = $('#' + highlight);
36439    		
36440    		if (jhigh.length === 0) {
36441    			var jhigh = $('.' + highlight);
36442    		}
36443    		
36444    		if (jhigh.length) {
36445    			UI.highlight(jhigh, 100, 9500, true);
36446    		}
36447		}
36448    }
36449    
36450    _constructor.initServiceSetup = function() {
36451    	var nm = UTIL.cleanString($.cookies.get('pname')).toLowerCase();
36452    	var industry = null;
36453    	
36454    	if (nm.indexOf('nail') !== -1) {
36455    		industry = 'i1';
36456    	} else if (nm.indexOf('hair') !== -1) {
36457    		industry = 'i2';
36458    	} else if (nm.indexOf('barber') !== -1) {
36459    		industry = 'i6';
36460    	} else if (nm.indexOf('lash') !== -1) {
36461    		industry = 'i3';
36462    	} else if (nm.indexOf('massage') !== -1) {
36463    		industry = 'i40';
36464    	}
36465    	
36466    	if (industry) {
36467    		$('#Industry_cd').val(industry).change();
36468    	}
36469    }
36470    
36471    _constructor.initWiz4 = function() {
36472    	Wiz4.calculateHeight();
36473    	Wiz4.Popup.Edit.init();
36474        UI.init_Tooltip(".shadow-content2 ul li", WIZ.toolTip_OnHover);
36475        
36476        $(".shadow-content2").click(Wiz4.Popup.Edit.open);
36477        var gt = GLO.Uri.query('goto').toLowerCase();
36478        var hi = GLO.Uri.query('highlight').toLowerCase();
36479        var sgid = GLO.Uri.query('sgid');
36480        var edit = GLO.Uri.query('edit').toLowerCase();
36481        
36482        if (gt === 'fee' && GLO.Info.roleType > 219) {
36483        	$('#set-service-commission-fees').find('a').click();
36484        }
36485        
36486        if (hi === 'ccfee') {
36487        	$('#wiz4-set-ccfee').addClass('help-highlight').find('input').focus();
36488        }
36489        
36490        if (UTIL.isNumber(sgid)) {
36491        	$('#wiz4-main').find('#wiz4-box-' + sgid).click();
36492        	
36493        	if (edit === 'color') {
36494        		$('#services-edit-popup #color-picker-image').click();
36495        	}
36496        }
36497    }
36498    
36499    function _initSetupWebsite() {
36500    	_constructor.changeCustomDomain($('#Website_Url_vc')[0], true);
36501    	//GLO.Template.Manage.enableWebTemplate($('#ManageTemplate #Active_fl')[0]);
36502		
36503		UTIL.Validate.saveButton = '#step-3.select-web-address .btnSave a';
36504		
36505		var js = $('#step-3.select-web-address').find('input, textarea, select');
36506		js.change(UTIL.Validate.changeUnsaved);
36507		js.keyup(UTIL.Validate.changeUnsaved);
36508		
36509		/*
36510    	$('#faq-wizard-step-2>a').click(function() {
36511        	window.setTimeout(function() {
36512        		if ($('#step-2 .sl_examples').find('.sl-wrapper').length === 0) {
36513        			$('.sl_examples').find('td > a').hoverwords({ overlay: true, dir: 'rightleft' });
36514        		}
36515        	}, 100);
36516        });
36517        */
36518        
36519        _initSetupWebsiteLanguage();
36520    }
36521    
36522    function _initSetupWebsiteLanguage() {
36523    	if ($.cookies.get('language') === 'vi') {
36524    		$('faq-wizard-title').text(SA.Resource.MarketYourBusinessWithYourOwnWebsite);
36525    	}
36526    }
36527    
36528    function _initSortGallery() {
36529    	var jlist = $('#website-galleries').find('>dl');
36530    	jlist.find('dt.gallery-custom').append('<span class="gallery-drag ui-sortable-handle"></span>');
36531    	
36532    	jlist.sortable({
36533			handle: '.gallery-drag'
36534			//, cancel: 'dt,input,select'
36535			, update: function(event, ui) {
36536				var dts = $('#website-galleries').find('>dl>dt');
36537				
36538				for (var i=0; i < dts.length; i++) {
36539					dts.eq(i).attr('order_sr', i+10);
36540				}
36541				
36542				_saveOrder();
36543			}
36544		});
36545    }
36546    
36547    function _saveOrder() {
36548    	var xml = '', url = GLO.Link.Page.Provider.WebTemplate + 'GalleryOrder';
36549    	var dts = $('#website-galleries').find('dl > dt.gallery-custom');
36550    	
36551    	for (var i=0; i < dts.length; i++) {
36552    		xml += '<dt order_sr="' + (i+10) + '" gallery_id="' + dts.eq(i).attr('gallery_id') + '"/>';
36553    	}
36554    	
36555    	xml = UTIL.htmlEncode('<dl>' + xml + '</dl>');
36556    	
36557    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "order_xml": xml } })
36558            .success(function(data, textStatus, jqXHR) {
36559                
36560            })
36561            //.error(function (jqXHR, textStatus, errorThrown) { });
36562    }
36563    
36564    function _loadSetupWebsite() {
36565    	_initSetupWebsite();
36566    	_initSortGallery();
36567    	
36568    	var hash = window.location.hash;
36569        
36570        if (!UTIL.isEmpty(hash)) {
36571        	hash = hash.toLowerCase();
36572        	
36573        	if (hash.indexOf('step=2') !== -1) {
36574        		FaqWizard.clickHeader($('#faq-wizard-step-2>a')[0]);
36575        	} else if (hash.indexOf('step=3') !== -1) {
36576        		FaqWizard.clickHeader($('#faq-wizard-step-3>a')[0]);
36577        	} else if (hash.indexOf('step=4') !== -1) {
36578        		var tmp = $('#faq-wizard-step-4>a:visible');
36579        		
36580        		if (tmp.length === 1) {
36581        			FaqWizard.clickHeader(tmp[0]);
36582        		}
36583        	}
36584        }
36585        
36586        if (GLO.Data.Staff.require_password_appointment_edit_fl) {
36587    		var css = 'position: absolute; display: block; width: 100%; height: 100%; line-height: 200%; letter-spacing: 2px; text-align: center;';
36588    		css += 'font-size: 40px; font-weight: bold; color: black; background-color: #dde; z-index: 9999; opacity: .9;';
36589    		
36590    		var msg = 'To edit your website please Login as Manager, Admin, or Receptionist that does not require password on edit';
36591    		var overlay = '<div class="receptionist-required" style="' + css + '"> <div style="padding-top: 100px; padding-bottom: 20px; padding-left: 20px; padding-right: 12px;">' + msg + '</div> </div>';
36592    		$('#wizBody').prepend(overlay);
36593    	}
36594    }
36595    
36596    _constructor.updateModal = function(hgt, width) {
36597        var hgt = (hgt ? hgt : _constructor.modalDefaultHeight) + _constructor.modalAdjustHeight;
36598        var width = (width ? width : _constructor.modalDefaultWidth) + _constructor.modalAdjustWidth;
36599        
36600        if (width > innerWidth) { width = innerWidth; }
36601        
36602        $.modal.update(hgt, width);
36603    }
36604
36605    _constructor.closeModalPopup = function(popup) {
36606        UTIL.DefaultText.deInit(popup);
36607        $.modal.close();
36608    }
36609    
36610    _constructor.openManageWebsite = function(me) {
36611        if (WIZ.page == 6) {
36612        	document.location = GLO.Info.http + document.location.host + '/wizard/website#tab=website';
36613        	return;
36614        }
36615        
36616        _setupWebsite(me, 21);
36617        
36618        //var url = GLO.Link.Page.Provider.WebTemplate + 'manage?isPartial=true&dt=' + UTIL.getDateString();
36619        var url = GLO.Link.WebsiteDomain + 'wizard/website?isPartial=1&dt=' + UTIL.getDateString();
36620        
36621        var ajax_load = "<div style='width: 100px; margin: auto; margin-top: 100px;'><img class='loading' src='" + GLO.Data.cdnDirectory + "image/processing.gif' alt='loading...' /></div>";
36622        var throbber = $('.loadingDiv').clone().find('img').css({ "display": "block", "margin": "auto", "padding-top": "50px" });
36623        
36624        if ( $('#change-website-template').length === 1 ) {
36625        	_loadSetupWebsite();
36626        } else {
36627	        $('#wizBody').html(throbber).load(url, function() {
36628	            if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; }
36629	            
36630	            //if (GLO.Info.isIPad) { GLO.Mobile.updateViewPort('user-scalable=no, width=1040'); }
36631	            
36632	            //GLO.Mobile.updateViewPort('width=555, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0');
36633	            _initSetupWebsite();
36634	        });
36635        }
36636        
36637        _setWebsiteProfileUrl();
36638    }
36639    
36640    function _setupWebsite(tab, page) {
36641    	WIZ.page = page;
36642    	$('#feedback-container').addClass('hide');
36643    	$('.shadow0, .shadow-content0').css({ "height": "" });
36644    	$('#doc3.sa-responsive').css({ "max-width": "1240px" });
36645    	
36646    	var backColor = $('.shadow-content0').css('backgroundColor');
36647        var jCurrTab = $('#wiz-status-header .wiz-tab');
36648        jCurrTab.css('backgroundColor', '').removeClass('wiz-tab');
36649        
36650        if (UTIL.isEmptyObject(tab)) { tab = $('#wiz-h21'); }
36651        $(tab).addClass('wiz-tab').css('backgroundColor', backColor);
36652        
36653        $('.wiz-buttons').remove();
36654        
36655        _setWebsiteProfileUrl();
36656        setTimeout(GLO.Mobile.resizeStaffProfile, 450);
36657    }
36658    
36659    function _setWebsiteProfileUrl() {
36660    	if (GLO.Uri.hash('tab') !== 'website') {
36661        	if (window.history.pushState) {
36662        		window.history.pushState('Website Profile', 'Website Profile', '/wizard/website#tab=website');
36663        	} else {
36664        		GLO.Uri.hash('tab', 'website');
36665        	}
36666        }
36667    }
36668    
36669    function _getThrobber() {
36670    	var ajax_load = "<div style='width: 100px; margin: auto; margin-top: 100px;'><img class='loading' src='" + GLO.Data.cdnDirectory + "image/processing.gif' alt='loading...' /></div>";
36671        
36672        var mleft = ((innerWidth - 100) * .96)/2 + 'px';
36673        
36674        return $('.loadingDiv').clone().find('img').css({"margin": "100px auto", "margin-left": mleft });
36675    }
36676    
36677    _constructor.openSetupDomain = function(company) {
36678        _setupWebsite(undefined, 22);
36679        
36680        var url = GLO.Link.WebsiteDomain + 'wizard/website/' + company + '?isPartial=1&dt=' + UTIL.getDateString();
36681        var throbber = _getThrobber();
36682        
36683        if ( $('#setup-godaddy:visible').length !== 1 ) {
36684	        $('#wizBody').html(throbber).load(url, function() {
36685	            if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; }
36686	            
36687	            //GLO.Mobile.updateViewPort('width=555, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0');
36688	        });
36689        }
36690    }
36691    
36692    _constructor.changeCustomDomain = function(element, alwaysDisplay) {
36693    	if (alwaysDisplay || !UTIL.isEmpty(element.value)) {
36694    		//$('.swMain ul.anchor').width(1020);
36695    		$('#faq-wizard-step-4').removeClass('hide');
36696    	} else {
36697    		$('#faq-wizard-step-4').addClass('hide');
36698    		//$('.swMain ul.anchor').width(1020 - 255);
36699    	}
36700    }
36701    
36702    _constructor.openManageSecurity = function(me) {
36703        var backColor = $('.shadow-content0').css('backgroundColor');
36704        $('#wiz-status-header .wiz-tab').css('backgroundColor', '').removeClass('wiz-tab');
36705        $(me).addClass('wiz-tab').css('backgroundColor', backColor);
36706
36707        $('.wiz-buttons').remove();
36708
36709        var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer?isPartial=true&dt=' + UTIL.getDateString();
36710        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto", "margin-left": "350px" });
36711
36712        $('#wizBody').html(throbber).load(uri, function() {
36713            if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; }
36714            
36715            //if (GLO.Info.isIPad) { GLO.Mobile.updateViewPort('user-scalable=no, width=1040'); }
36716            
36717            UTIL.Validate.saveButton = '#security-setup-page .btnSave a';
36718            $('#security-setup-page').find('input:visible').keyup(UTIL.Validate.changeUnsaved);
36719            $('.shadow0, .shadow-content0').css({ "height": "" });
36720            
36721            if (GLO.Info.isMobile()) {
36722            	$('#doc3').css({ "width": "100%", "max-width": "720px" });
36723            	//GLO.Mobile.updateViewPort('width=555, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0');
36724            }
36725            
36726            WIZ.SetupSecurity.init();
36727        });
36728        
36729        _setSecurityProfileUrl();
36730    }
36731    
36732    function _setSecurityProfileUrl() {
36733    	if (GLO.Uri.hash('tab') !== 'security') {
36734        	if (false && window.history.pushState) {				//--> need to implement this on the server-side.
36735        		window.history.pushState('Website Profile', 'Website Profile', '/wizard/security#tab=security');
36736        	} else {
36737        		GLO.Uri.hash('tab', 'security');
36738        	}
36739        }
36740    }
36741    
36742    function _validateHoursForAndroid() {
36743    	var tr = $('#wizHoursTable').find('tr');
36744    	var open, close;
36745    	
36746    	for (var i=0; i < tr.length; i++) {
36747    		if (!tr.eq(i).find('.bizClosed').prop('checked')) {
36748    			open = tr.eq(i).find('.open-time');
36749    			close = tr.eq(i).find('.close-time');
36750    			
36751    			if (!UTIL.isEmpty(open.val()) || !UTIL.isEmpty(close.val())) {
36752	    			if (!UTIL.isValidTime(open.val())) {
36753	    				new GLO.Popup.Warning('<div><b>' + open.val() + '</b> ' + SA.Resource.IsNotValidTime + '</div>', function() { open.focus(); });
36754	    				return false;
36755	    			} else if (!UTIL.isValidTime(close.val())) {
36756	    				new GLO.Popup.Warning('<div><b>' + close.val() + '</b> ' + SA.Resource.IsNotValidTime + '</div>', function() { close.focus(); });
36757	    				return false;
36758    				}
36759    				
36760    				//toDo: if NOT a valid time, but is numeric --> try to make a time (i.e. '9' + ':00')
36761    			}
36762    		}
36763    	}
36764    	
36765    	return true;
36766    }
36767    
36768    _constructor.validateHours = function() {
36769    	//if (GLO.Info.isAndroid && !_validateHoursForAndroid()) { return false; }
36770    	
36771    	var trs = $('#wizHoursTable').find('tr');
36772    	
36773    	for (var i=0; i < trs.length; i++) {
36774    		var tr = trs.eq(i);
36775    		
36776    		if (!tr.find('.bizClosed').prop('checked')) {
36777    			var open = UTIL.timeToInt(tr.find('.open-time').val());
36778    			var strClose = $.trim(tr.find('.close-time').val()).toLowerCase();
36779    			var close = UTIL.timeToInt(strClose);
36780    			
36781    			if (strClose == '12:00 am') {
36782    				tr.find('.close-time').val('');
36783    			} else if (open > close) {
36784					if (close === 0) {
36785						tr.find('.close-time').val('11:59 pm');
36786					} else {
36787						var weekday = UTIL.getWeekDayName(i);
36788						var h1 = '<h1 class="friendly-msg2">Invalid Time Range on ' + weekday + '</h1>';
36789						var msg = '<p>The open time must be before the close time</p> <p>On ' + weekday + ' the open time is after the close time</p>';
36790						var htm = '<div>' + h1 + '<div class="friendly-msg2">' + msg + '</div></div>';
36791						
36792						var fn = function() { tr.find('.open-time').focus(); };
36793						new GLO.Popup.Warning(htm, fn);
36794						return false;
36795					}
36796				}
36797    		}
36798    	}
36799    	
36800    	return true;
36801    }
36802    
36803    _constructor.changeIndustry = function() {
36804    	var industry = $('#Industry_cd').val();
36805    	var j = _hideIndustryService();
36806    	var classCount = 0;
36807    	
36808    	if (UTIL.isEmpty(industry)) {
36809    		j.addClass('hide');
36810    	} else {
36811    		var jli = j.find('li.i' + industry).removeClass('hide');
36812    		var jli_opt = j.find('li.i' + industry + '-opt').removeClass('hide');
36813    		
36814    		if (jli_opt.length + jli.length > 1) {
36815    			j.removeClass('hide');
36816    			j.find('#svc-other').removeClass('hide').find(':checkbox');
36817    			
36818    			for (var i=0; i < jli.length; i++) {
36819		    		jli.find(':checkbox').prop('checked', true);
36820		    		
36821		    		if (UTIL.parseBool(jli.attr('has_class_fl'))) { ++classCount; }
36822		    	}
36823		    	
36824		    	if (industry == 1) {
36825		    		//$('#primary-nail-salon').removeClass('hide');
36826		    	}
36827		    	
36828		    	if (classCount === 0) {
36829		    		j.find('#svc-other-classes').find('label').text(SA.Resource.OfferClasses);
36830		    	}
36831		    	
36832		    	if ($('#wiz4-form #boxContainer').length > 0) { Wiz4.calculateHeight(); }
36833    		} else {
36834    			_constructor.generateServiceList(industry);
36835    		}
36836    	}
36837    }
36838    
36839    function _hideIndustryService() {
36840    	var j = $('#services-offered-container').addClass('hide');
36841    	var li = j.find('li').addClass('hide');
36842    	
36843    	for (var i=0; i < li.length; i++) {
36844    		li.find(':checkbox').prop('checked', false);
36845    	}
36846    	
36847    	j.find('#create-services-button').removeClass('hide');
36848    	j.find('#svc-other-classes').find('label').text(SA.Resource.OtherClasses);
36849    	
36850    	$('#primary-nail-salon').addClass('hide');
36851    	$('#wiz4-top-buttons').addClass('hide');
36852    	return j;
36853    }
36854    
36855    _constructor.generateServiceList = function(industry) {
36856    	var jlist = $('#service-setup').find(':checkbox:checked');
36857    	var svc_xml = '';
36858    	
36859    	if (UTIL.isEmpty(industry) && jlist.length === 0) {
36860    		if ($('#services-offered-container:visible').find(':checkbox:visible').length > 0) {
36861    			var msg = '<div> <h1 class="friendly-msg">' + SA.Resource.PleaseSelectService + '</h1> <div class="friendly-msg" style="font-size: large;">' + SA.Resource.PleaseCheckServiceBox + '</div> </div>';
36862    			var fn = null;
36863    		} else {
36864    			var msg = '<div> <h1 class="friendly-msg">' + SA.Resource.PleaseSelectService + '</h1> <div class="friendly-msg" style="font-size: large;">' + SA.Resource.PleaseSelectAService + '</div> </div>';
36865    			var fn = function() { $('#Industry_cd').focus() };
36866    		}
36867    		
36868    		new GLO.Popup.Warning(msg, fn);
36869    		return;
36870    	}
36871    	
36872    	for (var i=0; i < jlist.length; i++) {
36873    		svc_xml += '<service>' + jlist.eq(i).attr('id') + '</service>';
36874    	}
36875    	
36876    	if (i > 0) { svc_xml = UTIL.htmlEncode('<list>' + svc_xml + '</list>'); }
36877    	
36878    	if (UTIL.isEmpty(industry)) { industry = $('#Industry_cd').val(); }				//= industry empty if svc checkboxes are visible.
36879    	
36880    	var url = GLO.Link.Object.Provider.Ajax + 'GenerateServiceList';
36881    	GLO.UI.Form.beginProcessing($('.btnCreateServices:visible'));
36882    	
36883    	var btnNext = $('#btnNext, .wiz-buttons .btnCreateServices').addClass('hide');
36884    	
36885        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "industry_cd": industry, "service_list_xml": svc_xml } })
36886            .success(function(data, textStatus, jqXHR) {
36887                GLO.UI.Form.resetProcessing();
36888                btnNext.removeClass('hide');
36889                
36890                var jdata = $(data).find('#boxContainer');
36891                var jdataForm = $(data).find('form');
36892                
36893                $('#boxContainer').remove();
36894                
36895                var frm = $('#wiz4-form').removeClass('hide');
36896                frm.prepend(jdata);
36897                
36898                frm.attr('has_class_fl', jdataForm.attr('has_class_fl'));
36899                frm.attr('has_appt_fl', jdataForm.attr('has_appt_fl'));
36900                frm.attr('class_is_event_fl', jdataForm.attr('class_is_event_fl'));
36901                
36902                _hideIndustryService();
36903                $('#wiz4-top-buttons').removeClass('hide');
36904                
36905                var jbtns = $('.wiz-buttons');
36906                jbtns.find('.btnCreateServices').addClass('hide');
36907                jbtns.find('#btnNext').removeClass('hide');
36908                
36909                _constructor.initWiz4();
36910            })
36911            .error(function (jqXHR, textStatus, errorThrown) {
36912                GLO.UI.Form.resetProcessing();
36913                btnNext.removeClass('hide');
36914                //new GLO.Popup.Error('Unable to delete.  Please try again.');
36915            });
36916    }
36917
36918    return _constructor;
36919})();
36920
36921
36922WIZ.SetupSecurity = (function() {
36923    function _conSecurity() { }
36924    _conSecurity.companyComputerGuid = '';
36925    var _suppressPopups = false;
36926    
36927    _conSecurity.init = function() {
36928    	var jclockin = $('#security-setup-clock-in');
36929    	var isClockInAnywhere = UTIL.parseBool(jclockin.attr('clock_in_anywhere_fl'));
36930    	
36931    	jclockin.find(':radio').change(WIZ.SetupSecurity.saveClockInSetup);
36932    	
36933    	if (isClockInAnywhere) {
36934    		jclockin.find('#clock-in-anywhere').prop('checked', true);
36935    	} else {
36936    		jclockin.find('#clock-in-company-device-only').prop('checked', true);
36937    	}
36938    }
36939    
36940    _conSecurity.whatIsThis = function(thisIcon, isCompanyCpu, noCpuNameRequired) {
36941        var p = '<p style="white-space: pre-wrap; margin-bottom: 8px; padding-left: 12px; line-height: 170%;">';
36942        
36943        if (isCompanyCpu) {
36944        	var htm = p + SA.Resource.CompanyComputerHelp1 + '</p>' + p + SA.Resource.CompanyComputerHelp2 + '</p>';
36945        } else {
36946        	var htm = p + SA.Resource.CompanyComputerHelp3 + '</p>' + p + SA.Resource.CompanyComputerHelp4 + '</p>';
36947            
36948            if (!noCpuNameRequired) {
36949            	htm += p + SA.Resource.CompanyComputerHelp5 + '</p>';
36950            }
36951        }
36952        
36953        var aMoreInfo = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=staff&id=faq-staff-setup-company-device\', this, null, true);">More Information</a>';
36954        var htmMore = '<div style="margin: 8px 0 32px; text-align: center; font-weight: bold;">' + aMoreInfo + '</div>';
36955        var ojInfo = GLO.Popup.Info.open('<div id="pop-info-company-devices">' + htm + htmMore + '</div>', 'Company Devices');
36956    }
36957
36958    _conSecurity.addCpu = function() {
36959        var tbl = $('#security-setup-this-cpu');
36960        var cpu = tbl.find('#Computer_Name_vc').val();
36961		
36962		if (UTIL.isEmpty(cpu)) {
36963        	var cpu = _getDefaultDeviceName();
36964        	
36965        	if (UTIL.isEmpty(cpu)) {
36966	            tbl.find('#Computer_Name_vc').parent().css('background-color', 'pink');
36967	            
36968	            GLO.Popup.Warning('<div style="line-height: 200%;">' + SA.Resource.PleaseEnterCompanyComputerName + '<br/>' + SA.Resource.ItCanBeAnyName + '</div>', function() { window.setTimeout(
36969	                function() { $('#security-setup-this-cpu').find('#Computer_Name_vc').parent().css('background-color', ''); }
36970	            , 2500) });
36971	            
36972	    		return;
36973	        }
36974        }
36975		
36976        _conSecurity.addCpuConfirmed(cpu);
36977    }
36978    function _getDefaultDeviceName() {
36979    	var tr = $('#current-company-computers').find('tbody > tr');
36980    	var deviceNumber = 1;
36981    	
36982    	for (var i=0; i < tr.length; i++) {
36983    		var device = $.trim(tr.eq(i).find('.column-company-cpu-name').text().toLowerCase().replace('device', ''));
36984    		
36985    		if (UTIL.isNumber(device)) {
36986    			var test = UTIL.coalesceInt(device, 0) + 1;
36987    			
36988    			if (test > deviceNumber) {
36989    				deviceNumber = test;
36990    			}
36991    		}
36992    	}
36993    	
36994    	return 'Device ' + deviceNumber;
36995    }
36996    
36997    _conSecurity.addCpuConfirmed = function(cpu) {
36998    	var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer';
36999    	GLO.UI.Form.beginProcessing($('#security-setup-save'));
37000    	
37001        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Is_Company_Computer_fl": "1", "Computer_Name_vc": cpu, "Status_cd": "2" } })
37002            .success(function(data, textStatus, jqXHR) {
37003                var jd = $(data);
37004                var guid = jd.attr('guid');
37005                var pcid = jd.attr('provider_computer_id');
37006                
37007                if (guid.length > 30) {
37008                	if (GLO.Info.isIPad || GLO.Info.isIPhone) {
37009						SA.App.setCompanyDevice(guid);		//GLO.Mobile.iosNativeBridge.call("setCompanyDevice", [guid]);		//GLO.Mobile.iosNativeBridge.call("setCompanyDevice", [guid], callbackFn);
37010					}
37011					
37012					if (_suppressPopups) {
37013	                	_suppressPopups = false;
37014	                } else {
37015	                	setTimeout(function() { location.reload(); }, 900);
37016	                }
37017				}
37018            })
37019            .error(function(jqXHR, textStatus, errorThrown) {
37020                if (!_suppressPopups) {
37021	                new GLO.Popup.Error('Unable to setup this computer as a company computer at this time');
37022	                GLO.UI.Form.resetProcessing();
37023                }
37024            });
37025    }
37026    
37027    _conSecurity.addRemoteCpu = function() {
37028        var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer';
37029        var tbl = $('#security-setup-generate-link-popup');
37030        var cpu = tbl.find('#Remote_Computer_Name_vc').val();
37031        var sid = tbl.find('#Send_To_Staff_id option:selected').val();
37032
37033        if (UTIL.isEmpty(cpu)) {
37034            tbl.find('#Remote_Computer_Name_vc').parent().css('background-color', 'pink');
37035            
37036            GLO.Popup.Warning(SA.Resource.PleaseEnterCompanyComputerName, function() { 
37037                $('#security-setup-generate-link-popup').find('#Remote_Computer_Name_vc').focus();
37038                window.setTimeout( function() { $('#security-setup-generate-link-popup').find('#Remote_Computer_Name_vc').parent().css('background-color', ''); }, 2500) });
37039            return;
37040        }
37041
37042        if (UTIL.isEmpty(sid)) {
37043            tbl.find('#Send_To_Staff_id').closest('tr').css('background-color', 'pink');
37044            
37045            GLO.Popup.Warning('<div style="width: 550px;">' + SA.Resource.CompanyComputerEmailHelp + '<b>' + SA.Resource.CompanyComputer + '</b></div>', function() { 
37046                $('#security-setup-this-cpu').find('#Send_To_Staff_id').focus();
37047                window.setTimeout( function() { $('#security-setup-this-cpu').find('#Send_To_Staff_id').parent().css('background-color', ''); }, 2500) });
37048            return;
37049        }
37050
37051        GLO.UI.Form.beginProcessing($('#security-setup-generate-button'));
37052
37053        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Is_Company_Computer_fl": "1", "Computer_Name_vc": cpu, "Status_cd": "1", "Send_To_Staff_id": sid } })
37054            .success(function(data, textStatus, jqXHR) {
37055                location.reload();
37056            })
37057            .error(function(jqXHR, textStatus, errorThrown) {
37058                new GLO.Popup.Error('Unable to setup this computer as a company computer at this time');
37059                GLO.UI.Form.resetProcessing();
37060            });
37061    }
37062
37063    _conSecurity.removeCpu = function(btnRemove) {
37064        btnRemove = $(btnRemove);
37065        var tr = btnRemove.closest('tr');
37066        var cpu = tr.find('.security-setup-current-cpu-name').text();
37067        var id = tr.attr('provider_computer_id');
37068        var guid = tr.attr('guid');
37069        
37070        var msg = '<p style="margin-bottom: 24px;">' + SA.Resource.Remove + ' <b>' + cpu + '</b> ' + SA.Resource.as_a_company_computer + '?</p>';
37071        var fnSave = function() { WIZ.SetupSecurity.removeCpuConfirmed(id, guid, btnRemove); };
37072        var staffCountCompanyDeviceOnly = UTIL.coalesceInt(tr.attr('logged_in_staff_device_only_sr'), 0);
37073        
37074        if (staffCountCompanyDeviceOnly > 0) {
37075        	msg += '<p style="margin-bottom: 24px;">This will logout the staff - because the staff logged in is only allowed to login on company devices</p>';
37076        }
37077        
37078        GLO.Popup.Confirm.open(msg, 'Remove As Company Device?', fnSave);
37079    }
37080
37081    _conSecurity.removeCpuConfirmed = function(providerCpuId, guid, btnRemove) {
37082        var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputer';
37083        
37084        GLO.UI.Form.beginProcessing(btnRemove);
37085        
37086        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Provider_Computer_id": providerCpuId, "Status_cd": "3", "guid": guid } })
37087            .success(function(data, textStatus, jqXHR) {
37088                GLO.Popup.Success.open('Company Device Removed Successfully', 'Device Removed');
37089                
37090                setTimeout(function() {
37091                	location.reload();
37092                }, 2500);
37093            })
37094            .error(function(jqXHR, textStatus, errorThrown) {
37095                GLO.Popup.Error.open('Unable to remove this computer as a company computer at this time', 'Problem Removing Company Device');
37096                GLO.UI.Form.beginProcessing(btnRemove);
37097                
37098                setTimeout(function() {
37099                	location.reload();
37100                }, 2500);
37101            });
37102    }
37103
37104    _conSecurity.remoteSetup = function() {
37105        GLO.Popup.Confirm(SA.Resource.CompanyComputerConfirm
37106            , function() { WIZ.SetupSecurity.remoteSetupConfirmed(); }
37107            , function() { document.location = GLO.Link.Page.Provider.Profile; });
37108    }
37109
37110    _conSecurity.remoteSetupConfirmed = function() {
37111        var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/CompanyComputerRemotely';
37112        var guid = GLO.Uri.query("g");
37113        var sid = GLO.Uri.query("s");
37114
37115        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Provider_Computer_guid": guid, "Status_cd": "2", "Staff_id": sid } })
37116            .success(function(data, textStatus, jqXHR) {
37117                GLO.Popup.Info(SA.Resource.ComputerSuccessfullySetupHello, function() { document.location = GLO.Link.Page.Provider.Profile; });
37118            })
37119            .error(function(jqXHR, textStatus, errorThrown) {
37120                new GLO.Popup.Error('Unable to setup this computer as a company computer at this time');
37121                //GLO.UI.Form.resetProcessing();
37122            });
37123    }
37124
37125    _conSecurity.openRemotely = function() {
37126        $('#security-setup-generate-link-popup').modal();
37127        var jModal = $('#simplemodal-container').draggable({ "handle": "h2" });
37128        
37129        jModal.find('#security-setup-generate-link-popup').css({ "padding": "0" });
37130    	jModal.find('fieldset').css({ "margin-bottom": "10px", "border-radius": "0" });
37131    	jModal.css({ "padding": "0", "left": "3px" });
37132    	
37133    	if (GLO.Info.isMobile()) {
37134    		jModal.find('.modalCloseImg').attr("style", "top: 3px !important");
37135    	}
37136        
37137        if (jModal.height() < 10 || jModal.width() < 10 || GLO.Info.isMobile()) {
37138        	$.modal.update(510, 555);
37139        } else {
37140        	if (GLO.Info.isIE) {
37141        		jModal.find('fieldset').css({ "margin-bottom": "20px" });
37142        	}
37143        	
37144        	$.modal.update();
37145        }
37146    }
37147    
37148    _conSecurity.justLoggedIn = function() {
37149    	if (UTIL.isEmpty(WIZ.SetupSecurity.companyComputerGuid) && GLO.Info.roleType > 229) {
37150			var iconSrc = GLO.Data.cdnDirectory + 'image/questionMark.png';
37151			var iconTitle = SA.Resource.RegisterThisComputer + ' \'' + SA.Resource.CompanyComputer + '\'';
37152			var iconCSS = 'margin-left: 20px;';
37153			
37154			var h5CSS = 'margin-left: 10px; margin-bottom: 20px;';
37155			
37156			var icon = '<span class="helpIcon2 sa-sprite" onclick="WIZ.SetupSecurity.whatIsThis(this, false, true)" alt="' + iconTitle + '" title="' + iconTitle + '" style="' + iconCSS + '"></span>';
37157			var htm = '<div> <h5 style="' + h5CSS + '">' + SA.Resource.IsThisACompanyComputer + icon + '</h5></div>';
37158			
37159			//Temporary Disable: need to ask this less often: GLO.Popup.Confirm(htm, WIZ.SetupSecurity.askConfirmed);
37160		}
37161    }
37162    
37163    _conSecurity.askConfirmed = function(cpuName) {
37164    	_suppressPopups = true;
37165    	_conSecurity.addCpuConfirmed(cpuName);
37166    }
37167    
37168    _conSecurity.saveClockInSetup = function() {
37169    	var uri = GLO.Link.Page.Provider.Home + 'SetupSecurity/ClockInSetup';
37170    	var clockAnywhere = $('#security-setup-page').find(':radio:checked').val();
37171    	
37172        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "Clock_In_Anywhere_fl": clockAnywhere } })
37173            .success(function(data, textStatus, jqXHR) {
37174                var j = $('#security-setup-this-cpu');
37175				
37176				if (clockAnywhere == 0 && j.length > 0) {
37177					var nm = UTIL.coalesce(j.find('#Computer_Name_vc').val(), 'Main Computer');
37178					
37179					j.find('#Computer_Name_vc').val(nm);
37180					j.find('#security-setup-save').find('a').click();
37181				}
37182            });
37183    }
37184    
37185    _conSecurity.openRemoteRequest = function() {
37186    	var jpop0 = $('#pop-company-device-remote-request').closest('.glopop');
37187    	var username = UTIL.coalesceString(GLO.Uri.query('username'), jpop0.find('#coUser').val(), '');
37188    	var password = UTIL.cleanString(jpop0.find('#coPass').val(), $('#login-password').val());
37189    	
37190    	var msg1 = '<p>Send Company Device Request Email to your admin</p>';
37191    	var msg2 = '<p style="margin-bottom: 36px;">This email contains the verification code you can then enter to set this as a company device</p>';
37192    	
37193    	var htmUser = '<div> <label for="coUser">Your Username</label> <input type="text" id="coUser" value="' + username + '"/> </div>';
37194    	var htmPass = '<div> <label for="coPassword">Your Password</label> <input type="password" id="coPass" value="' + password + '"/> </div>';
37195    	var htmDevice = '<div> <label for="coDevice" title="What name do you want to give this device?">Device Name</label> <input type="text" id="coDevice"/> </div>';
37196    	
37197    	var btn = '<div><span class="btnAdd">
37197<a onclick="WIZ.SetupSecurity.sendRemoteRequest()">Send Admin Request</a></span></div>';
37198    	var htm = '<form id="pop-company-device-remote-request">' + msg1 + msg2 + htmUser + htmPass + htmDevice + '</form>';
37199    	
37200    	GLO.Popup.closeIfExist(jpop0);
37201    	
37202    	var jpop = new GLO.Popup.Custom.openSimple(htm, 'Send Company Device Request', WIZ.SetupSecurity.sendRemoteRequest);
37203    	jpop.find('h1').css({ "background-color": "forestgreen", "color": "white" });
37204    	jpop.find('.btnSave').css({ "min-height": "20px" }).find('> a').text('Send Email');
37205    }
37206    _conSecurity.openRemoteVerification = function() {
37207    	var tpid = $('#login-form').attr('verify_provider_id');
37208    	var jpop0 = $('#pop-company-device-remote-request').closest('.glopop');
37209    	var username = UTIL.coalesceString(GLO.Uri.query('username'), jpop0.find('#coUser').val(), '');
37210    	var password = UTIL.cleanString(jpop0.find('#coUser').val());
37211    	
37212    	var btnBegin = '<span class="btnAdd"><a onclick="WIZ.SetupSecurity.openRemoteRequest()" style="letter-spacing: 0;">Begin Remote Setup</a></span>';
37213    	var htmArrow = '<b class="arrow-right" style="margin-right: 4px;">&#10140;</b>';
37214    	var msg1 = '<p>Enter verification code sent to admin email</p>';
37215    	var msg2 = '<p style="margin-bottom: 36px;">If do not have verification code ' + htmArrow + btnBegin + '</p>';
37216    	
37217    	var htmUser = '<div> <label for="coUser">Your Username</label> <input type="text" id="coUser" value="' + username + '"/> </div>';
37218    	var htmPass = '<div> <label for="coPassword">Your Password</label> <input type="password" id="coPass" value="' + password + '"/> </div>';
37219		var htmVerify = '<div> <label for="Verification_Code_vc">Verification Code</label> <input type="text" id="Verification_Code_vc"/> </div>';
37220    	
37221    	var btn = '<div><span class="btnAdd"><a onclick="WIZ.SetupSecurity.sendRemoteRequest(' + tpid + ')">Send Admin Request</a></span></div>';
37222    	var htm = '<form id="pop-company-device-remote-request">' + msg1 + msg2 + htmUser + htmPass + htmVerify + '</form>';
37223    	
37224    	var jpop = new GLO.Popup.Custom.openSimple(htm, 'Company Device Complete Remote Setup', WIZ.SetupSecurity.sendRemoteRequestVerifyCode);
37225    	jpop.find('h1').css({ "background-color": "forestgreen", "color": "white" });
37226    	jpop.find('.btnSave').css({ "min-height": "20px" });
37227    }
37228    _conSecurity.sendRemoteRequest = function() {
37229    	var jpop = $('#pop-company-device-remote-request').closest('.glopop');
37230    	var jsave = jpop.find('.btnSave');
37231    	
37232    	var user = jpop.find('#coUser').val();
37233    	var pass = jpop.find('#coPass').val();
37234    	var device = jpop.find('#coDevice').val();
37235    	
37236    	if (!_isValidRemoteRequest(jpop, jsave, user, pass, false)) {
37237    		return;
37238    	}
37239    	
37240    	var url = GLO.Link.WebsiteDomain + 'provider/SetupSecurity/CompanyComputerRemoteRequest';
37241    	var json = { "username": user, "password": pass, "device": UTIL.htmlEncode(device) };
37242    	GLO.UI.Form.beginProcessing(jsave);
37243        
37244    	$.ajax({ type: "POST", url: url, "cache": false, data: json })
37245            .success(function(data, textStatus, jqXHR) {
37246                var jdata = $(data);
37247                
37248                if (jdata.hasClass('error')) {
37249                	var ojpop2 = GLO.Popup.Warning.open(data, SA.Resource.CompanyComputerEmailFail);
37250                } else if (jdata.hasClass('success')) {
37251                	GLO.Popup.closeIfExist(jpop);
37252                	
37253                	var tpid = jdata.find('tpid');
37254                	var ojpop2 = GLO.Popup.Success.open('Please ask admin to check their email for verification code', 'Admin Sent Email');
37255                	
37256                	$('#login-form').attr('verify_provider_id', tpid);
37257                } else {
37258                	var ojpop2 = GLO.Popup.Warning.open(data, 'Verification Code Not Sent');
37259                }
37260                
37261                GLO.UI.Form.resetProcessing();
37262                //ojpop2.getPopup().find('h1').css({ "padding": "2px 12px", "font-size": "20px", "background-color": "black", "color": "white" });
37263                ojpop2.getPopup().find('.msg').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" });
37264            })
37265            .error(function(jqXHR, textStatus, errorThrown) {
37266                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
37267            });
37268    }
37269    _conSecurity.sendRemoteRequestVerifyCode = function(tpid) {
37270    	var jpop = $('#pop-company-device-remote-request').closest('.glopop');
37271    	var jsave = jpop.find('.btnSave');
37272    	
37273    	var user = jpop.find('#coUser').val();			//not required
37274    	var pass = jpop.find('#coPass').val();			//not required
37275    	var code = jpop.find('#Verification_Code_vc').val();
37276    	
37277    	if (!_isValidRemoteRequest(jpop, jsave, user, pass, true, code)) {
37278    		return;
37279    	}
37280    	
37281    	var url = GLO.Link.WebsiteDomain + 'provider/SetupSecurity/CompanyComputerRemoteComplete';
37282    	var json = { "username": user, "password": pass, "code": code, "provider": tpid };
37283    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
37284        
37285    	$.ajax({ type: "POST", url: url, "cache": false, data: json })
37286            .success(function(data, textStatus, jqXHR) {
37287                if ($(data).hasClass('error')) {
37288                	var ojpop2 = GLO.Popup.Error.open(data, 'Unable to Process Verification Code');
37289                } else if ($(data).hasClass('success')) {
37290                	GLO.Popup.closeIfExist(jpop);
37291                	
37292                	var ojpop2 = GLO.Popup.Success.open(SA.Resource.CompanyComputerNowRegistered, 'Company Device Successfully Setup');
37293                	var url = $(data).attr('url');
37294                	var jform = $('#login-form');
37295                	
37296                	if (jform.length) {
37297                		jform.find('#login-user').val(user);
37298                		jform.find('#login-password').val(pass);
37299                		
37300                		window.setTimeout(function() {
37301                			jform.find('#btnLogin').click();
37302                		}, 2500);
37303                	} else if (url) {
37304                		window.setTimeout(function() {
37305                			document.location = GLO.Link.WebsiteDomain + url;
37306                		}, 1500);
37307                	}
37308                } else {
37309                	var ojpop2 = GLO.Popup.Warning.open(data, 'Verification Code Not Processed');
37310                }
37311                
37312                GLO.UI.Form.resetProcessing();
37313                //ojpop2.getPopup().find('h1').css({ "padding": "2px 12px", "font-size": "20px", "background-color": "black", "color": "white" });
37314                ojpop2.getPopup().find('.msg').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" });
37315            })
37316            .error(function(jqXHR, textStatus, errorThrown) {
37317                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
37318            });
37319    }
37320    function _isValidRemoteRequest(jpop, jsave, user, pass, isRequireVerify, verify) {
37321    	var warnMsg = null, jfield = null;
37322    	
37323    	if (jsave.hasClass('btnProcessing4')) {
37324    		return false;
37325    	} else if ($.trim(user).length < 4) {
37326    		warnMsg = 'Please enter valid <b>Username</b>';
37327    		jfield = jpop.find('#CoUser');
37328    	} else if ($.trim(pass).length < 4) {
37329    		warnMsg = 'Please enter valid <b>Password</b>';
37330    		jfield = jpop.find('#CoPass');
37331    	} else if (isRequireVerify && $.trim(verify).length < 8) {
37332    		warnMsg = 'Please enter valid remote company device setup <b>Verification Code</b>';
37333    		jfield = jpop.find('#Verification_Code_vc');
37334    	}
37335    	
37336    	if (warnMsg) {
37337    		var fn = function() {
37338    			jfield.focus();
37339    			UI.highlight(jfield);
37340    		}
37341    		
37342    		var jpop = GLO.Popup.Warning.open(warnMsg, 'In-Complete Warning').getPopup();
37343    		//jpop.find('h1').css({ "padding": "2px 12px", "font-size": "20px", "background-color": "orange", "color": "white" });
37344    		jpop.find('.msg').css({ "letter-spacing": "1px", "font-size": "16px", "font-weight": "bold" });
37345    		return false;
37346    	} else {
37347    		return true;
37348    	}
37349    }
37350    
37351    _conSecurity.setupRemotely = function() {
37352    	new GLO.Popup.Confirm(SA.Resource.SetupThisDeviceAsA + ' <b>' + SA.Resource.CompanyComputer + '</b>?'
37353	        , function() {
37354	            var jform = $('#remote-company-computer-setup');
37355	            var guid = jform.find('#Provider_Computer_guid').val();
37356            	
37357            	var url = GLO.Link.WebsiteDomain + 'provider/SetupSecurity/CompanyComputerRemotely?g=' + guid;
37358            	GLO.UI.Form.beginProcessing(jform.find('#progress2'));
37359	            
37360            	$.ajax({ type: "POST", url: url, "cache": false, data: { "Provider_Computer_guid": guid } })
37361	                .success(function(data, textStatus, jqXHR) {
37362	                    var url = $(data).attr('url');
37363	                    
37364	                    if (url === 'err') {
37365	                    	new GLO.Popup.Warning(SA.Resource.CompanyComputerEmailFail);
37366	                    } else {
37367	                    	new GLO.Popup.Success(SA.Resource.CompanyComputerNowRegistered);
37368	                    	
37369	                    	window.setTimeout(function() { document.location = GLO.Link.WebsiteDomain + url; }, 1500);
37370	                    }
37371	                })
37372	                .error(function(jqXHR, textStatus, errorThrown) {
37373	                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
37374	                });
37375	        }
37376	    );
37377    }
37378    
37379    return _conSecurity;
37380})();
37381
37382
37383var Wiz1 = (function() {
37384    function _constructor(name) { }
37385	_constructor.header = null;
37386    
37387    _constructor.init = function(pop, profileType) {
37388        if (pop != null) {
37389            var jWiz1 = pop.find('#wiz1-body');
37390        } else {
37391            var jWiz1 = $('#wiz1-body');
37392        }
37393
37394        UI.phoneMask(jWiz1.find("#Mobile_Phone_vc"));
37395        UI.phoneMask(jWiz1.find("#Other_Phone_vc"));
37396        jWiz1.find("#Birth_Year_sr").mask("9999");
37397        var isNew = true;
37398        
37399        if (GLO.Info.isAndroid) {
37400            jWiz1.find("#Mobile_Phone_vc, #Other_Phone_vc").attr('type', 'tel');
37401        }
37402        
37403        if (!UTIL.isEmpty(jWiz1.find('#Staff_id').val())) {
37404        	isNew = false;
37405        	jWiz1.find('#First_Name_vc, #Middle_Initial_c, #First_Name_vc').css({ "text-transform": "inherit" });
37406        }
37407        
37408        _initLanguage(WIZ.page, isNew, jWiz1);
37409        SA.Parent.initLinkStaffButton(jWiz1, isNew);
37410        
37411        if (WIZ.page == 1) {
37412            WIZ.init(1, '#wiz1-body');
37413            
37414            /*
37415            var loadUrl = GLO.Link.Object.MobileProvider + '?dt=' + UTIL.getDateString();
37416            
37417            jWiz1.find("#mobile-providers").load(loadUrl, function() {
37418                UI.setAccessKey('#text-me-popup', null, MobileProviderPopup.save);
37419            });
37420            */
37421            
37422            if (WIZ.isWizard) {
37423            	var jrefer = jWiz1.find('#wiz-referred-by').removeClass('hide2').find('#Referred_By_vc');
37424            	var refer = UTIL.coalesce(GLO.Uri.query('Referred_By_vc'), GLO.Uri.query('refer'), GLO.Uri.query('referby'), jrefer.val(), '');
37425            	jrefer.val(refer);
37426            } else {
37427            	$('#btnNext').css({ "margin": "auto", "letter-spacing": "2px" });
37428            }
37429        } else {
37430            if (pop == null && WIZ.page != 5) {
37431                UI.setAccessKey('#wiz1-body', null, WIZ.save)
37432            } else {
37433                UI.setAccessKey('#wiz1-body', null, WIZ.popupSave, null);
37434            }
37435
37436            if (profileType === 'client' || profileType === 'clientadmin') {
37437                jWiz1.find('#wiz1-profilePhoto').addClass('hide');
37438                jWiz1.find('#wiz1-showMore-container').addClass('hide');
37439                jWiz1.find('#wiz1-popupNext').removeClass('hide');
37440            } else {
37441                var imgProfile = jWiz1.find('#Image_Path_vc').val();
37442                var staffId = jWiz1.find('#Staff_id').val();
37443                jWiz1.find('#wiz1-profilePhoto').remove();
37444                jWiz1.find('#wiz1-editPhoto').removeClass('hide');
37445                
37446                if (!GLO.Info.isIosApp) { var target = ' target="_blank"'; } else { var target = ''; }
37447                
37448                if (!UTIL.isEmpty(imgProfile)) {
37449                    var existingImg = '<a href="/provider/profilephoto/?staff=' + staffId + '"' + target + '><img src="/upload-folder/' + imgProfile + '" height="55px" style="margin:0;"/></a>';
37450                    existingImg += '<span style="margin-left: 50px;"><a href="/provider/profilephoto/?staff=' + staffId + '"' + target + '>' + SA.Resource.EditPhoto + '</a></span>'
37451    
37452                    jWiz1.find('#editPhoto').html(existingImg);
37453                } else {
37454                    var noImg = '<span style="margin-left: 5px;"><a href="/provider/profilephoto/?staff=' + staffId + '"' + target + '>' + SA.Resource.UploadPhoto + '</a></span>';
37455                    jWiz1.find('#editPhoto').css('height', '65px').html(noImg);
37456                }
37457            }
37458
37459            return;
37460        }
37461        
37462        if (innerWidth < 500) {
37463        	jWiz1.find('#First_Name_vc').css({ "margin-left": "8px", "margin-right": "8px" });
37464        	jWiz1.find('#Password2_vc').css({ "margin-left": "8px" });
37465        }
37466        
37467        if (innerWidth < 800) {
37468        	jWiz1.find('#labelTextReminders').text('Text Me');
37469        }
37470        
37471        jWiz1.find('#wiz1-header').css('padding', '20px');
37472        
37473        if (_constructor.header == null) {
37474            jWiz1.find('.shadow0 #wiz1-header').text(SA.Resource.PleaseTellUsAboutYou);
37475        } else {
37476            jWiz1.find('#wiz1-header').text(_constructor.header);
37477        }
37478        
37479        _initForPhone();
37480        _initDisplayMessage();
37481        _initUrlActions();
37482    }
37483	
37484	function _initUrlActions() {
37485    	var open = UTIL.cleanString(GLO.Uri.query('open')).toLowerCase();
37486    	var highlight = UTIL.cleanString(GLO.Uri.query('highlight'));
37487    	var popuptab = UTIL.cleanString(GLO.Uri.url('popuptab')).toLowerCase();
37488    	var btns = $('#wiz1-staff-buttons');
37489    	
37490    	if (!UTIL.isEmpty(open)) {
37491	    	if (open === 'link') {
37492	    		btns.find('#btnLinkStaff > a').click();
37493	    	} else if (open === 'alert' || open === 'role') {
37494	    		btns.find('.btnAlert > a').click();
37495	    	} else if (open === 'service') {
37496	    		btns.find('.btnService > a').click();
37497	    	} else if (open === 'hour') {
37498	    		btns.find('.btnHour > a').click();
37499	    	} else if (open === 'client') {
37500	    		btns.find('.btnClientSetup > a').click();
37501	    		
37502	    		if (GLO.Uri.query('tab') == 2) { popuptab = 'client-messages'; }
37503	    		
37504	    		if (highlight == 'confirmation' || popuptab === 'client-messages' || popuptab === 'policy') {
37505	    			Wiz5.initPopupUrlAction(popuptab, highlight, 1);
37506	    		}
37507	    	} else if (open === 'bio') {
37508	    		btns.find('.btnBio > a').click();
37509	    	}
37510	    }
37511	    
37512	    if (UTIL.cleanString(GLO.Uri.query('msg')) == 'pastdue') {
37513	    	var msg1 = '<p style="font-weight: bold; color: red;">Your account is past due</p>';
37514	    	var msg2 = '<p>Please login as a Manager or Admin to update the card-on-file with ' + GLO.Info.getScheduleAnyoneHtm(
37514) + '</p>';
37515	    	var msg3 = '<p></p>';
37516	    	
37517	    	var htm = '<div id="pop-warn-past-due">' + msg1 + msg2 + '</div>';
37518			var jpop = GLO.Popup.Warning.open(htm, 'Account Past Due').getPopup().css({ "background-color": "#eee" });
37519			
37520			GLO.Popup.Custom.singleButton(jpop, 'Close');
37521	    }
37522	    
37523	    UI.highlightCheck(highlight, null, 2800);
37524    }
37525    
37526    function _initLanguage(page, isNew, jWiz1) {
37527		var jlanguage = jWiz1.find('#wiz-language');
37528		var language = (window.navigator.userLanguage || window.navigator.language);
37529		var hasSaLanguage = (!UTIL.isEmpty(jlanguage.find('select').val()));
37530		var isViet = (language.indexOf('vi-') === 0);
37531		var isMS = (GLO.Data && GLO.Data.provider && GLO.Data.provider.var_cd === 3);
37532		var isNail = (GLO.Data && GLO.Data.provider && GLO.Data.provider.industry_cd === 8);
37533		var isActive = true;			//($.cookies.get('pstatus') == 11);
37534		
37535		if (isActive && page == 1 && (hasSaLanguage || isViet || isNew || isNail || isMS)) {
37536			jlanguage.removeClass('hide');
37537			
37538			if (isViet && isNew) {
37539				jlanguage.find('select').val(2);
37540			}
37541		} else if (jlanguage.is(':visible')) {
37542			jlanguage.remove();
37543			$.modal.update($('#simplemodal-container').height() - 60, null);
37544		}
37545	}
37546	
37547	function _initDisplayMessage() {
37548		if (GLO.Uri.query('username') == 'duplicate') {
37549			var jmsg = $('<div class="friendly-msg2"> <h1 class="friendly-msg2">' + SA.Resource.InvalidUsername + '</h1> <div>' + SA.Resource.UsernameAlreadyTaken + '</div> <div>' + SA.Resource.PleaseUseDiffUsername + '</div> </div>');
37550			new GLO.Popup.Warning(jmsg);
37551		}
37552	}
37553	
37554	function _initForPhone() {
37555		if (!GLO.Info.isMobile()) { return; }
37556		
37557		var jb = $('#wizBody');
37558		jb.find('#labelTextReminders').text('Text Me');
37559		
37560		/*
37561		var jselect = jb.find('#Female_fl');
37562		jselect.css({ "width": "50px" });
37563		jselect.find('option').eq(1).text('M');
37564		jselect.find('option').eq(2).text('F');
37565		
37566		jb.find('#First_Name_vc, #Last_Name_vc, #Password_vc, #Password2_vc').css({ "width": "100px" })
37567		
37568		var trMobile = jb.find('#row-mobilePhone');
37569		trMobile.find('td:last').attr('colspan', 2).prepend( jb.find('#Mobile_Phone_vc') );
37570		trMobile.find('td').eq(1).remove();
37571		
37572		jb.find('#Mobile_Phone_vc').css({ "margin-right": "40px" });
37573		jb.find('#Mobile_Phone_vc').before('<label for="Mobile_Phone_vc">' + SA.Resource.Mobile + ':</label>');
37574		
37575		jb.find('#Email_vc').css({ "width": "310px" });
37576		jb.find('#Username_vc').before('<b>' + SA.Resource.Username + ':</b>');
37577		jb.find('#Password_vc').before('<b>' + SA.Resource.Password + ':</b>');
37578		
37579		if (WIZ.isWizard) {
37580			jb.find('#Username_vc').css({ "width": "210px" });
37581		} else {
37582			jb.find('#Username_vc').css({ "width": "240px" });
37583		}
37584		*/
37585		//$('#search-bar, #ft').css({ "width": "inherit", "min-width": "inherit" });
37586	}
37587	
37588	_constructor.changeNormalStaffRole = function(element) {
37589		var jmodal = $('#simplemodal-container');
37590		var juser = jmodal.find('#wiz1-username');
37591		var h = jmodal.height(), isResetUsername = false;
37592		var isVisible = juser.is(':visible');
37593		
37594		if (element.value > 199) {
37595			if (!isVisible) {
37596				if (UTIL.coalesce(juser.find('input').val(), 'Username') == 'Username') {
37597					isResetUsername = true;
37598				}
37599				
37600				juser.removeClass('hide').after(juser.prop('password_htm'));
37601				var jpass = jmodal.find('#wiz1-password');
37602				UTIL.DefaultText.init(jpass);
37603				
37604				Wiz1.changeNormalStaffRole_display(isResetUsername);
37605				setTimeout(function() { Wiz1.changeNormalStaffRole_display(isResetUsername); }, 120);
37606				
37607				h += 100;
37608			}
37609		} else if (isVisible) {
37610			var jpass = jmodal.find('#wiz1-password');
37611			juser.addClass('hide');
37612			juser.prop('password_htm', jpass.outerHTML());
37613			jpass.remove();
37614			h -= 100;
37615		}
37616		
37617		$.modal.update(h, null);
37618	}
37619	
37620	_constructor.changeNormalStaffRole_display = function(isResetUsername) {		//clear any 'default password' from browser + set focus.
37621		var jmodal = $('#simplemodal-container');
37622		var juser = jmodal.find('#wiz1-username');
37623		var jpass = jmodal.find('#wiz1-password');
37624		
37625		if (isResetUsername) {
37626			jpass.find('input').val('').blur();
37627		}
37628		
37629		jpass.find('input').val('').blur();
37630			
37631		if (isResetUsername) {
37632			juser.find('input').focus();
37633		} else {
37634			jpass.find('input:first').focus();
37635		}
37636	}
37637	
37638    _constructor.helpPinCode = function() {
37639    	var msg1 = '<p>Passwords must be 8 characters or longer</p>';
37640    	var msg2 = '<p>PIN Codes can be shorter <span class="narrow-text" style="color: inherit;">(PIN Codes are 4-10 characters)</span></p>';
37641    	var msg3 = '<p>Use your password to login</p>';
37642    	var msg4 = '<p style="margin-top: 20px;">If your account is setup to require entering password when changing appointments or accessing reports then you can use your password or PIN Code</p>';
37643    	var htm = '<div id="pop-help-pin-code">' + msg1 + msg2 + msg3 + msg4 + '</div>';
37644    	
37645    	var ojpop = GLO.Popup.Info.open(htm, 'PIN Code vs Password');
37646    }
37647    
37648    _constructor.UsernameIsUnique = function() {
37649        var url = GLO.Link.Object.Provider.Ajax + "UsernameIsUnique";
37650        var j = $('#wiz1-form');
37651
37652        var sid = j.find('#Staff_id').val();
37653        var user = j.find('#Username_vc').val();
37654        
37655        if (UTIL.isEmpty(user)) { 
37656            $('#UsernameUniqueStatus').html('').removeClass('good').removeClass('bad');
37657            return; 
37658        }
37659
37660        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { 'Username_vc': user, 'Staff_id': sid} })
37661            .success(function(data, textStatus, jqXHR) {
37662                var jdata = $(data);
37663                
37664                if (UTIL.parseBool(jdata.attr('is_unique_fl'))) {
37665                    $('#UsernameUniqueStatus').removeClass('bad').addClass('good').html(SA.Resource.Available.toLowerCase());
37666                } else {
37667                    $('#UsernameUniqueStatus').removeClass('good').addClass('bad').html(SA.Resource.already_taken);
37668                    GLO.ClientProfile.changeUsernameAndRetry(j);
37669                }
37670            })
37671            .error(function(jqXHR, textStatus, errorThrown) {
37672                //_saveReset();
37673            })
37674    }
37675
37676    _constructor.emailChange = function(el) {
37677        var jClient = $('#wiz1-form');
37678        var username = jClient.find('#Username_vc');
37679        
37680        if (UTIL.isEmpty(username.val()) || username.val() == 'Username') { 
37681            GLO.ClientProfile.setUsername(username, el.value);
37682            username.removeClass("defaultTextActive");
37683            _constructor.UsernameIsUnique();
37684        }
37685    }
37686    
37687    _constructor.displayTextAlertConfirm = function() {
37688    	if (GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) { return false; }
37689    	if (GLO.Info.providerPackage === 4) { return false; }
37690    	
37691    	var jwiz1 = $('#wiz1-form');
37692        var jtext =  jwiz1.find('#Text_Appt_Reminders_fl');
37693        var jmp =  jwiz1.find('#Mobile_Provider_cd');
37694        
37695        if (UTIL.parseBool(jmp.attr('override_fl')) || !UTIL.isEmpty(jmp.val())) {			// && jtext.prop('checked')
37696        	return false;
37697        }
37698        
37699        if (UTIL.isEmpty(jwiz1.find('#Mobile_Phone_vc').val())) { return; }
37700        
37701        var ddlabelCSS = 'width: 240px; margin: auto; font-size: 18px; font-weight: bold;';
37702        if (innerWidth < 500) { ddlabelCSS += 'display: block;'; } else { ddlabelCSS += 'padding-right: 6px;'; }
37703        
37704        var ddlabel = '<label for="Staff_Mobile_Provider_cd" style="' + ddlabelCSS + '">Mobile Phone Provider</label>';
37705        var dd = '<select id="Staff_Mobile_Provider_cd" style="letter-spacing: 1px; font-size: 16px;">' + jwiz1.find('#Mobile_Provider_cd').html() + '</select>';
37706        var frm = '<div style="margin-top: 8px; margin-bottom: 20px;">' + ddlabel + dd + '</div>';
37707        
37708        var msg0 = 'Do you';
37709        if (jwiz1.closest('#simplemodal-container').length) { msg0 = 'Does ' + jwiz1.find('#First_Name_vc').val(); }
37710        
37711        var msg = '<p>' + msg0 + ' want to receive text alerts when clients book appointments?</p>';
37712		var htm = '<div id="pop-staff-mobile-provider" class="friendly-msg4"><h1 class="friendly-msg">Appointment Alerts?</h1><div class="friendly-msg">' + msg + frm + '</div></div>';
37713		var jpop = new GLO.Popup.Confirm(htm, Wiz1.saveTextAlertConfirm, Wiz1.c
37713ancelTextAlertConfirm).getPopup();
37714		
37715		jpop.find('.btnYes > a').css({ "border-radius": "20px" });
37716		
37717		jmp.attr('override_fl', '1');
37718		return true;
37719    }
37720    
37721    _constructor.saveTextAlertConfirm = function() {
37722    	var jpop = $('#pop-staff-mobile-provider').closest('.glopop');
37723    	var newMP = jpop.find('#Staff_Mobile_Provider_cd').val();
37724    	
37725    	if (UTIL.isEmpty(newMP)) {
37726    		var warnH1 = 'Please Enter Phone Company';
37727    		
37728    		var jwiz1 = $('#simplemodal-container #wiz1-form');
37729    		var warnMsg0 = 'your';
37730    		if (jwiz1.length) { warnMsg0 = jwiz1.find('#First_Name_vc').val() + '\'s'; }
37731    		
37732    		var warnMsg = 'Please enter ' + warnMsg0 + ' mobile phone company to opt-in to text alerts';
37733    		var warnHtm = '<div id="pop-staff-mobile-provider-warn" class="friendly-msg4"><h1 class="friendly-msg">' + warnH1 + '</h1><div class="friendly-responsive">' + warnMsg + '</div></div>';
37734    		var fnOk = function() { jpop.find('#Staff_Mobile_Provider_cd').focus(); }
37735    		
37736    		new GLO.Popup.Warning(warnHtm, fnOk);
37737    		return 'wait';
37738    	}
37739    	
37740    	var jwiz1 = $('#wiz1-form');
37741        jwiz1.find('#Text_Appt_Reminders_fl').prop('checked', true);
37742        jwiz1.find('#Mobile_Provider_cd').val(newMP);
37743        
37744        _constructor.saveProfile();
37745    }
37746    
37747    _constructor.cancelTextAlertConfirm = function() {
37748    	$('#wiz1-form #Text_Appt_Reminders_fl').prop('checked', false);
37749    	_constructor.saveProfile();
37750    }
37751    
37752    _constructor.saveProfile = function() {
37753    	var jsave = $('#wiz5-popupStaffProfile #wiz1-Save');
37754        
37755        if (jsave.length) {			//WIZ.page == 5
37756        	jsave.find('a').click();
37757        } else {
37758        	$('#btnNext > a').click();
37759        }
37760    }
37761    
37762    return _constructor;
37763})();
37764
37765var Wiz2 = (function() {
37766    function _constructor(name) { }
37767
37768    _constructor.geocoder;
37769    
37770    _constructor.setLatLong = function(element, event) {
37771        var street = $('#Street1_vc').val();
37772        var city = $('#City_vc').val();
37773        var state = $('#State_cc').val();
37774        var zip = $('#Zip_vc').val();
37775
37776        if (UTIL.isEmpty(street) || UTIL.isEmpty(city) || UTIL.isEmpty(state) || UTIL.isEmpty(zip)) { return; }
37777        if (street === $('#Street1_vc').attr('title') || city === $('#City_vc').attr('title') || state === $('#State_cc').attr('title') || zip === $('#Zip_vc').attr('title')) { return; }
37778        
37779        GLO.Map.lookupLatLong(street, city, state, zip);
37780	    
37781	    if (element && element.name === 'State_cc') {
37782	    	var state = element.value;
37783	    	
37784	    	if (state === 'AB' || state === 'BC' || state === 'MB' || state === 'NB' || state === 'NL' || state === 'NS' || state === 'NT' || state === 'NU'
37785	    			 || state === 'ON' || state === 'PE' || state === 'QC' || state === 'SK' || state === 'YT') {
37786	    		$('#Country_Code_c2').val('CA');
37787	    	} else if (state !== 'OO' || state !== '') {
37788	    		$('#Country_Code_c2').val('US');
37789	    	}
37790	    }
37791    }
37792    
37793    return _constructor;
37794})();
37795
37796var Wiz5 = (function() {
37797    function _constructor(name) { }
37798    _constructor.newProfileIsLoaded = false;
37799    var _columnNumber, _staffId;
37800	
37801    _constructor.init = function() {
37802        var sortList = [[2, 1]];				//sort by Role, then Staff Name
37803        
37804        $("#wiz5-stafflist").tablesorter({ headers: { 0: { sorter: false}}, textExtraction: UI.tableSorterOrderBy, sortList: sortList }).bind("sortEnd", function() {
37805                var tbody = $("#wiz5-stafflist").find("tbody");
37806                tbody.find("tr:even").removeClass('EveryOtherRowQuiet');
37807                tbody.find("tr:odd").addClass('EveryOtherRowQuiet');
37808                tbody.find("tr").css({ "background-color": "" });
37809            });
37810
37811        WIZ.init(5, '#wiz5-context');
37812        
37813        //if ($.cookies.get('package') == "1") { $('#wiz-status-header').find('.wiz-tab').removeClass('wiz-tab').css({ "background-color": "" }); }
37814        
37815        var j = $('.wiz-buttons')
37816        
37817        if (WIZ.isWizard) {
37818        	if (!GLO.Info.isMobile()) {
37819        		j.find('#wiz5-AddProvider').removeClass('hide');
37820        	}
37821        } else {
37822        	j.find('#wiz5-AddProvider').removeClass('hide');
37823        }
37824        
37825        _initHeaderLinks();
37826        _expandHeight();
37827        _initUrlActions();
37828        
37829        if (!WIZ.isWizard) {
37830        	if (GLO.Info.isMobile()) {
37831        		$('.wiz-buttons, #wiz-button-top-padding').remove();
37832        	} else {
37833        		j.find('.btnDelete').removeClass('hide');
37834        	}
37835        }
37836        
37837        if (GLO.Info.providerPackage === 2 || GLO.Info.providerPackage === 3 || GLO.Info.providerPackage === 10) {
37838        	if (GLO.Info.roleType > 219) {
37839	        	GLO.Report.enableFullPageCheck();
37840	        }
37841        } else if (GLO.Info.providerPackage === 4) {
37842        	_initSilverPackage();
37843        }
37844    }
37845    
37846    function _initSilverPackage() {
37847    	if (innerWidth > 800) { return; }
37848    	
37849    	var jtbl = $('#wiz5-stafflist');
37850    	var td = jtbl.find('.wiz5-column-staff-service');
37851    	
37852    	for (var i=0; i < td.length; i++) {
37853    		var svc = td.eq(i).text();
37854    		
37855    		if (svc.length > 30) {
37856    			td.eq(i).text(svc.substring(0,28) + '..');
37857    		}
37858    	}
37859    }
37860    
37861    function _initUrlActions() {
37862    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
37863    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
37864    	var popuptab = UTIL.cleanString(GLO.Uri.url('popuptab')).toLowerCase();
37865    	var sid = GLO.Uri.url('staff');
37866    	
37867    	if (!UTIL.isEmpty(open)) {
37868	    	if (sid == 0) {
37869	    		var tr = $('#wiz5-stafflist').find('tbody tr:first');
37870	    		
37871	    		if (tr.attr('is_fa') == '1') { tr = $('#wiz5-stafflist').find('tbody tr').eq(1); }
37872	    	} else {
37873	    		var tr = $('#wiz5-stafflist').find('#trStaff' + sid);
37874	    	}
37875	    	
37876	    	if (open === 'profile') {
37877	    		tr.find('.wiz5-column-name').click();
37878	    	} else if (open === 'alert' || open === 'role') {
37879	    		tr.find('.wiz5-column-alerts-and-role').click();
37880	    		
37881	    		if (open == 'alert') {
37882	    			Wiz5.initPopupUrlAction('#wiz-tab-alert > a', highlight, 1);
37883	    		} else if (open == 'role') {
37884	    			Wiz5.initPopupUrlAction('#wiz-tab-role > a', highlight, 1);
37885	    		}
37886	    	} else if (open === 'service') {
37887	    		tr.find('.wiz5-column-staff-service').click();
37888	    	} else if (open === 'hour') {
37889	    		tr.find('.wiz5-column-hours').click();
37890	    	} else if (open === 'client') {
37891	    		tr.find('.wiz5-column-client-config').click();
37892	    		
37893	    		if (highlight == 'confirmation' || popuptab === 'client-messages' || popuptab == 2) {
37894	    			Wiz5.initPopupUrlAction(popuptab, highlight, 1);
37895	    		}
37896	    	} else if (open === 'permission') {
37897	    		tr.find('.wiz5-permission-item').click();
37898	    	} else if (open === 'add-staff') {
37899	    		$('#wiz5-AddProvider').find('a').click();
37900	    	} else if (open === 'link-staff') {
37901	    		$('#wiz5-AddProvider').find('a').click();
37902	    		
37903	    		setTimeout(function() {
37904	    			$('#pop-add-staff-create-or-copy #btnAddLinkStaff').find('a').click();
37905	    		}, 600);
37906	    	}
37907	    }
37908	    
37909	    _initHighlightColumn(highlight);
37910    }
37911    
37912    _constructor.initPopupUrlAction = function(popuptab, highlight, attempt) {
37913    	var jtabs = $('#simplemodal-container .tab-control');
37914    	var highlightTest = highlight.toLowerCase();
37915    	
37916    	if (jtabs.length > 0) {
37917	    	if (highlightTest == 'confirmation') {
37918				jtabs.find('#wizcc-tab-appt-message > a').click();
37919				
37920				UI.highlight($('#wiz5-cc-confirm-row'), 100);
37921			} else if (popuptab == 2 || popuptab === 'client-messages') {
37922				jtabs.find('#wizcc-tab-appt-message > a').click();
37923				
37924				if (highlightTest === 'reminder') {
37925					UI.highlight($('#wiz5-cc-reminder-row'), 100);
37926				} else if (highlightTest === 'unconfirm') {
37927					UI.highlight($('#wiz-cc-allow-unconfirm-row, #wiz-cc-text-on-unconfirm-row'));
37928				} else if (highlightTest === 'prices') {
37929					UI.highlight($('#wiz-cc-display-prices-row'), 100);
37930				} else {
37931					UI.highlightCheck(highlight, null, 800);
37932				}
37933			} else {
37934				jtabs.find(popuptab).click();
37935				
37936				if (highlightTest == 'client-note-access') {
37937					UI.highlight($('#wiz5-popupStatus-client-note-access'), 100);
37938				} else {
37939					UI.highlightCheck(highlight, null, 800);
37940				}
37941			}
37942		} else if (attempt < 9) {
37943			setTimeout(function() {
37944				Wiz5.initPopupUrlAction(popuptab, highlight, ++attempt);
37945			}, 800)
37946		}
37947    }
37948    
37949    function _initHighlightColumn(highlightValue) {
37950    	var highlightColumn = null;
37951    	var highlight = highlightValue.toLowerCase();
37952    	
37953    	if (highlight == 'checkbox-column' || highlight == 'column0') {
37954    		highlightColumn = 0;
37955		} else if (highlight == 'profile-column' || highlight == 'column1') {
37956	    	highlightColumn = 1;
37957	    } else if (highlight == 'alert-column' || highlight == 'column2') {
37958	    	highlightColumn = 2;
37959	    } else if (highlight == 'service-column' || highlight == 'column3') {
37960	    	highlightColumn = 3;
37961	    } else if (highlight == 'hour-column' || highlight == 'column4') {
37962	    	highlightColumn = 4;
37963	    } else if (highlight == 'client-column' || highlight == 'column5') {
37964	    	highlightColumn = 5;
37965	    } else if (highlight == 'permission-column' || highlight == 'column6') {
37966	    	highlightColumn = 6;
37967	    }
37968	    
37969	    if (highlightColumn) {
37970	    	++highlightColumn;
37971	    	var jcolumn = $('#wiz5-stafflist').find('tr th:nth-child(' + highlightColumn + '), tr td:nth-child(' + highlightColumn + ')');
37972	    	
37973	    	UI.highlight(jcolumn, 800, 9800);
37974	    }
37975    }
37976    
37977    function _expandHeight() {
37978    	var docHeight = $('#doc3').height();
37979        var extraHeight = innerHeight - docHeight;
37980        var listHeight = $('#wiz5-stafflist-container').height();
37981        
37982        if (innerHeight > listHeight + 80) {
37983        	if (listHeight < 500 && innerHeight - 400 > listHeight) {
37984        		listHeight = innerHeight - 400;
37985        	}
37986        	
37987        	$('#wiz5-main').height(listHeight + 100);
37988        	$('#wiz5-staffparent').height(listHeight + 20);
37989        } else if (extraHeight > 0 && listHeight > 400) {
37990        	$('#wiz5-main').height(480 + extraHeight);
37991        	$('#wiz5-staffparent').height(420 + extraHeight);
37992        } else if (docHeight - listHeight > 300) {
37993        	if (listHeight < 300 && !GLO.Info.isMobile(true)) {
37994        		if (innerHeight - listHeight > 600) { listHeight = innerHeight - 600; }
37995        		if (listHeight < 300) { listHeight = 240; }
37996        	}
37997        	
37998        	$('#wiz5-main').height(150 + listHeight);
37999        	$('#wiz5-staffparent').height(80 + listHeight);
38000        }
38001    }
38002
38003    function _initHeaderLinks() {
38004        $('#wiz5-th-profile').click( function(ev) {
38005            if (ev.altKey) {
38006                ev.stopPropagation();
38007                GLO.UI.Form.beginProcessing($(this));
38008                document.location = GLO.Link.WebsiteDomain + 'fragment/staff/ProfileList';
38009            }
38010        });
38011
38012        $('#wiz5-th-notify').click( function(ev) {
38013            if (ev.altKey) {
38014                ev.stopPropagation();
38015                GLO.UI.Form.beginProcessing($(this));
38016                document.location = GLO.Link.WebsiteDomain + 'fragment/staff/NotificationList';
38017            }
38018        });
38019
38020        $('#wiz5-services-offered').click( function(ev) {
38021            if (ev.altKey) {
38022                ev.stopPropagation();
38023                GLO.UI.Form.beginProcessing($(this));
38024                document.location = GLO.Link.WebsiteDomain + 'fragment/staff/QuickViewAll?fullpage=1';
38025            }
38026        });
38027
38028        $('#wiz5-th-hours').click( function(ev) {
38029            if (ev.altKey) {
38030                ev.stopPropagation();
38031                GLO.UI.Form.beginProcessing($(this));
38032                document.location = GLO.Link.WebsiteDomain + 'fragment/staff/StaffHourList';
38033            }
38034        });
38035
38036        $('#wiz5-th-client-config').click( function(ev) {
38037            if (ev.altKey) {
38038                ev.stopPropagation();
38039                GLO.UI.Form.beginProcessing($(this));
38040                document.location = GLO.Link.WebsiteDomain + 'fragment/staff/ClientConfigList';
38041            }
38042        });
38043
38044        $('#wiz5-permission').click( function(ev) {
38045            if (ev.altKey) {
38046                ev.stopPropagation();
38047                GLO.UI.Form.beginProcessing($(this));
38048                document.location = GLO.Link.WebsiteDomain + 'fragment/staff/PermissionList?fullpage=1';
38049            }
38050        });
38051    }
38052    
38053    _constructor.openStaffColorSelector = function() {
38054    	var j = $('#color-selector');
38055    	var oj = new GLO.Popup.Custom(j);
38056        j = oj.getPopup();
38057        
38058        var aCal = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'pos\', this, event, true)" class="narrow-text" style="font-weight: bold; color: #139ad2;">Front Desk Calendar</a>';
38059        var aPos = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'pos\', this, event, true)" class="narrow-text" style="font-weight: bold; color: #139ad2;">P.O.S. Screen</a>';
38060        var htmHelp = '<p style="padding-top: 0; padding-left: 12px; padding-right: 6px; padding-bottom: 24px;">Color used on ' + aCal + ' Header + ' + aPos + '</p>';
38061        var htmUseDefault = '<div> <span cd="" class="" style="border: 1px outset black; color: black;"> Use Default Color </span> </div>';
38062        
38063        j.find('#color-selector-scroll').prepend(htmHelp + htmUseDefault);
38064        j.find('#color-selector-scroll>div>span').click(Wiz5.clickStaffColorSelector);
38065        
38066        var bcolor = $('#simplemodal-container').css('background-color');
38067        j.find('#color-selector h1').css({ "background-color": bcolor });
38068        
38069        var jfoot = j.find('.pop-buttons-parent');
38070        jfoot.find('.btnSave').remove();
38071        jfoot.find('.btnCancel').css({ "float": "none" }).find('a').text(SA.Resource.Close);
38072    }
38073    _constructor.clickStaffColorSelector = function() {
38074    	var j = $(this);
38075    	var color = j.css("background-color");
38076    	var colorValue = UTIL.replaceAll($.trim(color).replace('rgba(', '').replace('rgb(', '').replace(')', ''), ' ', '');
38077    	
38078    	if (UTIL.replaceAll(colorValue, ',', '') == 0) {
38079    		colorValue = '';
38080    	}
38081    	
38082    	var jmodal = $('#simplemodal-container');
38083    	jmodal.find('.btnSave').find('a').css({ "border": "3px solid Red" });
38084    	jmodal.find('#Color_Rgb_vc').val(colorValue);
38085    	
38086    	var jStaffHeader = jmodal.find('#pop-staff-profile-header');
38087    	jStaffHeader.attr('css_class_vc', j.attr('class'));
38088    	jStaffHeader.css({ "background-color": color });
38089    	
38090    	GLO.Popup.close();
38091    }
38092    
38093    _constructor.askResetHourManualAdjust = function(editSID, manualAdjustCount) {
38094    	if (manualAdjustCount > 0) {
38095			var msg1 = 'The start or end time was manually adjusted for ' + UTIL.pluralLabel(manualAdjustCount, 'day');
38096			var msg1b = '<small style="display: block;">(by dragging the start/end time up or down)</small>';
38097			var msg2 = 'Reset ' + UTIL.pluralLabel(manualAdjustCount, 'Day') + ' with Adjusted Start/End Time?';
38098			var htm = '<div id="pop-confirm-wiz-day-manual-reset" style="line-height: 1.4;"><p style="margin-bottom: 24px;">' + msg1 + msg1b + '</p><p>' + msg2 + '</p></div>';
38099			var fnReset = function() { Wiz5.saveResetHourManualAdjustment(editSID); };
38100			
38101			GLO.Popup.Confirm.open(htm, 'Reset Adjusted Start/End Times?', fnReset);
38102		}
38103    }
38104    
38105    _constructor.saveResetHourManualAdjustment = function(saveForStaff) {
38106    	var url = GLO.Link.WebsiteDomain + 'fragment/wizard/wiz5HoursManualAdjustReset?editstaff=' + saveForStaff;
38107        
38108        GLO.Popup.close($('#pop-confirm-wiz-day-manual-reset').closest('.glopop'));
38109        
38110        var jqxhr = $.ajax({ type: "GET", url: url })
38111    		.success(function(data, textStatus, jqXHR) {
38112            	var test = 123;
38113            })
38114            .error(function(jqXHR, textStatus, errorThrown) {
38115                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
38116            });
38117    }
38118    
38119    _constructor.changeDefaultScreenOnly = function(element) {
38120    	_constructor.changeDefaultScreen(element);
38121    }
38122    _constructor.changeDefaultScreen = function(element) {
38123    	var jpop = $('#wiz5-popupStaffConfig').closest('#simplemodal-container');
38124    	var jdefaultScreen = jpop.find('#Default_Screen_Type_cd');
38125    	var isDefaultScreenOnly = jpop.find('#Default_Screen_Only_fl').prop('checked');
38126    	
38127    	if (isDefaultScreenOnly && UTIL.isEmpty(jdefaultScreen.val())) {
38128    		var msg = '<p style="font-size: larger; font-weight: bold;">For this login, what screen would you like to use?</p>';
38129    		var msg2 = '<p>Please select the <b>Home Screen</b></p>'
38130    		var icon = '<span class="helpIcon2 sa-sprite" onclick="SA.Help.Profile.openHelpHomeScreen(this)" title="Can lock Limited Receptionist login to the home screen"></span>';
38131    		var htm = '<div id="pop-default-screen" style="text-align: center;">' + msg + msg2 + '<div>' + icon + '</div></div>';
38132    		
38133    		var onClosePopup = function() {
38134    			UI.highlight(jdefaultScreen);
38135    			jdefaultScreen.focus();
38136    		}
38137    		
38138    		GLO.Popup.Warning.open(htm, 'Home Screen Only', onClosePopup);
38139    	}
38140    }
38141    _constructor.changeRoleType = function(element, event) {
38142    	var newRole = UTIL.coalesceInt(element.value);
38143    	var jpop = $('#wiz5-popupStaffConfig');
38144    	var jHideClient = jpop.find('#wiz5-popupStatus-hide-client');
38145    	var jNoteAccess = jpop.find('#wiz5-popupStatus-client-note-access');
38146    	var jtrReportRole = jpop.find('#wiz5-popupStatus-role-report');
38147    	var jtrRequirePass = jpop.find('#wiz5-popupStatus-require-password');
38148    	var jtrRequireRole = jpop.find('#wiz5-popupStatus-require-role');
38149    	var jtrDefaultScreen = jpop.find('#wiz5-staff-default-screen');
38150    	var jtrDefaultScreenOnly = jpop.find('#wiz5-staff-default-screen-only').addClass('hide');
38151    	
38152    	if (GLO.Info.roleType > 219) {
38153    		if (newRole > 149) {
38154    			jNoteAccess.removeClass('hide');
38155    		} else {
38156    			jNoteAccess.addClass('hide');
38157    		}
38158    		
38159    		if (newRole > 169) {
38160    			jHideClient.removeClass('hide');
38161    		} else {
38162    			jHideClient.addClass('hide');
38163    		}
38164    	} else {
38165    		jHideClient.addClass('hide');
38166    		jNoteAccess.addClass('hide');
38167    	}
38168    	
38169    	if (newRole > 199) {
38170    		jtrRequirePass.removeClass('hide');
38171    		jtrRequireRole.removeClass('hide');
38172    		jtrDefaultScreen.removeClass('hide');
38173    		
38174    		if (newRole == 200) {
38175    			jtrDefaultScreen.find('td.default-screen-is-report').addClass('hide');
38176    			jtrDefaultScreenOnly.removeClass('hide');
38177    		} else {
38178    			jtrDefaultScreen.find('td.default-screen-is-report').removeClass('hide');
38179    		}
38180    	} else {
38181    		jtrRequirePass.addClass('hide');
38182    		jtrRequireRole.addClass('hide');
38183    		jtrDefaultScreen.addClass('hide');
38184    	}
38185    	
38186    	if (newRole > 200) {
38187    		jtrReportRole.removeClass('hide');
38188    	} else {
38189    		jtrReportRole.addClass('hide');
38190    	}
38191    }
38192    
38193    _constructor.changeConfirmOnCreate = function(element, event) {
38194    	if (!element.checked) {
38195    		var jupd = $('#wiz5-cc-confirm-row #Confirm_On_Update_fl');
38196    		
38197    		if (jupd.prop('checked')) {
38198    			jupd.prop('checked', false);
38199    		}
38200    	}
38201    }
38202    
38203    _constructor.changeConfirmOnUpdate = function(element, event) {
38204    	if (element.checked) {
38205    		var jcreated = $('#wiz5-cc-confirm-row #Send_Confirmation_Email_fl');
38206    		
38207    		if (!jcreated.prop('checked')) {
38208    			jcreated.prop('checked', true);
38209    		}
38210    	}
38211    }
38212    
38213    _constructor.staffCheckAll = function(checkBox, context) {
38214        context = context ? context : '#wiz5-stafflist tbody';
38215        var radioList = $(context + ' input:checkbox');
38216        var isChecked = $(checkBox).prop('checked');
38217        //window.setTimeout(function() { if (isChecked) $(checkBox).prop('checked', true); }, 1000);
38218
38219        radioList.each(function() {
38220            if (isChecked) {
38221                $(this).prop('checked', true);
38222            } else {
38223                $(this).prop('checked', false);
38224            }
38225        });
38226    }
38227
38228    _constructor.deleteStaff = function(isOverride) {
38229        if (!isOverride && GLO.Data.Staff.require_password_appointment_edit_fl) {
38230        	var fnSave = function() { Wiz5.deleteStaff(true); };
38231        	
38232        	WIZ.openRequireEditPassword(fnSave);
38233        	return;
38234        }
38235        
38236        var ojDel = $('#staffCheck:checked');
38237        var msgDelLink = '', delCount = ojDel.size();
38238
38239        if (delCount === 0) {
38240            GLO.Popup.Warning(SA.Resource.PleaseSelectPerson); 
38241        } else {
38242            var msg = delCount + ' ' + SA.Resource.People.toLowerCase();
38243            var id = ojDel.parent().parent().attr('id').substr(7);
38244            
38245            if (delCount === 1) { msg = ojDel.closest('tr').find('td').eq(1).text(); }
38246            
38247            if (id == GLO.Info.getStaffId()) {
38248                GLO.Popup.Warning(SA.Resource.YouCannotDeleteYourself); 
38249                return false;
38250            }
38251            
38252            if (_hasStaffParent(ojDel)) {
38253            	msgDelLink = '<div style="padding-top: 16px; padding-bottom: 24px;">'
38254            					+ '<input type="checkbox" id="Also_Delete_Linked_Staff_fl" style="width: 20p
38254x; height: 20px; margin-top: -4px; margin-right: 8px;"/>'
38255            					+ '<label for="Also_Delete_Linked_Staff_fl">Also Delete Linked Staff</label>'
38256            				+ '</div>';
38257            }
38258
38259            msg = '<div class="friendly-msg4"><h1 class="friendly-msg4">Confirm Delete Staff</h1><div><div>' + SA.Resource.ConfirmDelete + ' <b>' + msg + '</b>?</div>' + msgDelLink + '</div></div>';
38260            
38261            new GLO.Popup.Confirm(msg, function() {
38262                var delLinkedStaff = $('#Also_Delete_Linked_Staff_fl').prop('checked');
38263                var btnDel = $('.wiz-buttons .btnDelete');
38264                GLO.UI.Form.beginProcessing(btnDel);
38265                
38266                $('#staffCheck:checked').each(function() {
38267                    --delCount;
38268					var sid = $(this).parent().parent().attr('id').substr(7);
38269					
38270					_constructor.deleteStaffConfirmed(sid, delLinkedStaff, delCount);
38271					
38272					$(this).parent().parent().remove();
38273                });
38274            });
38275        }
38276    }
38277    
38278    _constructor.deleteStaffAsk = function(staffid, staffName) {
38279    	var htm = 'Are you sure you want to delete <b style="white-space: nowrap;">' + staffName + '</b>';
38280    	
38281    	var fnYes = function() {
38282    		var jbtns = $('#wiz5-popupStaffProfile #wiz1-popupNext');
38283    		jbtns.find('.btnSave').addClass('hide');
38284    		GLO.UI.Form.beginProcessing(jbtns.find('.btnDelete'));
38285    		
38286    		Wiz5.deleteStaffConfirmed(staffid, false, 0, true);
38287    	};
38288    	
38289    	GLO.Popup.Confirm.open(htm, 'Confirm Delete Staff', fnYes);
38290    }
38291    
38292    _constructor.deleteStaffConfirmed = function(staffid, delLinkedStaff, delCount, mustDeleteRow) {
38293    	var url = GLO.Link.Object.Provider.Ajax + 'DeleteStaff' + '?dt=' + UTIL.getDateString();
38294        
38295        var jqxhr = $.ajax({ type: "POST", url: url, data: { "Role_Type_cd": 0, "Staff_id": staffid, "Delete_Linked_Staff_fl": delLinkedStaff } })
38296        		.success(function(data, textStatus, jqXHR) {
38297                	if (UTIL.coalesceInt(delCount, 0) == 0) {
38298                		GLO.UI.Form.resetProcessing();
38299                		
38300                		if (mustDeleteRow) {
38301                			$.modal.close();
38302                			$('#wiz5-stafflist').find('#trStaff' + staffid).remove();
38303                		}
38304                	}
38305                })
38306                .error(function(jqXHR, textStatus, errorThrown) {
38307                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
38308                });
38309    }
38310    
38311    function _hasStaffParent(ojDel) {
38312    	if (!SA.Parent.canLinkStaff()) { return false; }
38313    	
38314    	for (var i=0; i < ojDel.length; i++) {
38315    		if (!UTIL.isEmpty(ojDel.eq(i).closest('tr').attr('staff_parent_id'))) {
38316    			return true;
38317    		}
38318    	}
38319    	
38320    	return false;
38321    }
38322    
38323    _constructor.openStatus = function(sid, tabNumber) {
38324        //var ajax_load = "<img class='loading' src='" + GLO.Link.WebsiteDomain + "_static/image/processing.gif' alt='loading...' />";
38325        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"});
38326        
38327        var loadUrl = GLO.Link.Object.Provider.Wiz5Config + '?dt=' + UTIL.getDateString();
38328        if (sid !== null) { loadUrl += '&sid=' + sid; }
38329        var pop = $('#wiz5-popupStatus');
38330
38331        pop.html(throbber).load(loadUrl, function() {
38332            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
38333            $('#simplemodal-container').css('padding', '0').find('.simplemodal-data').css('padding', '0');
38334            
38335            UI.setAccessKey('#wiz5-popupStatus', null, WIZ.popupSave);
38336            //$("#wiz5-popupStatus input:checkbox").change(UI.CrossOutCheckbox).change();
38337            
38338            if (GLO.Info.isAndroid) {
38339            	pop.find('#Email_Reminder_Day_sr').attr('type', 'number').attr('step', 'any');
38340            	pop.find('#Text_Reminder_Hr_sr').attr('type', 'number').attr('step', 'any');
38341            }
38342            
38343            pop.find('#Text_Reminder_fl').click(function() { UI.changeFocus(this, 'Text_Reminder_Hr_sr'); });
38344            pop.find('#Text2_Reminder_fl').click(function() { UI.changeFocus(this, 'Text2_Reminder_Hr_sr'); });
38345            pop.find('#Email_Reminder_fl').click(function() { UI.changeFocus(this, 'Email_Reminder_Day_sr'); });
38346            pop.find('#Allow_Neighbor_Within_Day_fl').click(function() { UI.changeFocus(this, 'Allow_Neighbor_Within_Day_sr'); });
38347            
38348            pop.find('#Text_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text_Reminder_fl'); }).change();
38349            pop.find('#Text2_Reminder_Hr_sr').change(function() { UI.markCheckbox(this, 'Text2_Reminder_fl'); }).change();
38350            pop.find('#Email_Reminder_Day_sr').change(function() { UI.markCheckbox(this, 'Email_Reminder_fl'); }).change();
38351            pop.find('#Allow_Neighbor_Within_Day_sr').change(function() { UI.markCheckbox(this, 'Allow_Neighbor_Within_Day_fl'); }).change();
38352            
38353            pop.find('#Email_Reminder_Day_sr').change();
38354            pop.find("input:checkbox").change(UI.CrossOutCheckbox).change();
38355            
38356            pop.find('form').attr('action', loadUrl);
38357            WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 5, null, data); }
38358
38359            var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text();
38360            if (UTIL.isEmpty(staffName)) { staffName = $('#staff-hour-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); }
38361            $('form#wiz5-form-clientConfig #wiz5-staffName').text(staffName);
38362            
38363            if (UTIL.isEmpty(staffName)) {
38364            	$('h2#wiz5-staffName').addClass('hide');			//.css({ "background-color": "transparent" });
38365            }
38366            
38367			pop.find('#Text_Reminder_Hr_sr').focus();
38368			
38369			if ($('#Provider_Has_Enabled_ReputationMgmt').val() === 'True') {
38370				$('#wiz5-cc-reputation-management-row').removeClass('hide');
38371			}
38372            
38373            pop.find('#Client_Access_cd1, #Client_Access_cd2, #Client_Access_cd3, #Client_Access_cd4').click(Wiz5.setClientAccess);
38374            _constructor.setClientAccess();
38375            _columnNumber = 5; _staffId = sid;
38376            
38377            if (GLO.Info.isMobile()) {
38378            	$('#simplemodal-container .modalCloseImg').addClass('hide');			//.attr("style", "top: 3px !important");
38379            	$('#simplemodal-container .simplemodal-wrap').css({ "border-bottom-left-radius": "4px", "border-bottom-right-radius": "4px" });
38380            	
38381            	if (GLO.Info.isIPhone) {
38382            		pop.find('.tblSlim').find('label').css({ "-webkit-text-size-adjust": "none" });		// "font-size": "12px", 
38383            	}
38384            } else {
38385            	$('#simplemodal-container').draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
38386            }
38387            
38388            UTIL.Validate.init(pop);
38389            UTIL.Validate.saveButton = '#simplemodal-container .btnSave a';
38390            $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved);
38391            $('#simplemodal-container').css({ "max-height": "760px" });
38392            
38393            _differentPackageOptions(pop);
38394            
38395            $.modal.update(pop.height() + 80);
38396            pop.closest('.simplemodal-wrap').css({ "background-color": "rgb(240,240,250)" });
38397            WIZ.addScrollBarsToSimpleModal();
38398            
38399            if (tabNumber == 2) { pop.find('#wizcc-tab-appt-message > a').click(); }
38400        });
38401
38402        pop.modal();
38403        _openStatusDimensions()
38404    }
38405	
38406	function _differentPackageOptions(pop) {
38407		if (!GLO.Provider.isPaidAccount(true)) {
38408            var price = SA.Upgrade.getPackagePriceNumber(GLO.Info.providerPackage);
38409            
38410            _addClientEmailUpgrade(pop, price);
38411            _addExistingClientUpgrade(pop, price);
38412        } else if (GLO.Info.roleType > 169) {
38413        	pop.find('#wiz-cc-allow-unconfirm-row, #wiz-cc-text-on-unconfirm-row').removeClass('hide');
38414        }
38415	}
38416	
38417	_constructor.displayStatusTab = function(tabElement, tabid) {
38418		var thisLI = $(tabElement).parent();
38419		var jtabControl = thisLI.closest('.tab-control');
38420		var j = jtabControl.parent();
38421		var jpop = $('#wiz5-popupStaffConfig');
38422		
38423		jtabControl.find('li.active-tab').removeClass('active-tab');
38424		j.find('.tab-body').addClass('hide');
38425		
38426		thisLI.addClass('active-tab');
38427		j.find('#' + tabid).removeClass('hide');
38428		
38429		_verifyStaffConfigPopupHeight(jpop);
38430	}
38431	
38432	function _addExistingClientUpgrade(pop, price) {
38433		//pop.find('#ccClient_Access_cd2 > td').css({ "border-radius": "40px", "z-index": "9", "background-color": "rgba(40,40,40,.8)", "color": "#62BECB" });
38434	}
38435	
38436	function _addClientEmailUpgrade(pop, price) {
38437		var msg = '<div class="block-msg">' + SA.Resource.UpgradeForOnly + ' $' + price + ' ' + SA.Resource.AutoSendEmail + '</div>';
38438        var btnUpgrade = '<div> <span class="btn btnAdd btnUpgrade"> <a onclick="SA.Upgrade.gotoUpgradePackage(this, \'send-reminders\', \'profile\')">' + SA.Resource.Upgrade + '</a> </span> </div>';
38439        var htmUpgrade = '<div class="block-container">' + msg + btnUpgrade + '</div>';
38440        
38441        var jmsg = pop.find('#client-config-message-to-clients').css({ "opacity": ".4" });
38442        jmsg.parent().css({ "position": "relative" }).prepend(htmUpgrade);
38443	}
38444	
38445	function _openStatusDimensions() {
38446		$('#simplemodal-container').css({ "margin-top": "10px" })
38447		
38448		if (GLO.Info.isMobile() && !GLO.Info.isLandscape() && innerWidth > 340) {
38449			$('#client-config-message-to-clients').css({ "margin": "0 10px" });
38450		}
38451		
38452		var w = 650;
38453		
38454		if (innerWidth < 400) {
38455			w = parseInt(innerWidth * .98);
38456		} else if (innerWidth < 550) {
38457			w = parseInt(innerWidth * .96);
38458		} else if (innerWidth < 660) {
38459			w = parseInt(innerWidth * .94);
38460		}
38461		
38462		GLO.Popup.resizeSimpleModal(w, 530, 450);
38463	}
38464	
38465	_constructor.openAddress = function(sid) {
38466		var uri = GLO.Link.WebsiteDomain + 'wizard2/StaffAddress?staff=' + sid;
38467		var ojProcessing = new GLO.Popup.Processing('Looking up staff address...');
38468		
38469		$.ajax({ type: "GET", url: uri, "cache": false })
38470			.success(function(data, textStatus, jqXHR) {
38471				ojProcessing.close();
38472				
38473				var jdata = $(data);
38474				var header = jdata.find('#staff-name-header').text();
38475				var htm = '<div id="pop-staff-address">' + data + '</div>';
38476				
38477				if (jdata.hasClass('warning')) {
38478					GLO.Popup.Warning.open(data, 'Staff Address');
38479					return;
38480				}
38481				
38482                var jpop = new GLO.Popup.Custom.openSimple(htm, header, Wiz5.saveAddress);
38483                var jform = jpop.find('#staff-address-form');
38484                
38485                //setup drop-down for state + country
38486                var stateCode = jform.attr('state_cc'), countryCode = jform.attr('country_cc');
38487                var stateDD = '<select id="Staff_State_cc" name="Staff_State_cc">' + $('#State_cc').html() + '</select>';
38488                var countryDD = '<select id="Staff_Country_Code_c2" name="Staff_Country_Code_c2">' + $('#Country_Code_c2').html() + '</select>';
38489                
38490                jform.find('#Staff_State_cc').replaceWith(stateDD);
38491                jform.find('#Staff_Country_Code_c2').replaceWith(countryDD);
38492                
38493                jform.find('#Staff_State_cc').find('option[value="' + stateCode + '"]').prop('selected', true);
38494                jform.find('#Staff_Country_Code_c2').find('option[value="' + countryCode + '"]').prop('selected', true);
38495			}).error(function(jqXHR, textStatus, errorThrown) { 
38496				GLO.UI.Form.resetProcessing();
38497	            GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
38498			});
38499	}
38500	_constructor.saveAddress = function() {
38501		var jpop = $('#pop-staff-address').closest('.glopop');
38502		var jform = jpop.find('#staff-address-form');					//jform.serialize()
38503		
38504		var street = jform.find('#Staff_Street1_vc').val();
38505		var city = jform.find('#Staff_City_vc').val();
38506		var state = jform.find('#Staff_State_cc').val();
38507		var zip = jform.find('#Staff_Zip_vc').val();
38508		var country = jform.find('#Staff_Country_Code_c2').val();
38509		var max = jform.find('#Outcall_Mile_Max_sr').val();
38510		
38511		var jd = { "street": UTIL.htmlEncode2(street), "city": UTIL.htmlEncode2(city), "state": state, "zip": UTIL.htmlEncode2(zip), "country": country, "max": max };
38512		var staffId = jform.attr('staff_id');
38513		var uri = GLO.Link.WebsiteDomain + 'wizard2/StaffAddress?staff=' + staffId;
38514		
38515		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
38516		
38517		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
38518            	.success(function(data, textStatus, jqXHR) {
38519            		GLO.UI.Form.resetProcessing();
38520            		
38521            		if ($(data).hasClass('success')) {
38522            			GLO.Popup.closeIfExist(jpop);
38523            			GLO.Popup.Success.open(data, 'Address Updated');
38524            			
38525		                setTimeout(function() {
38526		                	document.location.reload();
38527		            	}, 1500);
38528            		} else {
38529	                	GLO.Popup.Warning.open(data, 'Edit Staff Address');
38530	                }
38531            	})
38532	        .error(function(jqXHR, textStatus, errorThrown) {
38533	            GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
38534	        });
38535	}
38536	
38537    _constructor.openHours = function(sid) {
38538        if (UTIL.isEmpty(sid)) { sid = GLO.Info.getStaffId(); }
38539
38540        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "200px auto"});
38541        var loadUrl = GLO.Link.Object.Provider.Wiz5Hours + '?dt=' + UTIL.getDateString();
38542        
38543        if (sid !== null) { loadUrl += '&sid=' + sid; }
38544        var pop = $('#wiz5-popupHours');
38545
38546        pop.html(throbber).load(loadUrl, function() {
38547            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
38548            
38549            if (GLO.Data.provider.role_change_hours_cd > GLO.Info.roleType) {
38550            	pop.find('input, select').prop('disabled', true);
38551            }
38552            
38553            UTIL.DefaultText.init($('#wizHours'));
38554            
38555            var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text();
38556            if (UTIL.isEmpty(staffName)) { staffName = $('#staff-hour-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); }
38557            $('#wiz5-staffName').text(staffName);
38558            
38559            if (UTIL.isEmpty(staffName)) {
38560            	$('#wiz5-staffName').css({ "background-color": "transparent" });
38561            }
38562            
38563            UI.setAccessKey('#wizHours', null, WIZ.popupSave);
38564            pop.find('form').attr('action', loadUrl).attr('edit_staff_id', sid);
38565            WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 4, null, data); }
38566
38567            pop.find('#Start_tm1').focus();
38568            _initOpenHoursFirstAvailable(pop);
38569            
38570            //pop.off('click', 'button.positive');
38571            //$('#simplemodal-container').on('click', 'button.positive', function() { Wiz5.processingCellUpdate(sid, 4); });
38572            //pop.find('button.positive').click(function() { Wiz5.processingCellUpdate(sid, 4); });
38573            _columnNumber = 4; _staffId = sid;
38574            
38575            GLO.Hours.initAdjustedDays(sid);
38576            
38577            if (GLO.Info.isMobile()) {
38578            	$('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important");
38579            	
38580            	if (innerWidth >= 400) {
38581            		$.modal.update(540, null);
38582            	}
38583            } else {
38584            	$('#simplemodal-container').css({ "padding": 0 }).draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
38585            	
38586            	if (innerWidth < 700) {
38587            		$.modal.update(null, innerWidth - 20);
38588            	}
38589            }
38590            
38591            var jhelp = pop.find('.help-description');
38592            
38593            if (jhelp.length > 0) {
38594            	var h = pop.height() + jhelp.height();			//need to add height to popup so buttons do not overlap help description
38595            } else {
38596            	var h = pop.height() + 60;
38597            }
38598            
38599            $.modal.update(h, null);
38600            
38601            UTIL.Validate.saveButton = '#simplemodal-container .btnSave a';
38602            $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved);
38603            
38604            if (GLO.Info.isMobile() && (WIZ.page === 1 || WIZ.page === 5) ) {
38605            	if (GLO.Info.isIPhone) {
38606					var scale = 'width=320, minimum-scale=.72, maximum-scale=.8, initial-scale=.8';
38607				} else {
38608					var scale = 'width=440, minimum-scale=.8, maximum-scale=.8, initial-scale=.8';
38609				}
38610            	
38611            	//GLO.Mobile.updateViewPort(scale, undefined, 'STAFF HOURS');
38612            }
38613            
38614            WIZ.addScrollBarsToSimpleModal();
38615        });
38616        
38617        pop.modal();
38618        _openHoursDimensions(pop)
38619    }
38620    
38621    function _initOpenHoursFirstAvailable(jpop) {
38622    	var jfa = jpop.find('#first-available-hours-help');
38623    	
38624    	if (jfa.length) {
38625    		if (SA.Data.resourceJson && SA.Data.resourceJson.length) {
38626    			var msg = 'The hours set above change the regular hours for your resources like: ';
38627    			var resourceList = '';
38628    			
38629    			for (var i=0; i < SA.Data.resourceJson.length; i++) {
38630    				if (i > 0) { resourceList += ', '; }
38631    				
38632    				resourceList += SA.Data.resourceJson[i].name;
38633    			}
38634    			
38635    			jfa.find('#first-avilable-hour-change-help').html(msg + resourceList);
38636    		}
38637    	}
38638    }
38639    
38640    function _openHoursDimensions(pop) {
38641    	var w = 420, h = 510;				//h = 510
38642    	
38643    	if (GLO.Info.isMobile()) {
38644        	h = 460;
38645        	pop.closest('#simplemodal-container').css({ "top": "10px", "padding": "6px" });
38646        	
38647        	if (GLO.Info.isLandscape()) {
38648        		$.modal.update(h, 555);
38649        	} else if (innerWidth < 330) {
38650        		$.modal.update(h, 315);
38651        	} else {
38652        		$.modal.update(h, (innerWidth * .96));
38653        	}
38654        } else {
38655        	$.modal.update(h, 650);
38656        }
38657	}
38658	
38659    _constructor.openStaffConfig = function(sid, isSalonAdmin) {       //isSalonAdmin == '1' if the currently logged in user is a salon admin or manager.
38660        if (UTIL.isEmpty(sid)) { sid = GLO.Info.getStaffId(); }
38661
38662        //var ajax_load = "<img class='loading' src='" + GLO.Link.WebsiteDomain + "_static/image/processing.gif' alt='loading...' />";
38663        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"});
38664
38665        var loadUrl = GLO.Link.Object.Provider.Wiz5StaffConfig + '?dt=' + UTIL.getDateString();
38666        if (sid !== null) { loadUrl += '&sid=' + sid; }
38667        var pop = $('#wiz5-popupStaffConfig');
38668
38669        pop.html(throbber).load(loadUrl, function() {
38670            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) {
38671            	return;
38672            }
38673            
38674            UI.setAccessKey('#wiz5-popupStaffConfig', null, WIZ.popupSave);
38675            
38676            if (GLO.Info.isAndroid) {
38677            	pop.find('#Text_Notify_Hr_sr').change().attr('type', 'number');
38678            	pop.find('#Email_Notify_Day_sr').attr('type', 'number');
38679            	pop.find('#Service_Commission_pct').attr('type', 'number').attr('step', 'any');
38680            	pop.find('#Hourly_Wage_mn').attr('type', 'number').attr('step', 'any');
38681            }
38682            
38683            pop.find('#Text_Notify_Hr_sr').change();
38684            pop.find('#Email_Notify_Day_sr').change();
38685
38686            pop.find("input:checkbox").change(UI.CrossOutCheckbox).change();
38687            pop.find('form').attr('action', loadUrl);
38688            WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 2, null, data); }
38689
38690            var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text();
38691            if (UTIL.isEmpty(staffName)) { staffName = $('#staff-notification-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); }
38692            
38693            if (GLO.Info.roleType > 200) {
38694	            if (UTIL.isEmpty(staffName)) {      //is on staff member (ie. role type = staff) profile.
38695	                if (sid != GLO.Info.StaffId) {
38696	                	$('#notification-sent-to').text('Staff');					//$('#wiz5-myNotifications legend span.quiet7').addClass('hide');
38697	                }
38698	                
38699	                $('#wiz5-staffName').css({ "background-color": "transparent" });
38700	                
38701	                var j = $('#wiz5-popup-staff-config-tbl1');
38702	                
38703	                j.find('tr#wiz5-history').remove();
38704	                j.find('tr#wiz5-popupStatus-inactive').remove();
38705	                j.find('tr#wiz5-popupStatus-role').remove();
38706	            } else {
38707	                $('#wiz5-staffName').text(staffName);
38708	                
38709	                if (innerWidth < 600) {
38710		            	var maxLen = parseInt((innerWidth * 2)/100);
38711		            	staffName = UTIL.maxString(staffName, maxLen, true);
38712		            }
38713		            
38714		            $('#notification-sent-to').text(staffName);
38715	            }
38716            }
38717
38718            if (GLO.Info.providerPackage == 1) {
38719                pop.find('#wiz5-popupStatus-staff-alert').remove();
38720            } else if (GLO.Info.providerPackage == 20) {
38721                pop.find('#wiz5-popupStatus-staff-alert').find('select, input').prop('disabled', 'disabled');
38722            }
38723            
38724            _initHourlyWageField(sid);
38725            _initCommission(pop);
38726            _initFirstAvailable_StaffConfig(pop, sid);
38727            _initStaffConfigRoleReport(pop);
38728            _initStaffConfigTab(pop);
38729
38730            //pop.off('click', 'button.positive');
38731            //pop.on('click', '#simplemodal-container button.positive', function() { Wiz5.processingCellUpdate(sid, 2); });
38732            _columnNumber = 2; _staffId = sid;
38733            $('#simplemodal-container').draggable({ "handle": "h2" }).css({ "padding": 0 }).find('h2').css({ "cursor": "move" });
38734            
38735            if (GLO.Info.isMobile()) {
38736            	if (innerWidth < 330) {
38737            		$('#simplemodal-container').css({ "width": "315px", "height": "auto", "padding": "0" });
38738            	}
38739
38740            	
38741            	var jlbl = pop.find('#Email_Notify_fl-label1');
38742            	jlbl.text( jlbl.text().replace(SA.Resource.WhenA + ' ', '') );
38743            	
38744            	jlbl = pop.find('#Text_Notify_fl-label1');
38745            	jlbl.text( jlbl.text().replace(SA.Resource.WhenA + ' ', '') );
38746            	
38747            	$('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important");
38748            	
38749            	if (GLO.Info.isIPhone) {
38750            		pop.find('.tblSlim').find('label').css({ "-webkit-text-size-adjust": "none" });		// "font-size": "12px", 
38751            	}
38752            } else if (innerWidth < 800) {
38753            	var jmodal = $('#simplemodal-container').css({ "width": (innerWidth - 40) + "px", "padding": "0" });			//, "height": "auto"
38754            	jmodal.find('.hidePhone').addClass('hide');
38755            	jmodal.find('.displayPhoneOnly').removeClass('displayPhoneOnly');
38756
38757				$.modal.update(null, null);
38758            }
38759            
38760            if (WIZ.page == 1 && (GLO.Info.isIPhone || GLO.Info.isIPad)) {				// && GLO.Info.isIosApp
38761				$('#wiz5-popupStatus-appnotification-flag').removeClass("hide");
38762				$('#wiz5-popupStatus-appnotification-status-flag').addClass("hide");
38763				SA.App.checkPushNotificationEnabled();
38764			} else {
38765				//check if push notification enabled on any device for that staff
38766				$('#wiz5-popupStatus-appnotification-flag').addClass("hide");
38767				$('#wiz5-popupStatus-appnotification-status-flag').removeClass("hide");
38768				//IsPushNotificationEnabled
38769				var uri = GLO.Link.WebsiteDomain + 'message/IsStaffPushNotificationEnabled?sid=' + sid;
38770    	
38771				$.ajax({ type: "GET", url: uri, "cache": false })
38772					.success(function(data, textStatus, jqXHR) {
38773						if (data.length > 1 && data == 'ON') {
38774							$('#wiz5-popupStatus-appnotification-status-flag').html('<span style="font-size:medium;color:#000;">App Notifications:&nbsp;<b>ON</b></span>');
38775						}
38776						else {
38777							$('#wiz5-popupStatus-appnotification-status-flag').html('<span style="font-size:medium;color:#000;">App Notifications:&nbsp;<b>OFF</b></span>');
38778						}
38779					}).error(function(jqXHR, textStatus, errorThrown) { 
38780						$('#wiz5-popupStatus-appnotification-status-flag').html('<span style="font-size:medium;color:#000;">App Notifications:&nbsp;<b>OFF</b></span>');
38781					});
38782			}
38783            
38784            UTIL.Validate.init(pop);
38785            UTIL.Validate.saveButton = '#simplemodal-container .btnSave a';
38786            $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved);
38787            pop.find('input, select').change(function() { $('#simplemodal-container').find('.btnSave a').css({ "border": "3px solid Red" }); });
38788            
38789            if ($('#simplemodal-container').outerHeight() < $('#wiz5-popupStaffConfig').outerHeight()) {
38790            	var h = $('#wiz5-popupStaffConfig').outerHeight() + 10;
38791            	$.modal.update(h, null);
38792            }
38793            
38794            _addMyAlertsUpgrade(pop)
38795            _initFinishStaffConfig(pop);
38796            WIZ.addScrollBarsToSimpleModal();
38797        });
38798
38799        pop.modal();
38800        _initPopupHeight(isSalonAdmin);
38801    }
38802    function _initFinishStaffConfig(jpop) {
38803    	var jrole = jpop.find('#Role_Type_cd');
38804    	
38805    	if (GLO.Info.providerPackage === 1) {
38806    		jpop.find('#wiz-alert-role-tabs').remove();
38807    	} else if (jrole.length) {
38808    		_constructor.changeRoleType(jrole[0]);
38809    	}
38810    }
38811    function _initStaffConfigRoleReport(jpop) {
38812    	var tr = $('#wiz5-popupStatus-role-report');
38813    	
38814    	if (GLO.Info.roleType > 229) {
38815    		if (jpop.find('#Role_Type_cd').val() > 200) {
38816    			tr.removeClass('hide');
38817    		}
38818    	} else {
38819    		tr.addClass('hide');
38820    	}
38821    }
38822	function _initStaffConfigTab(jpop) {
38823		if (jpop.find('#Role_Type_cd').val() > 199) {
38824			jpop.find('#wiz-tab-role > a').click();
38825			_verifyStaffConfigPopupHeight(jpop);
38826		} else {
38827			jpop.find('#Email_Notify_Day_sr').focus();
38828			var contentHeight = jpop.find('#wiz5-form-staffConfig').height();
38829			var buttonHeight = 100;			//= height for buttons at bottom + App Notifications On/Off (which has not loaded yet)
38830			
38831			if (contentHeight + buttonHeight > jpop.height()) {
38832				$.modal.update(contentHeight + buttonHeight, null);
38833			}
38834		}
38835	}
38836	function _verifyStaffConfigPopupHeight(jpop) {
38837		var popupHeight = jpop.height();
38838		var tabHeaderHeight = jpop.find('#wiz5-staffName').height() + jpop.find('#wiz-alert-role-tabs').height();
38839		var tabBodyHeight = jpop.find('#wiz5-popup-staff-config-tbl1').height();
38840		var btnFooterHeight = jpop.find('#wiz5-popupStatus-buttons').height();
38841		
38842		if (tabHeaderHeight + tabBodyHeight + btnFooterHeight + 20 > popupHeight) {
38843			jpop.height(tabHeaderHeight + tabBodyHeight + btnFooterHeight + 32);
38844			jpop.closest('#simplemodal-container').css({ "height": "" });
38845		}
38846	}
38847	function _initFirstAvailable_StaffConfig(jpop, sid) {
38848		if (!UserPortal.isFirstAvailable(sid)) { return false; }
38849		//if (!UTIL.parseBool(jpop.find('#Is_First_Available_fl').val())) { return false; }
38850		
38851		jpop.find('#wiz5-popupStatus-hide-client, #wiz5-popupStatus-role, #wiz5-popupStatus-login, #wiz5-popupStatus-require-password, #wiz5-popupStatus-client-note-access').remove();
38852		jpop.find('#wiz5-popupStatus-commission, #wiz5-popupStatus-hourly-wage-row').remove();
38853		jpop.find('#wiz-tab-role').addClass('hideX');
38854		
38855		return true;
38856	}
38857	
38858	function _addMyAlertsUpgrade(pop) {
38859		if (GLO.Provider.isPaidAccount(true) && GLO.Info.providerPackage !== 4) { return; }
38860		var price = SA.Upgrade.getPackagePriceNumber(GLO.Info.providerPackage);
38861		
38862		var msg = '<div class="block-msg">' + SA.Resource.Upgrade + ' ' + SA.Resource.AutoReceiveNotifications + '</div>';
38863        var btnUpgrade = '<div> <span class="btn btnAdd btnUpgrade"> <a onclick="SA.Upgrade.gotoUpgradePackage(this, \'send-reminders\', \'profile\')">' + SA.Resource.Upgrade + '</a> </span> </div>';
38864        var htmUpgrade = '<div class="block-container">' + msg + btnUpgrade + '</div>';
38865        
38866        var jmsg = pop.find('#wiz5-myNotifications').css({ "opacity": ".8" });
38867        jmsg.css({ "position": "relative" }).prepend(htmUpgrade);
38868        
38869        pop.find('#wiz5-popupStatus-commission, .helpIcon2, .btnSave').remove();
38870        
38871        var jbtns = pop.find('#wiz5-popup-staff-config-tbl1').css({ "position": "relative", "width": "100%", "max-width": "600px", "margin-top": "12px", "opacity": ".8" });
38872        jbtns.find('tr td:first-child').css({ "padding-top": "8px", "padding-bottom": "8px" });
38873        
38874        var btnCancel = jbtns.find('.btnCancel').css({ "float": "none", "width": "60px", "margin-right": "0", "text-align": "center", "letter-spacing": "1px", "font-size": "14px" });
38875        btnCancel.find('>a').text(SA.Resource.Close);
38876        btnCancel.closest('td').css({ "padding-top": "60px", "text-align": "center" });
38877        
38878        var a2 = '<a style="color: inherit;" href="/hello/SecurityRole">assign different security roles to each staff member</a>';
38879        var msg2 = '<div class="block-msg">' + SA.Resource.Upgrade + ' to the gold package to enable clock-in/out and for the ability to ' + a2 + '</div>';
38880        var btnUpgrade2 = '';		//'<div> <span class="btn btnAdd btnUpgrade"> <a onclick="SA.Upgrade.gotoUpgradePackage(this, \'staff roles\', \'profile\')">' + SA.Resource.Upgrade + '</a> </span> </div>';
38881        var htmUpgrade2 = '<div class="block-container" style="max-height: ' + (jbtns.height() - 40) + 'px;">' + msg2 + btnUpgrade2 + '</div>';
38882        
38883        jbtns.prepend(htmUpgrade2);
38884	}
38885	
38886	function _initPopupHeight(isSalonAdmin) {
38887		var w = 780;
38888        if (GLO.Info.isMobile()) { w = 555; }
38889        
38890        if (UTIL.parseBool(isSalonAdmin)) {
38891            if (GLO.Info.isMobile()) {
38892            	var h = 500;
38893            } else {
38894            	var h = 550;
38895            }
38896        } else {
38897            var h = 320;
38898        }
38899        
38900        GLO.Popup.resizeSimpleModal(w, h);				//$.modal.update(h, w);
38901	}
38902	
38903	function _initCommission(jpop) {
38904		var cnt = UTIL.coalesceInt(jpop.find('#Service_Count_sr').val(), 0);
38905		
38906		if (GLO.Info.providerPackage === 1) {
38907			jpop.find('tr#wiz5-popupStatus-commission').addClass('hide2')
38908		} else if (GLO.Info.roleType < 200) {
38909			var jc = $('#wiz5-popup-staff-config-tbl1');
38910			jc.find('#wiz5-set-commission-by-service').addClass('hide').removeAttr('onclick').removeAttr('href').css({ "border-bottom": "none" });
38911			var c = jc.find('#Service_Commission_pct').val();
38912			
38913			if (UTIL.coalesceMoney(c) > 0) {
38914				jc.find('#wiz5-popupStatus-commission').find('b').text(c + '%');
38915			}
38916			
38917			jc.find('#Service_Commission_pct').addClass('hide');
38918		} else if (GLO.Info.roleType < 220) {
38919			jpop.find('#Service_Commission_pct').click(GLO.Provider.Commission.canEditStaffCommission).prop('readonly', true);
38920		}
38921		
38922		if (cnt === 0) {
38923			$('#wiz5-set-commission-by-service').remove();
38924			return;
38925		}
38926		
38927		var defaultCommission = UTIL.coalesceFloat(jpop.find('#Service_Commission_pct').val(), 0);
38928		var minCommission = UTIL.coalesceFloat(jpop.find('#Min_Service_Commission_pct').val(), 0);
38929		var maxCommission = UTIL.coalesceFloat(jpop.find('#Max_Service_Commission_pct').val(), 0);
38930		
38931		if (minCommission == 0 && maxCommission == 0) { return; }
38932		if (maxCommission == defaultCommission && (minCommission == 0 || minCommission == defaultCommission) ) { return; }
38933		
38934		if (minCommission == maxCommission && UTIL.coalesceFloat(defaultCommission, 0) == 0) {
38935			jpop.find('#Service_Commission_pct').val(minCommission);
38936			return;
38937		}
38938		
38939		if (UTIL.coalesceInt(jpop.find('#Use_Default_Commission_Count_sr').val()) > 0) {
38940			if (minCommission > 0 && minCommission > defaultCommission) {
38941				minCommission = defaultCommission;
38942			}
38943			
38944			if (maxCommission < defaultCommission) {
38945				maxCommission = defaultCommission;
38946			}
38947		}
38948		
38949		var crange = String(minCommission).replace('.00', '') + ' - ' + String(maxCommission).replace('.00', '') + '%';
38950		
38951		if (!GLO.Info.isMobile() && GLO.Info.roleType > 210) { crange += ' (edit)'; }
38952		
38953		$('#wiz5-set-commission-by-service').removeClass('hide').text(crange).css({ "margin": "inherit", "letter-spacing": "1px" });
38954		$('#wiz5-popupStatus-commission').find('td').css({ "padding-bottom": "20px" }).find('b, #Service_Commission_pct').addClass('hide');
38955	}
38956	
38957	function _initHourlyWageField(sid) {
38958		//if (GLO.Info.roleType < 220 && GLO.Info.StaffId != sid) { return; }
38959        
38960        if (_displayHourlyWageField(sid)) {
38961        	var tr = $('#wiz5-popupStatus-hourly-wage-row').removeClass('hide');
38962        	
38963        	if (GLO.Info.roleType > 219) {
38964        		var wageSummary, minWage = tr.find('#Min_Hourly_mn').val(), maxWage = tr.find('#Max_Hourly_mn').val();
38965        		
38966        		if (minWage != maxWage) {
38967        			wageSummary = UTIL.displayMoney(minWage) + ' - ' + UTIL.displayMoney(maxWage);
38968        		} else {
38969        			wageSummary = UTIL.coalesceString(UTIL.displayMoney(UTIL.coalesceMoney(maxWage, minWage)), 'none');
38970        		}
38971        		
38972        		wageSummary = '<a onclick="GLO.Provider.Commission.openEditWage(this)">' + wageSummary + '</a>';
38973        	} else {
38974        		var wageSummary, minWage = tr.find('#Min_Clock_mn').val(), maxWage = tr.find('#Max_Clock_mn').val();
38975        		
38976        		if (minWage != maxWage) {
38977        			wageSummary = UTIL.displayMoney(minWage) + ' - ' + UTIL.displayMoney(maxWage);
38978        		} else {
38979        			wageSummary = UTIL.displayMoney(UTIL.coalesceMoney(maxWage, minWage));
38980        		}
38981        		
38982        		if (UTIL.isEmpty(wageSummary)) {
38983        			tr.remove();
38984        		}
38985        	}
38986        	
38987        	tr.find('#wiz5-hourly-row').html(wageSummary);
38988        	
38989        	var h = $('#wiz5-popupStaffConfig').closest('#simplemodal-container').height() + 30;
38990        	$.modal.update(h, null);
38991        }
38992	}
38993	
38994	function _displayHourlyWageField(sid) {
38995		if (GLO.Data.provider.isCommissionBiz) { return true; }
38996		
38997		var sids = UserPortal.getStaffWhoDoInternalService();
38998        
38999    	if (sids.length > 0) {
39000    		if (sids.has(sid)) {						//= current user performs employee-service.
39001    			return true;
39002    		}
39003    			
39004    		var j = $('#ServiceGroupOptionsClone option');
39005    		var dsg, i = 0, hasClientSvc = false;
39006    		
39007    		if (UTIL.isEmpty(j.eq(0).attr('default_service_group_id'))) { ++i; }		//=first option is blank.
39008    		
39009    		for (; i < j.length; i++) {
39010    			dsg = j.eq(i).attr('default_service_group_id');
39011    			
39012    			if (dsg != "1009" && dsg != '9') {
39013    				if (j.eq(i).attr('staff_ids').split(',').has(sid)) {
39014    					hasClientSvc = true;
39015    				}
39016    			}
39017    		}
39018    		
39019    		if (!hasClientSvc) { return true; }
39020    	}
39021    	
39022    	var jStaffServiceCell = $('#wiz5-stafflist').find('#trStaff' + sid + ' .wiz5-column-staff-service .wiz5-updated-cell');		//= an imperfect way to see if on wiz5 and just updated services (may have added staff to employee-service but wont yet be added to '#ServiceGroupOptionsClone').
39023    	if (jStaffServiceCell.length === 1) { return true; }
39023																		//toDo: (this is a quick fix) Should do this check on the server when open staff config.
39024    	
39025    	//if (GLO.Data.provider.isCommissionBiz) { return true; }
39026    	return false;
39027	}
39028	
39029	_constructor.openBio = function(url, me, event) {
39030		var fn = function() { GLO.Uri.gotoUri(url, me, event, true); };
39031		
39032		if (GLO.Data && GLO.Data.Staff.require_password_appointment_edit_fl) {
39033			WIZ.openRequireEditPassword(fn);
39034		} else {
39035			fn();
39036		}
39037	}
39038	_constructor.openBioSimple = function(me, event) {
39039		var jpop = $('#wiz5-popupStatus').closest('#simplemodal-container');
39040		var staffId = jpop.find('#Staff_id').val();
39041		var url = GLO.Data.provider.urikey + '/About/edit?staff=' + staffId + '&helloback=profile';
39042		
39043		_constructor.openBio(url, me, event);
39044	}
39045	
39046	function _ifFirstAvailableDoesNotApply(element, msg) {
39047		var tr = $(element).closest('tr');
39048		
39049		if (tr.attr('is_fa') === '1') {
39050			msg += ' does not apply to First Available';
39051			new GLO.Popup.Info('<div><h1 class="friendly-msg">First Available</h1><div class="friendly-msg2" style="margin-bottom: 12px;">' + msg + '</div></div>');
39052			
39053			return true;
39054		} else {
39055			return false;
39056		}
39057	}
39058	
39059	_constructor.openPermission = function(element, sid) {
39060        if (_ifFirstAvailableDoesNotApply(element, 'Inventory Permissions')) { return; }
39061        
39062        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "200px auto"});
39063        var pop = $('#wiz5-popupPermission');
39064
39065        var loadUrl = GLO.Link.WebsiteDomain + 'fragment/wizard/wiz5Permission?dt=' + UTIL.getDateString();
39066        
39067        if (UTIL.isEmpty(sid)) { sid = GLO.Info.getStaffId(); }
39068        if (sid !== null) { loadUrl += '&sid=' + sid; }
39069        
39070        pop.html(throbber).load(loadUrl, function() {
39071            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
39072            UTIL.DefaultText.init($('#wizPermissions'));
39073            
39074            var staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text();
39075            if (UTIL.isEmpty(staffName)) { staffName = $('#staff-hour-list').find('#trStaff' + sid + ' .report-column-staff > a').text(); }
39076            $('#wiz5-staffName').text(staffName);
39077            
39078            if (UTIL.isEmpty(staffName)) {
39079            	$('#wiz5-staffName').css({ "background-color": "transparent" });
39080            }
39081            
39082            UI.setAccessKey('#wizPermission', null, WIZ.popupSave);
39083            pop.find('form').attr('action', loadUrl);
39084            
39085            WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 6, null, data); }
39086            _columnNumber = 6; _staffId = sid;
39087
39088            $('#simplemodal-container').css({ "padding": "0" }).draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
39089            
39090            UTIL.Validate.saveButton = '#simplemodal-container .btnSave a';
39091            $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved);
39092            
39093            WIZ.addScrollBarsToSimpleModal();
39094        });
39095        
39096        pop.modal();
39097        
39098        if (GLO.Info.isMobile()) {
39099        	$('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important");
39100        	$.modal.update(700, (innerWidth * .98) );
39101        } else if (innerWidth > 700) {
39102        	$.modal.update(700, 690);
39103        } else {
39104        	$.modal.update(700, (innerWidth * .98) );
39105        }
39106    }
39107    
39108    function _processForNonWizardPage() {
39109    	var j = $('#commission-by-staff-service');
39110    	
39111    	if (j.length > 0) {
39112    		var jpop = $('#simplemodal-container').css({ "padding": "0" });
39113    		jpop.find('.simplemodal-data').css({ "padding": "0" });
39114    		
39115    		var sname = UTIL.cleanString(j.find('h2').attr('staff_name_vc'));
39116    		
39117    		setTimeout(function() {										//= have to reset later so not overridden.
39118    			WIZ.Popup.onSave = function() {
39119    				new GLO.Popup.Processing('Updating Services for ' + sname);
39120    				location.reload();
39121    			}
39122    		}, 1500);
39123    		
39124    		return sname;
39125    	} else {
39126    		return '';
39127    	}
39128    }
39129    
39130    _constructor.openCopyStaffService = function(changeSid, changeSname) {
39131    	$.modal.close();
39132        
39133        var ojProcessing = new GLO.Popup.Processing('Opening Staff List...');
39134        var uri = GLO.Link.Object.Provider.Ajax + 'StaffModelList?ignore-staff=' + changeSid;
39135
39136        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false })
39137            .success(function(data, textStatus, jqXHR) {
39138                ojProcessing.close();
39139                
39140                var h1 = 'Copy Staff Service Setup';
39141                var msg = '<p style="margin: 0 8px;">Select Staff to Copy: Service Length, Prices, Commission, and Goals to ' + changeSname + '</p>';
39142                var htm = '<div id="pop-copy-staff-list" change_staff_id="' + changeSid + '" change_staff_vc="' + changeSname + '">' + msg + data + '</div>';
39143                var jpop = new GLO.Popup.Custom.openSimple(htm, h1);
39144                
39145                GLO.Popup.Custom.singleButton(jpop);
39146                jpop.find('input[type="radio"]').change(Wiz5.saveCopyStaffService);
39147            });		//.error(function(jqXHR, textStatus, errorThrown) { });
39148    }
39149    _constructor.saveCopyStaffService = function() {
39150    	var jmsg = $('#pop-copy-staff-list');
39151    	var jpop = jmsg.closest('.glopop');
39152    	var changeSid = jmsg.attr('change_staff_id');
39153    	var changeStaffName = jmsg.attr('change_staff_vc');
39154    	
39155    	var jradio = $(this);
39156    	var copySid = jradio.closest('li').attr('staff_id');
39157    	
39158    	//var changeStaffName = UserPortal.getStaffName(changeSid);
39159    	var copyStaffName = jmsg.find('label[for="model-staff' + copySid + '"]').find('b').text();
39160    	
39161    	var htmArrow = ' &#10140; ';
39162    	var msg1 = '<p>Copy Service Setup from ' + copyStaffName + '?</p>';
39163    	var msg2 = '<p>' + copyStaffName + htmArrow + changeStaffName + '</p>';
39164    	var htm = '<div id="pop-confirm-copy-staff">' + msg1 + msg2 + '</div>';
39165    	
39166    	var fnYes = function() {
39167    		Wiz5.saveCopyStaffServiceConfirmed(copySid, changeSid);
39168    	}
39169    	var fnNo = function() {
39170    		jradio.prop('checked', false);
39171    		GLO.UI.Form.resetProcessing();
39172    	}
39173    	
39174    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
39175    	GLO.Popup.Confirm.open(htm, 'Confirm Copy Staff', fnYes, fnNo);
39176    }
39177    _constructor.saveCopyStaffServiceConfirmed = function(copySid, changeSid) {
39178    	var jpop1 = $('#pop-confirm-copy-staff').closest('.glopop');
39179    	var jpop2 = $('#pop-copy-staff-list').closest('.glopop');
39180    	
39181    	GLO.Popup.close(jpop2);
39182    	
39183    	jpop1.find('.btnNo').addClass('hide');
39184    	GLO.UI.Form.beginProcessing(jpop1.find('.btnYes'));
39185    	
39186    	var uri = GLO.Link.Object.Provider.Ajax + 'StaffUpdateFromModel?copystaff=' + copySid + '&changestaff=' + changeSid;
39187    	
39188        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false })
39189            .success(function(data, textStatus, jqXHR) {
39190                GLO.Popup.close(jpop1);
39191                GLO.Popup.Success.open('Service Setup Successfully Copied', 'Copy Completed');
39192                
39193                var j = $('#wiz5-stafflist');
39194                var tdCopy = j.find('#trStaff' + copySid).find('td.wiz5-column-staff-service');
39195                var tdChange = j.find('#trStaff' + changeSid).find('td.wiz5-column-staff-service');
39196                tdChange.attr('title', tdCopy.attr('title'));
39197                tdChange.text(tdCopy.text());
39198            });		//.error(function(jqXHR, textStatus, errorThrown) { });
39199    }
39200    _constructor.openServicesOffered = function(sid, notPartialView) {
39201    	if (UTIL.isEmpty(sid)) {
39202    		sid = GLO.Info.getStaffId();
39203    	}
39204    	
39205    	//var fnManual = function() { Wiz5.openServicesOffered2(sid, notPartialView); };
39206    	
39207    	if (GLO.Data.provider.packageType == 2 && GLO.Info.roleType > 209) {
39208    		$('#quick-view-header')
39209    	}
39210    	
39211    	Wiz5.openServicesOffered2(sid, notPartialView);
39212    }
39213    _constructor.copyServicesOffered = function(sid, notPartialView) {
39214    	var staffName = $('#quick-view-header').text();
39215		
39216		if (UTIL.isEmpty(staffName)) {
39217			staffName = $('#wiz5-stafflist').find('#trStaff' + sid).find('td.wiz5-column-name').text();
39218		}
39219		
39220		var fnCopy = function() { Wiz5.openCopyStaffService(sid, staffName); };
39221		var fnManual = function() { };
39222		
39223		var msg = 'Would you like to copy the service times, prices, commission, and goals of another staff member?';
39224		var htm = '<div id="pop-confirm-copy-service-setup">' + msg + '</div>';
39225		
39226		var jpop = GLO.Popup.Confirm.open(htm, 'Copy Service Setup', fnCopy, fnManual).getPopup();
39227		jpop.find('.pop-buttons').css({ "width": "100%", "max-width": "480px" });
39228		jpop.find('.btnNo').removeClass('btnNo').addClass('btnAdd').find('>
39228a').text(' No ').css({ "position": "absolute", "left": "8px", "font-size": "16px" });
39229		jpop.find('.btnYes').removeClass('btnYes').addClass('btnAdd').find('>a').text('Yes, Copy').css({ "position": "absolute", "right": "8px", "font-size": "16px" });
39230    }
39231    _constructor.openServicesOffered2 = function(sid, notPartialView) {
39232        var staffName = $('#quick-view-header').text();
39233        $.modal.close();
39234        
39235        var throbber = $('.loadingDiv').clone().find('img').css({"margin": "100px auto"});
39236        var loadUrl = GLO.Link.Object.Provider.Wiz5Service + '?dt=' + UTIL.getDateString();
39237        if (sid !== null) { loadUrl += '&sid=' + sid; }
39238
39239        if (notPartialView) {
39240            document.location = loadUrl + '&fullpage=1&helloback=profile&pageback=1';
39241            return;
39242        }
39243
39244        var pop = $("#wiz5-popupServices");
39245        
39246        pop.html(throbber).load(loadUrl, function() {
39247            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
39248            
39249            UI.setAccessKey('#wiz5-popupServices', null, WIZ.popupSave);
39250            _setServicesStaffName(staffName, sid);
39251            
39252            pop.find('td > input:checkbox').each(function() {
39253                Wiz5.staffServiceChecked(this);
39254            });
39255
39256            pop.find('td > input[type="number"], td > input[type="text"]').each(function() {
39257                $(this).change(function() {
39258                    if (this.value != '') {
39259                        var chk = $(this).parent().parent().find(':checkbox');
39260                        Wiz5.staffServiceChecked(chk);
39261                    }
39262                })
39263            });
39264
39265            initServicesPopup();
39266
39267            UTIL.Validate.init(pop.find('form#wiz5-form-services'));
39268            pop.find('form').attr('action', loadUrl);
39269            WIZ.Popup.onSave = function(data) { Wiz5.markUpdated(sid, 3, null, data); }
39270
39271            //pop.off('click', 'button.positive');
39272            //pop.on('click', '#simplemodal-container button.positive', function() { Wiz5.processingCellUpdate(sid, 3); });
39273            _columnNumber = 3; _staffId = sid;
39274            $('#simplemodal-container').draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
39275
39276            UTIL.Validate.saveButton = '#simplemodal-container .btnSave a';
39277            $('#simplemodal-container').find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved);
39278            $('#wiz5-popup-service .shadow2:first').css({ "margin-top": "8px" });
39279
39280            pop.find('#price1').focus();
39281            
39282            _initNarrowPopup(pop);
39283        	_initNonWizardPage(pop);
39284        	_initTallPopup();
39285        });
39286
39287        pop.modal();
39288        _openServicesDimensions(pop);
39289    }
39290    
39291    _constructor.openUpdateQuickNote = function() {
39292    	if (GLO.Info.roleType < 209) { return; }
39293    	
39294    	var jmodal = $('#simplemodal-container');
39295    	var jhead = jmodal.find('#quick-view-header');
39296    	var text = '<textarea>' + $('#quick-view-note-text').text() + '</textarea>';
39297    	
39298    	var htm = '<div id="pop-staff-quick-note" staff_id="' + jhead.attr('staff_id') + '">
39298' + text + '</div>';
39299    	var header = 'Quick Staff Note for ' + jhead.text();
39300    	
39301    	GLO.Popup.Custom.openSimple(htm, header, Wiz5.saveQuickNote);
39302    }
39303    _constructor.saveQuickNote = function() {
39304    	var jpop = $('#pop-staff-quick-note');
39305    	var staffId = jpop.attr('staff_id');
39306    	jpop = jpop.closest('.glopop');
39307    	
39308    	var uri = GLO.Link.Object.Provider.Ajax + 'StaffQuickNote?staff=' + staffId;
39309    	var note = UTIL.htmlEncode2(jpop.find('textarea').val());
39310    	
39311    	GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
39312    	
39313        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "note": note } })
39314            .success(function(data, textStatus, jqXHR) {
39315                GLO.Popup.close(jpop);
39316                GLO.Popup.Success.open('Service Note Changed', 'Update Successful');
39317                $.modal.close();
39318            })
39319            .error(function(jqXHR, textStatus, errorThrown) { });
39320    }
39321    
39322    function _setServicesStaffName(staffName, sid) {
39323		if (UTIL.isEmpty(staffName)) {
39324			staffName = $('#wiz5-stafflist').find('#trStaff' + sid + ' td').eq(1).text();
39325	    }
39326	    
39327	    if (UTIL.isEmpty(staffName)) {
39328	    	staffName = _processForNonWizardPage();
39329	    }
39330	    
39331	    $('#wiz5-staffName').text(staffName);
39332	    
39333	    if (UTIL.isEmpty(staffName)) {
39334	    	$('#wiz5-staffName').css({ "background-color": "transparent" });
39335	    }
39336	}
39337    
39338    function _initTallPopup() {
39339    	if (innerHeight > 800) {
39340	    	var popupHeight = innerHeight - 100;
39341	    	$('#simplemodal-container').css({ "top": "40px", "height": popupHeight + "px", "max-height": "inherit" });
39342	    	$('#wiz5-form-body').css({ "height": (popupHeight - 90) + 'px' });
39343    	}
39344    }
39345    function _initNarrowPopup(pop) {
39346    	if (GLO.Info.isMobile()) {
39347        	$('#simplemodal-container').css({ "width": (innerWidth * .98), "height": "", "max-height": "inherit" });
39348        	$('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important");
39349        	$('#wiz5-form-body').css({ "height": "inherit" });
39350        	$('#wiz5-popupButtons').css({ "position": "relative" });
39351        //} else {
39352		//	$('#simplemodal-container').draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
39353		} else if (innerWidth < 640) {
39354    		pop.find('.hidePhone').addClass('hide');
39355    	}
39356    }
39357    function _initNonWizardPage() {
39358    	if (WIZ.page !== undefined || WIZ.isWizard) { return; }
39359    	
39360    	var jmodal = $('#simplemodal-container').css({ "padding": "0" });
39361    	
39362    	if (jmodal.width() > 800) {
39363    		$.modal.update(null, 800);
39364    	}
39365    }
39366	
39367	function _openServicesDimensions(pop) {
39368    	var h = 725;
39369    	
39370    	if (GLO.Info.isMobile()) {
39371        	pop.closest('#simplemodal-container').css({ "top": "10px", "padding": "6px" });
39372        	
39373        	/*
39374        	if (GLO.Info.isLandscape()) {
39375        		$.modal.update(h, 555);
39376        	} else {
39377        		$.modal.update(h, 360);			//480
39378        	}
39379        	*/
39380	    }
39381	    
39382	    if (innerWidth > 980) {
39383        	$.modal.update(h, 960);
39384        } else {
39385        	$.modal.update(h, innerWidth - 20);
39386        }
39387	}
39388	
39389    _constructor.staffServiceChecked = function(chkBox) {
39390        var tr = $(chkBox).parent().parent();
39391        
39392        if (tr.hasClass('wiz5-more-row')) { return; }
39393        
39394        var svcRowNum = tr.attr('id').substring(8);
39395        var prows = tr.parent().find('tr#prow' + svcRowNum);
39396        
39397        if ($(chkBox).is(':checked')) {
39398            tr.find('td').css('text-decoration', '');                           //tr.css('text-decoration', '');
39399            tr.css('opacity', '');
39400
39401            if (prows.eq(2).hasClass('hide')) { 
39402                if (!UTIL.isEmpty(prows.eq(0).find('.wiz5-default-time-val').text()) || !UTIL.isEmpty(prows.eq(1).find('.wiz5-default-time-val').text())
39403                		|| !UTIL.isEmpty(prows.eq(0).find('input[type="number"]').text()) || !UTIL.isEmpty(prows.eq(1).find('input[type="number"]').text())
39404                		|| !UTIL.isEmpty(prows.eq(1).find('.wiz5-max-clients').val())) {
39405                    tr.find('.wiz5-more').click();
39406                    //prows.removeClass('hide');
39407                }
39408            }
39409        } else {
39410            if (!prows.eq(0).hasClass('hide')) {
39411                tr.find('.wiz5-more').click();
39412                //prows.addClass('hide'); 
39413            }
39414
39415            tr.find('td').css('text-decoration', 'line-through');               //tr.css('text-decoration', 'line-through');
39416            tr.css('opacity', '.5');
39417        }
39418    }
39419	
39420	_constructor.staffServiceCheckedAll = function(me) {
39421        me = $(me);
39422        
39423        var isChecked = me.prop('checked');
39424        var cBoxes = me.closest('table').find('input:checkbox.wiz5-svc-enable');
39425        
39426        cBoxes.each(function() {
39427            var jbox = $(this)
39428            
39429            if (isChecked && !jbox.prop('checked')) {
39430                jbox.prop('checked', true);
39431                Wiz5.staffServiceChecked(this);
39432            } else if (!isChecked && jbox.prop('checked')) {
39433                jbox.prop('checked', false);
39434                Wiz5.staffServiceChecked(this);
39435            }
39436        });
39437    }
39438	
39439    _constructor.saveStatus = function() {
39440        WIZ.popupSave();
39441    }
39442
39443    _constructor.markUpdated = function(staffId, columnNumber, caption, data) {
39444        if (staffId === 'new') {
39445            var jtr = $(data).css({ "background-color": "lightpink" });
39446            var jtbl = $('#wiz5-stafflist tbody').prepend(jtr);
39447
39448            //var rowpos = jtbl.find('tr:first').position();
39449            //jtbl.scrollTop(rowpos.top);
39450            $('#wiz5-staffparent').scrollTop(0);
39451        } else {
39452            var upd = $('.wiz5-updated-cell:first').clone();
39453        
39454            if (UTIL.isEmpty(caption)) { caption = SA.Resource.Updated.toLowerCase(); }
39455            upd.text(caption);
39456
39457            $('#wiz5-stafflist').find('#trStaff' + staffId + ' td').eq(columnNumber).html(upd);
39458            
39459            SA.Parent.processProfileUpdate(staffId, columnNumber);
39460            
39461            if (columnNumber === 3) {
39462            	var priceDiffCount = $(data).attr('price_diff_count_sr');
39463            	Wiz5.askServicePriceDiff(staffId, priceDiffCount);
39464            }
39465        }
39466        
39467        if ($('#staff-profile-report-header').length > 0) {
39468        	var tbl = $('#report-main').find('.tablesorter:visible')
39469        	var tr = tbl.find('#trStaff' + staffId).find('.report-column-staff > a');
39470        	
39471        	if (tr.length === 1) {
39472        		GLO.Popup.closeIfExist( $('#pop-success-refresh-ask').closest('.glopop') );
39473        		
39474        		var btnRefresh = '<span class="btnSearch" style="display: block; width: 100px; margin: auto; margin-bottom: 8px;"><a onclick="document.location.reload()">Refresh</a></span>';
39475        		var msg = '<div id="pop-success-refresh-ask" class="friendly-msg4" style="text-align: center; color: #4F81BD;"><p style="text-align: center;">Do you want to refresh the report?</p>' + btnRefresh + '</div>';
39476        		var h1 = tr.text() + ' Saved';
39477        		var jpop = $('#pop-success-wizard').closest('.glopop');
39478        		
39479        		if (jpop.length) {
39480        			var htm = '<div style="margin-top: 12px;">' + msg + '</div>';
39481        			jpop.find('h1').html(h1);
39482        			jpop.find('.msg').append(htm);
39483        		} else {
39484        			var htm = '<div id="pop-success-wizard-refresh">' + msg + '</div>';
39485        			GLO.Popup.Success.open(htm, h1, 9000);
39486        		}
39487        		
39488        		UI.highlight( $('#staff-profile-report-header .fa-refresh') );
39489        	}
39490        }
39491    }
39492
39493    _constructor.processingCellUpdate = function() {
39494        if (_staffId === 'new') {
39495            var jAddStaffBtn = $('#wiz5-AddProvider');
39496            GLO.UI.Form.beginProcessing(jAddStaffBtn);
39497        } else {
39498            var ajax_load = "<img class='loading' src='" + GLO.Data.cdnDirectory + "image/processing.gif' alt='loading...' style='margin: 0;'/>";
39499            $('#wiz5-stafflist').find('#trStaff' + _staffId + ' td').eq(_columnNumber).html(ajax_load);
39500        }
39501    }
39502
39503    _constructor.clickMyNotification = function(checkbox1, checkbox2) {
39504        checkbox1 = document.getElementById(checkbox1);
39505        checkbox2 = document.getElementById(checkbox2);
39506
39507        if (checkbox1.checked) {
39508            checkbox1.checked = false;
39509        } else {
39510            checkbox1.checked = true;
39511        }
39512
39513        if (checkbox2.checked) {
39514            checkbox2.checked = false;
39515        } else {
39516            checkbox2.checked = true;
39517        }
39518    }
39519
39520    _constructor.newProfile = function() {
39521        var pop = $('#wiz5-popup-newProfile');
39522
39523        /*  //CHANGE (low priority):
39524        For now I re-load this every time since the mask jquery pluggin throws an error if I re-open the same popup html.  
39525        I'm pretty sure that I fixed this on the client portal so I just have to see how I fixed it.
39526
39527        UPDATE (Sep 20xx): I'm actually only loading wiz2 in 1 location on the page as the Wiz2 javascript object doesn't currently support multiple wiz2 objects on the page.
39528        So instead of the "Add Staff Member" button calling this function it calls editProfile('')
39529        */
39530        
39531        var loadUrl = GLO.Link.Object.Provider.WizardPart1 + "?page=5&popup=yes&sid=new&dt=" + UTIL.getDateString();
39532        
39533        pop.load(loadUrl, function() { 
39534            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
39535            load_newProfile(); 
39536        });
39537
39538        /*
39539        if (pop.html() == '') {
39540            var loadUrl = GLO.Link.Object.Provider.WizardPart2 + "?page=4&popup=yes&sid=new";       //"/outglo/wizard/popups/4-1.htm";
39541            pop.load(loadUrl, function() { load_newProfile(); });
39542        } else {
39543            load_newProfile(pop);
39544        }
39545        */
39546    }
39547
39548    function load_newProfile(pop) {
39549        /*
39550        if (pop == null) { var pop = $('#wiz5-popup-newProfile'); }
39551        var loadUrl = GLO.Link.Object.Provider.WizardPart2 + "?page=4&popup=yes&sid=new";
39552        $('#wiz5-popup-newProfile').load(loadUrl);
39553        */
39554        //if (_constructor.newProfileIsLoaded) {
39555        //    pop.modal();
39556        //} else {
39557        
39558        //WIZ.modalAdjustHeight = 0;						// = -110;		// = 160;
39559        Wiz1.header = SA.Resource.AddStaffMember;
39560        //Wiz2.init(pop);
39561        
39562        var jContainer = $('#wiz1-body');
39563        var copyStaff = $('#staffCheck:checked');       //form#wiz5-form
39564        if (copyStaff.length == 1) { jContainer.find('#Copied_Staff_id').val(copyStaff.parent().parent().attr('id').substr(7)); }
39565
39566        //WIZ.openUserLogin(null, pop, false);
39567        //$.modal.update(450, 550);
39568        
39569        _constructor.newProfileIsLoaded = true;
39570        WIZ.Popup.onSave = Wiz5.AddNewStaffRow;
39571        UI.setAccessKey('#wiz1-body', null, WIZ.popupSave);
39572        //}
39573    }
39574
39575    _constructor.AddNewStaffRow = function(dataFromAjax) {
39576        $('#wiz5-stafflist tbody').append(dataFromAjax);
39577    }
39578
39579    _constructor.editProfile = function(staffId, staffName, isOverride) {
39580        if (staffId === 'new' && SA.Parent.canLinkStaff() && !isOverride) {
39581        	SA.Parent.openLinkStaffQuestion();
39582        	return;
39583        }
39584        
39585        var loadUrl = GLO.Link.Object.Provider.WizardPart1 + "?page=4&popup=yes&sid=" + staffId + "&dt=" + UTIL.getDateString();
39586        
39587        //CHANGE (low priority): I have to unload the empty wiz2 for adding staff because currently the way UTIL.Validate and wizard.js work there can only be 1 popup loaded on the page at one time.
39588        //$('#wiz5-popup-newProfile').html('');
39589        
39590        var cancelLoad = false;
39591        
39592        if (!UTIL.isEmpty(staffName)) {
39593        	var processingMsg = SA.Resource.LookingUp + " " + staffName + "'s " + SA.Resource.Profile + "...";
39594        } else {
39595        	var processingMsg = '';
39596        }
39597        
39598        var popProcessing = GLO.Popup.Processing(processingMsg, function() {
39599                cancelLoad = true;		//jqxhr.abort();
39600                $.modal.close();
39601            });
39602        
39603        var ojPopProcessing = popProcessing.getPopup();
39604		ojPopProcessing.find('.btnOk a').text(SA.Resource.Cancel);
39605        
39606        $("#wiz5-popupStaffProfile").load(loadUrl, function() {
39607            if (GLO.Log.processesSecurityException(null, arguments[0], arguments[1], arguments[2])) { return; }
39608            if (cancelLoad) { return; }
39609            popProcessing.close();
39610            
39611            var jpop = $('#wiz5-popupStaffProfile');
39612            var isFirstAvailable = _initWiz1FirstAvailable(jpop);
39613            
39614            if (staffId == 'new') {
39615                load_newProfile($("#wiz5-popupStaffProfile"));
39616            } else {
39617                _constructor.newProfileIsLoaded = false;
39618                WIZ.modalAdjustHeight = 160;
39619                WIZ.Popup.onSave = null;
39620                
39621                if (!isFirstAvailable && SA.Parent.canLinkStaff() && innerWidth > 500) {
39622                	var jbtns = $('#wiz1-popupNext').css({ "width": "100%" });
39623                	//jbtns.find('#wiz1-cancel').css({ "float": "none", "margin-left": "8px", "margin-right": "40px" }).find('>a').css({ "letter-spacing": "1px" });
39624                	//jbtns.find('#wiz1-Save').css({ "float": "none", "width": "80px", "margin": "auto", "margin-left": "40px" }).find('>a').css({ "letter-spacing": "1px" });
39625                	
39626                	if (!UTIL.isEmpty( $('#wiz1-form #Staff_Parent_id').val() )) {
39627                		var btnLink = '<span id="btnLinkStaff" class="btnAdd" title="Link Staff with Another Location"> <a onclick="SA.Parent.openLinkStaff()">Staff Linked</a> </span>';
39628                	} else {
39629                		var btnLink = '<span id="btnLinkStaff" class="btnAdd btnAction2" title="Link Staff with Another Location"> <a onclick="SA.Parent.openLinkStaff()">Link Staff</a> </span>';
39630                	}
39631                	
39632                	jbtns.find('#wiz1-Save').after(btnLink);
39633                }
39634            }
39635            
39636            WIZ.openUserLogin(staffId, $("#wiz5-popupStaffProfile"), false);				//$('#wiz1-profilePhoto').addClass('hide');
39637            
39638            jpop.find('#wiz1-body').css({ "margin-top": "" });
39639            jpop.find('#wiz1-cancel').removeClass('hide');
39640            jpop.find('label').css({ "margin-bottom": "0" });
39641            jpop.find(':text').css({ "margin-top": "4px" });
39642            
39643            if (GLO.Info.isMobile()) {
39644            	if (innerWidth < 555) {
39645            		$.modal.update( ($('#wiz1-body').height() + 120) , innerWidth - 10);
39646            	} else {
39647            		jpop.find('#wiz1-name').find('td').css({ "text-align": "center" });
39648            		jpop.find('#Email_vc').css({ "width": "420px", "letter-spacing": "1px" });
39649            		jpop.find('#mobile-phone-container2').css({ "display": "inline-block", "margin-left": "12px" });
39650            		
39651            		var tdUsername = jpop.find('#wiz1-username').find('td').css({ "text-align": "center" });
39652            		tdUsername.find('label').css({ "display": "inline-block", "width": "90px", "margin-right": "4px" });
39653            		tdUsername.find('#Username_vc').css({ "display": "inline-block" });
39654            		
39655            		jpop.find('#Mobile_Phone_vc, #Username_vc').css({ "letter-spacing": "1px" });
39656            		
39657            		$.modal.update( ($('#wiz1-body').height() + 50) , 550);
39658            	}
39659            } else {
39660            	$.modal.update( ($('#wiz1-body').height() + 120) , 550);
39661            }
39662            
39663            if ($('#commission-by-staff-service').length > 0) {
39664            	WIZ.Popup.onSave = function(data, staffName) {
39665	            	new GLO.Popup.Processing('<div><h1 class="friendly-msg4">Saving Profile</h1><div class="friendly-msg4">Updating Profile</div></div>');
39666	            	setTimeout(function() { location.reload(); }, 3000);
39667            	}
39668            } else {
39669            	WIZ.Popup.onSave = function(data, staffName) {
39670            		Wiz5.markUpdated(staffId, 1, staffName, data);
39671            	}
39672            }
39673            
39674            _columnNumber = 1; _staffId = staffId;
39675            var isnew = (staffId === 'new');
39676            
39677            var jModal = $('#simplemodal-container').css({ "padding": "0" });
39678            jModal.prepend('<h1 id="pop-staff-profile-header">Staff Profile</h1>');
39679            jModal.find('a.modalCloseImg').css({ "top": "4px", "right": "8px" });
39680            jModal.draggable({ "handle": "h1" }).find('h1').css({ "cursor": "move" });
39681
39682            UTIL.Validate.saveButton = '#simplemodal-container .btnSave a';
39683            jModal.find('input:visible, select:visible').change(UTIL.Validate.changeUnsaved);
39684            
39685            if (!WIZ.isWizard) {
39686            	jModal.find('#Mobile_Phone_vc').removeClass('required');
39687            	
39688            	if (WIZ.page == 5 || GLO.Report.portalName == 'Staff Profiles') {
39689            		jModal.find('#Last_Name_vc, #Username_vc, #Password_vc, #Password2_vc').removeClass('required');
39690            	}
39691            }
39692            
39693            if (!isFirstAvailable) {
39694	            _addMerchantOptions(jModal, staffId);
39695            	_initStaff(jModal, isnew);
39696            }
39697            
39698            jModal.find('#Email_vc').removeClass('required');               //toDo (Q2 20xx): add class 'suggest' --> if anyfields w/ suggest are empty popup a warning message ~ "Are you sure you want to save this without: {field(s)}?"
39699            _addDeleteStaffButton(jpop, staffId, staffName);
39700            Wiz1.init();
39701            _initStaffColor(jModal);
39702            _initStaffGoldPackage(jModal);
39703            
39704            if (!GLO.Info.isMobile()) {
39705            	$.modal.update( ($('#wiz1-body').height() + 120) , 550);
39706            	WIZ.addScrollBarsToSimpleModal();
39707            }
39708            
39709            setTimeout(function() {
39710            	jModal.find('#First_Name_vc').focus();
39711            }, 50);
39712        });
39713    }
39714    function _initStaffColor(jmodal) {
39715    	if (GLO.Info.isGold()) {
39716    		var color = jmodal.find('#Color_Rgb_vc').val();
39717    		var jheader = jmodal.find('#pop-staff-profile-header');
39718    		var headerText = '<b>' + jheader.text() + '</b>';
39719    		
39720    		if (GLO.Info.roleType > 219) {
39721    			var icon = '<span id="color-picker-image" class="sa-sprite" onclick="Wiz5.openStaffColorSelector()" title="click to change color"> </span>';
39722    		} else {
39723    			var icon = '';
39724    		}
39725    		
39726    		if (!UTIL.isEmpty(color)) {
39727    			jheader.css({ "background-color": "rgb(" + color + ")" });
39728    		}
39729    		
39730    		jheader.html(headerText + icon);
39731    	}
39732    }
39733    function _initStaffGoldPackage(jmodal) {
39734    	if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10) { return; }
39735    	
39736    	var yearRange = GLO.UI.getYearRange(false);
39737    	
39738    	jmodal.find('#wiz1-license, #wiz1-hired').removeClass('hide');
39739    	jmodal.find("#License_Expire_dt").datepicker({ beforeShowDay: _constructor.setDatePickerDays, changeYear: true, yearRange: yearRange });
39740    	jmodal.find("#Hire_dt").datepicker({ beforeShowDay: _constructor.setDatePickerDays });
39741    	
39742    	if (GLO.Info.roleType < 200) {
39743    		jmodal.find("#Hire_dt").prop('disabled', true);
39744    	}
39745    }
39746    function _initStaff(jmodal, isnew) {
39747    	if (!isnew) {
39748    		jmodal.find('#First_Name_vc, #Last_Name_vc').css({ "text-transform": "none" });
39749    	}
39750    	
39751    	jmodal.find('#wiz1-header-help').removeClass('hideX');
39752    	
39753        if (GLO.Info.providerPackage === 4 || !GLO.Provider.isPaidAccount(true)) {
39754        	var roleName = null, roleType = parseInt(jmodal.find('#Role_Type_cd').val());
39755        	var pop_height = jmodal.height() - 140;
39756        	var staffLoginCount = UTIL.coalesceInt(jmodal.find('#wiz1-form > table').attr('login_count_sr'), 0);
39757        	
39758        	jmodal.find('#row-birthday, #wiz1-license, #wiz1-hired').addClass('hide');
39759        	jmodal.find('#mobile-phone-container2').css({ "display": "none" });
39760        	
39761        	if (roleType > 229) {
39762        		roleName = 'Admin';
39763        	} else if (roleType > 209) {
39764        		roleName = 'Front Desk';
39765        	} else {
39766        		if (isnew) {
39767        			roleName = 'Add Staff';
39768        			
39769        			if (staffLoginCount < 2) {
39770        				var minRole = UTIL.coalesceInt(jmodal.find('#wiz1-form').attr('min_role_cd'), 150);
39771        				var labelRole = '<label for="Role_Type_cd" style="margin: 0; margin-right: 6px; font-weight: bold; color: #4F81BD;">Role</label>';
39772        				
39773        				var roleOption1 = '<option value="' + minRole + '" title="Normal staff">Normal</option>';
39774        				var roleOption2 = '<option value="200" title="Full access to all staff calendar; no access to reports">Limited Receptionist</option>';
39775        				var roleOption3 = '<option value="210" title="Access needed to manage business, limited access to sales and payment reports; cannot change advanced settings">Receptionist</option>';
39776        				
39777        				var ddCSS = 'width: 160px; padding-right: 0; letter-spacing: 1px; font-weight: bold; font-size: 16px; border-color: #4F81BD; color: #4F81BD;';
39778        				var ddRole = '<select name="Role_Type_cd" id="Role_Type_cd" onchange="Wiz1.changeNormalStaffRole(this)" style="' + ddCSS + '">' + roleOption1 + roleOption2 + roleOption3 + '</select>';
39779        				
39780        				var helpIcon = '<span class="helpIcon2 sa-sprite" onclick="SA.Help.Profile.openStaffRole(this)" style="margin-top: 1p
39780x;"></span>';
39781        				var htmRole = '<div style="position: relative; max-width: 240px; margin: auto; margin-top: 16px; margin-bottom: 8px;"> ' + labelRole + ddRole + helpIcon + '</div>';
39782        				jmodal.find('#wiz1-form').append(htmRole);
39783        				jmodal.find('#wiz1-username').find('td').css({ "padding-bottom": "2px" });
39784        				
39785        				var jpass = jmodal.find('#wiz1-password');
39786        				jmodal.find('#wiz1-username').addClass('hide').prop('password_htm', jpass.outerHTML());
39787        				jpass.remove();
39788        			}
39789        		} else if (staffLoginCount < 2) {
39790        			roleName = 'Front Desk';
39791        		}
39792        		
39793        		if (staffLoginCount > 1 && jmodal.find('#wiz1-username, #wiz1-password').length > 1) {
39794            		jmodal.find('#wiz1-username, #wiz1-password').remove();
39795            		pop_height -= 100;
39796        		}
39797        	}
39798        	
39799        	if (roleName !== null) {
39800        		jmodal.find('h1').text(roleName);
39801        		//jmodal.prepend('<h2 style="letter-spacing: 2px; border-radius: 0; border-top-left-radius: 4px; color: white;">' + roleName + '</h2>');
39802        		//pop_height += 30;
39803        		//$('body.phone #simplemodal-container a.modalCloseImg').css({ "top": "4px" });
39804        	}
39805        	
39806        	//$.modal.update(pop_height, null);			//commented out because causes issue on phone (silver package)
39807        }
39808    }
39809    
39810    function _addDeleteStaffButton(jpop, staffid, staffName) {
39811    	if (GLO.Info.providerPackage == 1 || _constructor.roleType < 210 || GLO.Data.Staff.require_password_appointment_edit_fl || staffid === 'new') { return; }
39812    	
39813    	var btn = '<a onclick="Wiz5.deleteStaffAsk(' + staffid + ', \'' + UTIL.replaceQuotesTitle(staffName) + '\')">Delete</a>';
39814    	var btnHtm = '<span class="btnDelete">' + btn + '</span>';
39815    	
39816    	var jbtns = jpop.find('#wiz1-popupNext').append(btnHtm);
39817    	//jbtns.find('.btnCancel').css({ "margin-left": "2%" }).find('>a').css({ "letter-spacing": "2px", "font-size": "16px" });
39818    	//jbtns.find('.btnSave').css({ "width": "80px", "margin-right": "2%" }).find('>a').css({ "letter-spacing": "2px", "font-size": "16px" });
39819    }
39820	
39821	function _initWiz1FirstAvailable(jpop) {
39822		if (!UTIL.parseBool(jpop.find('#Is_First_Available_fl').val())) { return false; }
39823		
39824		jpop.prepend('<h2 style="letter-spacing: 2px; border-radius: 0; border-top-left-radius: 4px; color: white;">First Available</h2>');
39825		jpop.find('#Female_fl, #Middle_Initial_c, #row-otherPhone, #wiz1-username, #wiz1-password, #row-birthday, #wiz1-license, #wiz1-hired, #use-house-merchant-row').remove();
39826		jpop.find('#wiz1-form table').css({ "margin-top": "0" });
39827		jpop.find('#wiz1-body .widegap tr td').css({ "text-align": "center" });
39828		jpop.find('input').css({ "letter-spacing": "1px" });
39829		
39830		return true;
39831	}
39832	
39833	function _addStaffMerchantLabel(jmodal) {
39834		var checkbox = '<img class="check-mark" src="' + GLO.Data.cdnDirectory + 'image/icon/32px-Black-check.svg.png" style="height: 20px; margin-bottom: 6px; margin-right: 6px;">';
39835		var snm = UTIL.htmlEncode2(jmodal.find('#First_Name_vc').val());
39836		var htm = '<div id="use-house-merchant-row">' + checkbox + ' <label for="Use_House_Merchant_fl">' + snm + ' ' + SA.Resource.HasMerchantAccount + '</label> </div>';
39837		
39838		jmodal.css({ "max-height": "700px" });
39839		jmodal.find('#wiz1-popupNext').before(htm);
39840		jmodal.height(jmodal.height() + 80);
39841	}
39842	
39843	function _addMerchantOptions(jmodal, staffId) {
39844		var mtype = UTIL.coalesceInt(jmodal.find('#Merchant_Type_cd').val(), 0);
39845		
39846		if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) > 19) { return; }
39847		if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) < 10) { return; }
39848		if (UTIL.coalesceInt(mtype, 0) > 49) { _addStaffMerchantLabel(jmodal); return; }
39849		
39850		if (GLO.Info.roleType < 220) {
39851			if (mtype > 0 && mtype < 20) {
39852				var checkbox = '<img class="check-mark" src="' + GLO.Data.cdnDirectory + 'image/icon/32px-Black-check.svg.png" style="height: 20px; margin-bottom: 6px; margin-right: 6px;">';
39853			} else if (GLO.Info.roleType > 209) {
39854				var checkbox = '<input type="checkbox" id="Use_House_Merchant_fl"/>';
39855			} else {
39856				return;
39857			}
39858		} else {
39859			if (mtype > 0 && mtype < 20) {
39860				var checkbox = '<input type="checkbox" id="Use_House_Merchant_fl" checked="checked"/>';
39861			} else {
39862				var checkbox = '<input type="checkbox" id="Use_House_Merchant_fl"/>';
39863			}
39864		}
39865		
39866		var snm = UTIL.htmlEncode2(jmodal.find('#First_Name_vc').val() + ' ' + jmodal.find('#Last_Name_vc').val());
39867		var helpHtm = '<div> <h1 style=\'letter-spacing: 1px;\'>
39867' + snm + ' ' + SA.Resource.CreditCardMerchantAccount + '</h1>'
39868						+ '<div style=\'margin-left: 4px; margin-bottom: 16px; line-height: 200%; letter-spacing: 1px; text-align: left;\'>' 
39869						+ SA.Resource.ReceptionistsCanAddSomeoneToHouseAcct + ' <small>(' + SA.Resource.by_checking_this_box + ')</small><br/>'
39870						+ SA.Resource.ManagerRequiredHouseAcct + ' <small>(' + SA.Resource.by_unchecking_box + ')</small><br/>' 
39871						+ SA.Resource.SetupMerchantAcct + ' <a href=\'https://www.scheduleanyone.com/hello/contact\' style=\'font-weight: bold;\'>' + SA.Resource.ContactUs.toLowerCase() + '</a> </div> </div>';
39872		
39873		var htmAddMerchant = _addNewMerchantButton(staffId, mtype);
39874		var help = '<span class="helpIcon2 sa-sprite" onclick="GLO.UI.openHelp(this)" alt_html="' + helpHtm + '" style="margin-left: 24px;">';
39875		var htm = '<div id="use-house-merchant-row"> <div>' + checkbox + '<label for="Use_House_Merchant_fl">' + SA.Resource.UseHouseMerchantAccount + '</label>' + help + '</div>' + htmAddMerchant + '</div>';
39876		
39877		var popHeight = jmodal.height() + 90;
39878		if (!UTIL.isEmpty(htmAddMerchant)) { popHeight += 50; }
39879		
39880		jmodal.css({ "max-height": "700px" }).find('#wiz1-popupNext').before(htm);
39881		jmodal.height(popHeight);
39882	}
39883	
39884	function _addNewMerchantButton(staffId, mtype) {
39885		if (mtype > 49 || UTIL.isEmpty(staffId) || staffId == 'new') {
39886			return '';
39887		} else if (GLO.Info.roleType > 209) {			// || (GLO.Info.roleType > 159 && GLO.Info.StaffId == staffId)
39888			return '<div id="btnAddMerchant"> <span class="btnAdd btnAction1"><a onclick="Wiz5.addNewMerchantAccount()">' + SA.Resource.AddMerchantAccount + '</a></span> </div>';
39889		} else {
39890			return '';
39891		}
39892	}
39893	
39894	_constructor.requestNewMerchant = function() {
39895		var jpop = $('#pop-staff-add-merchant').closest('.glopop');
39896		var sname = jpop.find('h1').text().replace(': ' + SA.Resource.AddMerchantAccount + '', '');
39897		var sid = jpop.find('#pop-staff-merchant-info').attr('staff_id');
39898		
39899		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
39900		var url = GLO.Link.Object.Provider.Ajax + "RequestMerchantAccount?staff_id=sid";
39901		
39902		$.ajax({ type: "POST", url: url, "cache": false, data: { "staff_id": sid } })
39903            .success(function(data, textStatus, jqXHR) {
39904                GLO.UI.Form.resetProcessing();
39905
39906                if (!UTIL.isEmpty(data)) {
39907                    var jdata = $(data);
39908                    
39909                    if (jdata.attr('error_fl') == '1') {
39910                        new GLO.Popup.Error(jdata.attr('error_vc'));
39911                        return;
39912                    }
39913                }
39914
39915                GLO.Popup.close(jpop);
39916                $.modal.close();
39917                
39918                var cssStyle = 'style="margin-bottom: 12px; letter-spacing: 1px; line-height: 200%;"';
39919                var htm = $('<div ' + cssStyle + '> ' + SA.Resource.WeWillContact + ' ' + sname + ' ' + SA.Resource.ToSetupMerchantAccount + '.<br/>' + SA.Resource.CallForQuestions + '</div>');
39920                new GLO.Popup.Info(htm);
39921            })
39922            .error(function(jqXHR, textStatus, errorThrown) {
39923                GLO.Popup.Error('Unable to clock in at this time.  Please try again later.');
39924                GLO.UI.Form.resetProcessing();
39925            });
39926	}
39927	
39928	_constructor.saveNewMerchant = function() {
39929		var jpop = $('#pop-staff-add-merchant').closest('.glopop');
39930		var sid = jpop.find('#pop-staff-merchant-info').attr('staff_id');
39931		var tab = jpop.find('.tab-body:visible');
39932		
39933		if (tab.attr('id') == 'tab-body-add-cayan') {
39934			var mname = jpop.find('#new-merchant-name').val();
39935			var mkey = jpop.find('#new-merchant-key').val();
39936			var msite = jpop.find('#new-merchant-site').val();
39937			
39938			if (mname.length < 5) {
39939				new GLO.Popup.Warning(SA.Resource.PleaseEnterMerchantName, function() { $('#pop-staff-add-merchant').find('#new-merchant-name').focus(); });
39940				return;
39941			} else if (mkey.length < 5) {
39942				new GLO.Popup.Warning(SA.Resource.PleaseEnterMerchantKey, function() { $('#pop-staff-add-merchant').find('#new-merchant-key').focus(); });
39943				return;
39944			} else if (msite.length < 5) {
39945				new GLO.Popup.Warning(SA.Resource.PleaseEnterMerchantSiteId, function() { $('#pop-staff-add-merchant').find('#new-merchant-site').focus(); });
39946				return;
39947			}
39948			
39949			var jd = { "staff_id": sid, "merchant_name_vc": mname, "merchant_key_vc": mkey, "merchant_site_vc": msite };
39950		} else {
39951			var mid = jpop.find('#new-merchant-id').val();
39952			var user = jpop.find('#new-merchant-username').val();
39953			var pass = jpop.find('#new-merchant-password').val();
39954			
39955			if (mid.length < 8) {
39956				GLO.Popup.Warning.open('Please Enter Merchant Id', 'Add Merchant Warning', function() { $('#pop-staff-add-merchant').find('#new-merchant-id').focus(); });
39957				return;
39958			} else if (user.length < 5) {
39959				GLO.Popup.Warning.open('Please Enter Merchant Username', 'Add Merchant Warning', function() { $('#pop-staff-add-merchant').find('#new-merchant-username').focus(); });
39960				return;
39961			} else if (user.length < 5) {
39962				GLO.Popup.Warning.open('Please Enter Merchant Password', 'Add Merchant Warning', function() { $('#pop-staff-add-merchant').find('#new-merchant-password').focus(); });
39963				return;
39964			}
39965			
39966			var jd = { "staff_id": sid, "merchant_id_vc": mid, "user_id_vc": user, "password_vc": pass };
39967		}
39968		
39969		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
39970		var url = GLO.Link.Object.Provider.Ajax + "SaveMerchantAccount";
39971		
39972		$.ajax({ type: "POST", url: url, "cache": false, data: jd })
39973            .success(function(data, textStatus, jqXHR) {
39974                GLO.UI.Form.resetProcessing();
39975
39976                if (!UTIL.isEmpty(data)) {
39977                    var jdata = $(data);
39978                    
39979                    if (jdata.attr('error_fl') == '1') {
39980                        GLO.Popup.Error.open(jdata.attr('error_vc'), 'Add Merchant Error');
39981                        return;
39982                    }
39983                }
39984
39985                GLO.Popup.close(jpop);
39986                GLO.Popup.Success.open(SA.Resource.MerchantAccountAdded, 'Merchant Insert Successful');
39987                $.modal.close();
39988                
39989                if (WIZ.page === 5) {
39990                	setTimeout(function() { $('#wiz5-stafflist').find('tr#trStaff' + sid).find('.wiz5-column-name').click() }, 900);
39991                }
39992            })
39993            .error(function(jqXHR, textStatus, errorThrown) {
39994                GLO.Popup.Error.open('<div id="pop-error-add-merchant"><p>Unable to add merchant at this time</p><p>Please try again later</p></div>', 'Add Merchant Error');
39995                GLO.UI.Form.resetProcessing();
39996            });
39997	}
39998	
39999	_constructor.backToProfile = function() {
40000		GLO.Popup.close($('#pop-staff-add-merchant').closest('.glopop'));
40001		
40002		$('#wiz1-body').closest('#simplemodal-container').removeClass('hide');
40003	}
40004	
40005	_constructor.addNewMerchantAccount = function() {
40006		var jfrm = $('#wiz1-body');
40007		var sid = jfrm.find('#Staff_id').val();
40008		var snm = jfrm.find('#First_Name_vc').val() + ' ' + jfrm.find('#Last_Name_vc').val();
40009		
40010		//jfrm.closest('#simplemodal-container').addClass('hide');
40011		
40012		var jpop = _getNewMerchantPop(sid, snm);
40013		jpop = new GLO.Popup.Custom(jpop, Wiz5.saveNewMerchant).getPopup().addClass('no-persist');
40014		
40015		jpop.find('.tab-control').find('li.active-tab > a').click();
40016		
40017		var jbtns = jpop.find('.pop-buttons').css({ "max-width": "400px" });
40018		jbtns.find('.btnCancel>a').text('Back').click(Wiz5.backToProfile).css({ "letter-spacing": "1px" });
40019		jbtns.find('.btnSave').css({ "position": "absolute", "right": "4px", "margin": "0", "letter-spacing": "1px" });
40020		
40021		if (innerWidth > 600) {
40022			jpop.find('#pop-staff-add-merchant').addClass('pop-this-wide');
40023		} else if (innerWidth > 600) {
40024			jpop.find('#pop-staff-add-merchant').addClass('pop-this-narrow');
40025		}
40026	}
40027	
40028	function _getNewMerchantPop(sid, snm) {
40029		var houseMerchant = UserPortal.Price.Payment.getMerchantByPayTo('h');
40030		var isIncludeCayan = UTIL.parseBool(GLO.Data.provider.mixed_vendor_merchant_fl || houseMerchant.co != 30);
40031		
40032		/* if (innerWidth < 350) {
40033			var legend = SA.Resource.MerchantDetails;
40034		} else {		//if (innerWidth < 400) {
40035			var legend = SA.Resource.YourMerchantDetails;
40036		//} else {
40037		//	var legend = SA.Resource.YourMerchantDetailsFrom;
40038		} */
40039		
40040		if (isIncludeCayan) {
40041			var tab1 = '<li id="tab-add-clover-connect" class="active-tab"><a onclick="Wiz5.displayStatusTab(this, \'tab-body-add-clover-connect\')">Clover Connect</a></li>';
40042			var tab2 = '<li id="tab-add-cayan"><a onclick="Wiz5.displayStatusTab(this, \'tab-body-add-cayan\')">Cayan</a></li>';
40043			var tabs = '<div id="tabs-add-merchant" class="tab-control"><ul>' + tab1 + tab2 + '</ul></div>';
40044			
40045			var tabBody1 = _getCloverMerchantHtm();
40046			var tabBody2 = _getCayanMerchantHtm();
40047			var htmBody = tabs + tabBody1 + tabBody2;
40048		} else {
40049			var htmBody = _getCloverMerchantHtm();
40050		}
40051		
40052		var h1 = '<h1 style="letter-spacing: 1px;">' + snm + ': ' + SA.Resource.AddMerchantAccount + '</h1>';
40053		var btnContact = '<span class="btnAdd btnAction2"><a onclick="Wiz5.requestNewMerchant()" style="0 4px">' + SA.Resource.RequestNewMerchantAccount + '</a></span>';
40054		
40055		var htm = '<div id="pop-staff-add-merchant">' + h1 + '<p>' + SA.Resource.IfNoMerchantAccount + btnContact + '</p>';
40056		htm += '<div id="pop-staff-merchant-info" staff_id="' + sid + '"><div>';				//<h4>' + legend + '</h4>
40057		htm += htmBody + '</div>';
40058		
40059		return $(htm);
40060	}
40061	function _getCloverMerchantHtm() {
40062		var imgFiserv = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/merchant/fiserv-secure-message-merchant-credentials.png"/>';
40063		var tabBody1 = '<div id="tab-body-add-clover-connect" class="tab-body">';
40064		tabBody1 += '<p style="line-height: 1.4;">The Clover Connect merchant credentials come in an email from Fiserv with the <span class="narrow-text">email subject</span> <b>Production Credentials for...</b></p>';
40065		tabBody1 += '<p style="text-align: center;">' + imgFiserv + '</p>';
40066		
40067		tabBody1 += '<p> <label for="new-merchant-id">' + SA.Resource.Merchant + ' Id' + '</label> <input type="text" id="new-merchant-id" maxlength="100"/> </p>';
40068		tabBody1 += '<p> <label for="new-merchant-username">' + SA.Resource.Username + '</label> <input type="text" id="new-merchant-username" maxlength="100"/> </p>';
40069		tabBody1 += '<p> <label for="new-merchant-password">' + SA.Resource.Password + '</label> <input type="text" id="new-merchant-password" maxlength="100"/> </p>';
40070		tabBody1 += '</div>';
40071		
40072		return tabBody1;
40073	}
40074	function _getCayanMerchantHtm() {
40075		var tabBody2 = '<div id="tab-body-add-cayan" class="tab-body">';
40076		tabBody2 += '<p style="line-height: 1.4;">You will receive your Cayan/TSYS merchant credentials in an email</p>';
40077		
40078		tabBody2 += '<p> <label for="new-merchant-name">' + SA.Resource.MerchantName + '</label> <input type="text" id="new-merchant-name" maxlength="100" style="width: 16em;"/> </p>';
40079		tabBody2 += '<p> <label for="new-merchant-key">' + SA.Resource.MerchantKey + '</label> <input type="text" id="new-merchant-key" maxlength="100" style="width: 18em;"/> </p>';
40080		tabBody2 += '<p> <label for="new-merchant-site">' + SA.Resource.MerchantSiteID + '</label> <input type="text" id="new-merchant-site" maxlength="100" style="width: 8em;"/> </p>';
40081		tabBody2 += '</div>';
40082		return tabBody2;
40083	}
40084	
40085    function initServicesPopup() {
40086        //UI.init_Tooltip(".shadow-content2 h4 label, .shadow-content2 table tr td label", WIZ.toolTip_OnHover);            //note: I don't think the tooltip is good to use on this page.
40087        /*
40088        $(".shadow-content2 > h4 > input").click(function() {
40089            if (this.checked) {
40090                $(this).parent().parent().find("table input:checkbox").each(function() {
40091                    this.checked = true;
40092                })
40093            } else {
40094                $(this).parent().parent().find("table input:checkbox").each(function() {
40095                    this.checked = false;
40096                })
40097            }
40098        });
40099        */
40100        
40101        var j = $('#wiz5-form-body');
40102
40103        var tabIndex = 1;
40104        j.find('.shadow-content2 input:text').each(function() { $(this).attr('tabindex', tabIndex++); });
40105        //$('.shadow-content2 input:text').attr('tabindex', '0');
40106
40107        j.find('.wiz5-more-row input[type="number"], .wiz5-svc-time').on('keyup', Wiz5.changeTimeLength);
40108        j.find('.wiz5-more-block-out-td :checkbox').on('change', Wiz5.changeBlockOut);
40109    }
40110	
40111	_constructor.setClientAccess = function(event) {
40112        var jpop = $('#wiz5-popupStatus');
40113        
40114        if (jpop.length === 1) {
40115        	var jClient_Access_cd = jpop.find('#wizcc-who-can-book-options input[type=radio]:checked');
40116        } else {
40117        	var jClient_Access_cd = $('#online-booking-access input[type=radio]:checked');
40118        }
40119        
40120        var clientAccess = jClient_Access_cd.val();
40121        
40122        if (clientAccess == 2 && !GLO.Provider.isPaidAccount(true)) {
40123        	jClient_Access_cd = jpop.find('#Client_Access_cd1').prop('checked', true);
40124        	
40125        	var h1 = '<h1 class="friendly-msg2">' + SA.Resource.ExistingClientsRequiresUpgrade + '</h1>';
40126        	var msg1 = '<p>' + SA.Resource.MustUpgradeToAllowExisting + '</p>';
40127        	var msg2 = '<p class="info-link"> <a href="/help/existing-clients-only">' + SA.Resource.LearnHowExistingClientsWork + '</a> </p>';
40128        	var msg = '<div>' + h1 + '<div class="friendly-msg">' + msg1 + msg2 + '</div> </div>';
40129        	new GLO.Popup.Info(msg);
40130        } else if (GLO.Info.providerPackage != 4) {
40131            var popConfirm = jpop.find('#wiz5-cc-confirm-input-container');
40132            var jcheckboxes = popConfirm.find(':checkbox').change(Wiz5.changeConfirmAppt);
40133            
40134            if (event) {														//= is click
40135            	var subAccess = jpop.find('#Client_Sub_Access_cd').val();
40136            	_displayClientSubAccess(clientAccess, subAccess);
40137            } else if (clientAccess == 2 || clientAccess == 4) {				//= is load.
40138            	_setClientSubAccess(jpop, clientAccess, false);
40139            }
40140        }
40141        
40142        var clientAccess_color = jClient_Access_cd.parent().find('label').css('color');
40143        jpop.find('#online-booking-access legend').css('color', clientAccess_color);
40144    }
40145    
40146    function _displayClientSubAccess(clientAccess, subAccess) {
40147    	var isbiz = (GLO.Info.providerPackage !== 1);
40148    	var jmodal = $('#simplemodal-container #wiz5-popupStatus');
40149		var allowsOnlineBooking = UTIL.parseBool(jmodal.find('#Online_Booking_fl').val());
40150		var allowsRequestAppt = UTIL.parseBool(jmodal.find('#Request_Appointment_fl').val());
40151		var isForbid = (clientAccess == 3), isRequestOnly = (clientAccess == 4);
40152		
40153    	if (clientAccess == 2) {
40154    		subAccess = UTIL.coalesceInt(subAccess, 220);
40155    		var msg0 = '', popCSS = 'existing-client', h1 = 'Define Existing Client', header = 'Who do you consider an <b>Existing</b> client?';
40156    	} else if (isbiz && allowsRequestAppt && ( (allowsOnlineBooking && isForbid) || isRequestOnly) ) {
40157    		subAccess = UTIL.coalesceInt(subAccess, 0);
40158    		
40159    		var popCSS = 'request-appt', h1 = 'When Display Staff on Request Appointment Screen', header = 'When should this staff show as option when clients request appointments?';
40160    		var subAccessForAll = 0;
40161    		
40162    		if (clientAccess == 3) { subAccessForAll = 10; }
40163    		
40164    		var msg0 = _getClientSubAccessTextHtm(subAccessForAll, 'All Clients', 'Allows anyone to request an appointment', 'color: rgb(0,200,40);');
40165    	} else {
40166    		return false;
40167    	}
40168    	
40169    	var msg1 = _getClientSubAccessText(clientAccess, 210, isbiz, true);
40170    	var msg2 = _getClientSubAccessText(clientAccess, 220, isbiz, true);
40171    	
40172    	if (isbiz) {
40173    		var msg3 = _getClientSubAccessText(clientAccess, 230, isbiz, true);
40174    	} else {
40175    		var msg3 = '';
40176    	}
40177    	
40178    	if (clientAccess == 3) {
40179    		var msg4 = _getClientSubAccessText(clientAccess, 400, isbiz, true);
40180    	} else {
40181    		var msg4 = '';
40182    	}
40183    	
40184    	var htm = '<div id="pop-client-sub-access" class="' + popCSS + '"> <h6>' + header + '</h6> <ul>' + msg0 + msg1 + msg2 + msg3 + msg4 + '</ul> </div>';
40185    	var jpop = GLO.Popup.Custom.openSimple(htm, h1, Wiz5.setClientSubAccess);
40186    	jpop.find('.btnSave').remove();
40187		
40188		var cssCancel = { "position": "relative", "left": "inherit", "float": "none", "display": "block", "padding": "0", "letter-spacing": "2px", "width": "80px", "margin": "auto" };
40189		jpop.find('.btnCancel').css(cssCancel).find('>a').text('Close');
40190		
40191		jpop.find('#Client_Sub_Access_cd' + subAccess).prop('checked', true);
40192		jpop.find('li').click(Wiz5.setClientSubAccess);
40193    }
40194    
40195    _constructor.setClientSubAccess = function(event) {
40196    	var jPopSubAccess = $('#pop-client-sub-access').closest('.glopop');
40197    	var jcurrentSub = jPopSubAccess.find(':radio[name="Client_Sub_Access_cd"]:checked');
40198    	var jrad = $(this).find(':radio[name="Client_Sub_Access_cd"]');
40199    	
40200    	if (jrad.length === 0) {
40201    		jrad = jcurrentSub;
40202    	}
40203    	
40204    	var currentSubValue = jcurrentSub.val();
40205    	var newSubValue = jrad.val();
40206    	var text = jrad.closest('li').find('.sub-access-text').text();
40207    	var jPopAccess = $('#wiz5-popupStatus').closest('#simplemodal-container');
40208    	
40209    	jPopAccess.find('#wizcc-who-can-book-options').find(':radio[name="Client_Access_cd"]:checked').closest('tr').find('.quiet9').html(text);
40210    	jPopAccess.find('#Client_Sub_Access_cd').val(newSubValue);
40211    	
40212    	if (currentSubValue != newSubValue) {
40213    		jPopAccess.find('.btnSave > a').css({ "border": "3px solid red" });
40214    	}
40215    	
40216    	GLO.Popup.close(jPopSubAccess);
40217    }
40218    
40219    function _setClientSubAccess(jpop, clientAccess, isForceReset) {
40220    	var subAccess = UTIL.coalesceInt(jpop.find('#Client_Sub_Access_cd').val(), 0);
40221    	var isbiz = (GLO.Info.providerPackage !== 1);
40222    	
40223    	var jtext2 = jpop.find('#Client_Access_cd2').closest('tr').find('label span');
40224    	var jtext4 = jpop.find('#Client_Access_cd4').closest('tr').find('label span');
40225    	
40226    	if (!isForceReset && subAccess === 0) { return; }
40227    	
40228    	var text2 = _getClientSubAccessText(2, subAccess, isbiz);
40229    	var text4 = _getClientSubAccessText(4, subAccess, isbiz);
40230    	
40231    	jtext2.html(text2);
40232    	
40233    	if (clientAccess == 4) {
40234    		jtext4.html(text4);
40235    	}
40236    }
40237    
40238    function _getClientSubAccessText(clientAccess, subAccess, isbiz, includeHtm) {
40239    	if (subAccess === 210) {
40240    		var title = 'Existing Account';
40241    		var css = 'color: rgb(255,170,0);';
40242    		
40243    		if (isbiz) {
40244    			if (clientAccess == 2) {
40245    				var text = 'Clients with existing account (created by your staff) can book online';
40246    			} else {
40247    				var text = 'Clients with existing account (created by your staff) can request staff';
40248    			}
40249    		} else {
40250    			if (clientAccess == 2) {
40251    				var text = 'Clients with existing account (created by me) can book online';
40252    			} else {
40253    				var text = 'Clients with existing account (created by me) can request appointment';
40254    			}
40255    		}
40256    	} else if (subAccess === 230) {
40257    		if (isbiz) {
40258	    		var title = 'Past Appointment with ' + UTIL.maxString(UserPortal.getStaffName($('#wiz5-popupStatus').find('#Staff_id').val()), 10, true);
40259	    		var css = 'color: rgb(255,120,0);';
40260	    		
40261	    		if (clientAccess == 2) {
40262	    			var text = 'Clients with a past appointment (with this staff) can book online';
40263	    		} else {
40264	    			var text = 'Clients with a past appointment (with this staff) can request staff';
40265	    		}
40266	    		
40267	    		if (GLO.Info.roleType < 210) {
40268	    			text = text.replace('this staff', 'me');
40269	    		}
40270	    	} else {
40271	    		return '';				//= is biz only setting
40272	    	}
40273    	} else if (subAccess === 400 && clientAccess == 3) {
40274    		if (isbiz) {
40275	    		var title = 'Forbid Request Appointment';
40276	    		var text = 'Clients cannot request appointment with ';
40277	    		var css = 'color: rgb(255,20,0);';
40278	    		
40279	    		if (GLO.Info.roleType < 210) {
40280	    			text += 'me';
40281	    		} else {
40282	    			text += UTIL.maxString(UserPortal.getStaffName($('#wiz5-popupStatus').find('#Staff_id').val()), 10, true);
40283	    		}
40284	    	} else {
40285	    		return '';				//= is biz only setting
40286	    	}
40287    	} else {			//subAccess === 220 || use-default
40288    		var css = 'color: rgb(255,140,0);';
40289    		
40290    		if (isbiz) {
40291    			var title = 'Past Appointment at ' + GLO.Data.provider.name;
40292    			
40293    			if (clientAccess == 2) {
40294    				var text = 'Clients with a past appointment (with any staff) can book online';
40295    			} else {
40296    				var text = 'Cannot book online, but show up in Request Appointment staff drop down';
40297    			}
40298    		} else {
40299    			var title = 'Past Appointment';
40300    			
40301    			if (clientAccess == 2) {
40302    				var text = 'Clients with a past appointment can book online';
40303    			} else {
40304    				var text = 'Clients request appointment which you must approve';
40305    			}
40306    		}
40307    	}
40308    	
40309    	if (includeHtm) {
40310    		return _getClientSubAccessTextHtm(subAccess, title, text, css);
40311    	} else {
40312    		return text;
40313    	}
40314    }
40315    
40316    function _getClientSubAccessTextHtm(subAccess, title, text, css) {
40317    	var id = 'Client_Sub_Access_cd' + subAccess;
40318		var label1 = '<label class="sub-access-title" for="' + id + '">' + title + '</label>';
40319		var rdo = '<input type="radio" id="' + id + '" name="Client_Sub_Access_cd" value="' + subAccess + '"/>';
40320		
40321		return '<li style="' + css + '">' + rdo + label1 + '<label class="sub-access-text" for="' + id + '">
40321' + text + '</label></li>';
40322    }
40323    
40324    _constructor.changeConfirmAppt = function() {
40325    	var pop = $('#wiz5-popupStatus');
40326        var jClient_Access_cd = $('#online-booking-access input[type=radio]:checked').val();
40327    	
40328    	/* this is now allowed
40329    	if (jClient_Access_cd == 3) {
40330    		Wiz5.infoWhyConfirmationsDisabled();
40331    		this.checked = false;
40332    		pop.find('label[for="' + this.id + '"]').css({ "text-decoration": "line-through" });
40333    	}
40334    	*/
40335    }
40336    
40337    _constructor.infoWhyConfirmationsDisabled = function() {
40338    	if ( $('#pop-confirmation-disabled').length > 0) { return; }
40339    	
40340    	
40341    	var msg = '<div id="pop-confirmation-disabled" style="margin: 10px; margin-top: 0; line-height: 200%; letter-spacing: 1px;">' + SA.Resource.WhenOnlineBookingIsForbidden + '<br/>' + SA.Resource.AutomaticConfirmationEmailsDisabled + '</div>';
40342    	new GLO.Popup.Info(msg);
40343    }
40344    
40345    _constructor.openStaffQuickView = function(sid, event, isDisplayEditButton) {
40346    	if (event) {
40347    		if (event.altKey) {
40348    			Wiz5.openServicesOffered(sid);
40349    			return;
40350    		}
40351    	}
40352    	
40353        var throbber = $('.loadingDiv').clone().find('img').css({"margin-top": "150px"});
40354        var loadUrl = GLO.Link.WebsiteDomain + 'fragment/staff/quickview' + '?sid=' + sid + '&dt=' + UTIL.getDateString();
40355        var pop = $('#pop-temp');
40356        
40357        if (isDisplayEditButton) { loadUrl += '&allowedit=1'; }
40358
40359        pop.html(throbber).load(loadUrl, function() {
40360            if (GLO.Log.processesSecurityException(pop, arguments[0], arguments[1], arguments[2])) { return; }
40361            pop.find(".tablesorter").tablesorter({ textExtraction: UI.tableSorterOrderBy });
40362            
40363            var svcRows = pop.find('#quick-view table.tablesorter tbody tr').length;
40364            var width = null, height = null;
40365            var jmodal = pop.closest('#simplemodal-container').css({ "padding": "0" });
40366            jmodal.find('.simplemodal-data').css({ "padding": "0" });
40367            
40368            if (GLO.Info.isMobile()) {
40369	        	$('#simplemodal-container .modalCloseImg').attr("style", "top: 3px !important");
40370	        	$('#simplemodal-container, #quick-view').css({ "height": "", "max-height": "inherit" });
40371	        	$('#quick-view-buttons').css({ "position": "relative", "margin-top": "25px", "margin-bottom": "15px" });
40372	        	
40373	        	var btn = '<span class="btnAdd"> <a onclick="Wiz5.openServicesOffered(' + sid + ')" title="' + SA.Resource.AddClientToWaitingList + '">' + SA.Resource.Edit + '</a> </span>';
40374	        	$('#quick-view-header-table tbody').append('<tr> <td colspan="2" style="padding-bottom: 10px;">' + btn + '</td> </tr>');
40375	        	
40376	        	GLO.Popup.resizeMobile(jmodal);
40377	        	if (svcRows > 6) { height = 200 + svcRows * 25; }
40378	        } else {
40379	            jmodal.css({ "max-height": "800px" }).draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
40380	            
40381	            if (innerWidth < 720) {
40382	            	width = innerWidth - 20;
40383	            } else if (innerWidth > 970) {
40384		        	width = 900;
40385		        } else {
40386	            	width = 700;
40387	            }
40388	            
40389	            if (svcRows > 6) { height = 200 + svcRows * 25; }
40390	            if (height > $(window).height()) { height = $(window).height() - 50; }
40391	        }
40392	        
40393	        if (height > $('#simplemodal-container').outerHeight()) {
40394	        	if ($('#quick-view').height() > height - 100) {
40395		        	$('#quick-view').height(height - 130);
40396		        }
40397		        
40398	        	$.modal.update(height, width);
40399	        }
40400        });
40401        
40402        if (innerWidth < 650) {
40403        	var modalWidth = innerWidth;
40404        } else {
40405        	var modalWidth = 650;
40406        }
40407        
40408        pop.modal();
40409        $.modal.update(400, modalWidth);
40410    }
40411
40412    _constructor.openStaffQuickViewAll = function() {
40413        document.location = GLO.Link.WebsiteDomain + 'fragment/staff/QuickViewAll?fullpage=1';
40414
40415        //var throbber = $('.loadingDiv').clone().find('img').css({ "width": "150px", "height": "150px", "margin": "auto" });
40416        //$('#pop-temp').html(throbber).modal();
40417    }
40418
40419//    _constructor.openStaffQuickViewAll_Popup = function() {
40420//        var throbber = $('.loadingDiv').clone().find('img').css({"margin-top": "150px"});
40421//        var loadUrl = GLO.Link.WebsiteDomain + 'fragment/staff/QuickViewAll';
40422//        var pop = $('#pop-temp');
40423
40424//        pop.html(throbber).load(loadUrl, function() {
40425//            pop.find(".tablesorter").tablesorter({ textExtraction: UI.tableSorterOrderBy });
40426//            pop.find('#quick-view th').css({ "padding-top": "20px" });
40427//            
40428//            if (!GLO.Info.isMobile(false)) { $('#simplemodal-container').draggable({ "handle": "h2" }); }
40429//            $.modal.update(800, 900);
40430//        });
40431//        
40432//        pop.modal();
40433//        $.modal.update(400, 600);
40434//    }
40435
40436    _constructor.toggleProcessRows = function(btn) {
40437        btn = $(btn);
40438        var tr = btn.parent().parent();
40439
40440        if (parseInt(tr.css('opacity')) < 1) { return; }
40441
40442        var svcRow = tr.attr('id').substr(8);
40443        tr.parent().find('tr#prow' + svcRow).toggleClass('hide');
40444
40445        btn = btn.find('a');
40446
40447        if (btn.text() === '+') {
40448        	btn.text('-');
40449        } else if (btn.text() === '-') {
40450        	btn.text('+');
40451        } else if (btn.text() === SA.Resource.More.toLowerCase() + '...') {
40452            btn.text('...' + SA.Resource.Less.toLowerCase());
40453        } else {
40454            btn.text(SA.Resource.More.toLowerCase() + '...');
40455        }
40456    }
40457
40458    _constructor.changeTimeLength = function(inputBox) {
40459        //Step I: Set Variables
40460            if (this === Wiz5) {
40461            	var me = inputBox;
40462            } else {
40463            	var me = $(this);
40464            }
40465            
40466            if (me.hasClass('wiz5-svc-time')) {
40467                var svcRowId = me.attr('id').substring(4);
40468                var tbl = me.parent().parent().parent();
40469                var svcTime = me.val();
40470            } else {
40471                var tbl = me.parent().parent();
40472                if (tbl.prop('tagName') !== 'TR') { tbl = tbl.parent(); }
40473
40474                var svcRowId = tbl.attr('id').substring(4);
40475                tbl = tbl.parent();
40476                var svcTime = tbl.find('tr#wiz5-svc' + svcRowId + ' .wiz5-svc-time').val();
40477            }
40478
40479            if (!UTIL.isNumber(svcTime)) { 
40480                svcTime = parseInt(tbl.find('tr#wiz5-svc' + svcRowId + ' .wiz5-default-time-val').text());
40481            } else { 
40482                svcTime = parseInt(svcTime); 
40483            }
40484
40485            var totalBlockTime = svcTime;
40486            var rows = tbl.find('tr#prow' + svcRowId);
40487
40488        //Step II: Get Processing Time
40489            var processTime = rows.eq(0).find('input[type="number"]').val();
40490            if (!UTIL.isNumber(processTime)) { processTime = rows.eq(0).find('.wiz5-default-time-val').text(); }
40491
40492            if (UTIL.isNumber(processTime)) {
40493                processTime = parseInt(processTime);
40494                if (rows.eq(0).find(':checkbox').is(':checked')) { totalBlockTime += processTime; }
40495            } else {
40496                processTime = 0;
40497            }
40498
40499        //Step III: Get Finish Time
40500            var finishTime = rows.eq(1).find('input[type="number"]').val();
40501            if (!UTIL.isNumber(finishTime)) { finishTime = rows.eq(1).find('.wiz5-default-time-val').text(); }
40502
40503            if (UTIL.isNumber(finishTime)) {
40504                finishTime = parseInt(finishTime);
40505                if (rows.eq(1).find(':checkbox').is(':checked')) { totalBlockTime += finishTime; }
40506            } else {
40507                finishTime = 0;
40508            }
40509
40510        //Step IV: Set Total Time
40511            var total = svcTime + processTime + finishTime;
40512            
40513            if (total > 0) {
40514                total = total + ' ' + SA.Resource.Minutes.toLowerCase();
40515            } else {
40516                total = "";
40517            }
40518
40519            if (totalBlockTime > 0) {
40520                totalBlockTime = totalBlockTime + ' ' + SA.Resource.Minutes.toLowerCase();
40521            } else {
40522                totalBlockTime = "";
40523            }
40524
40525            rows.eq(2).find('.wiz5-total-processing').text(total);
40526            rows.eq(2).find('.wiz5-total-blocked-out').text(totalBlockTime);
40527    }
40528    
40529    _constructor.changeBlockOut = function() {
40530    	var input = $(this).closest('tr').find('input');
40531    	_constructor.changeTimeLength(input);
40532    }
40533    
40534    _constructor.textWhenClientUnconfirms = function(checkbox) {
40535    	if (!GLO.Info.isRequireGold(true)) {
40536    		$(checkbox).prop('checked', false);
40537    		return false;
40538    	}
40539    }
40540    
40541    _constructor.openHelpReputationManagement = function() {
40542    	var h1 = 'How Reputation Management Works';
40543    	var msg1 = '<p>Text Appointment Survey to Clients after appointment</p>';
40544    	var msg2 = '<p>Encourage happy customers to leave great reviews on your social media, while un-happy customers notify you directly (through email) of their complaints</p>';
40545    	
40546    	var alink = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'repman\', this, event, true)">Enable & Setup Reputation Management</a>';
40547    	var msg3 = '<div style="margin-bottom: 24px;">' + alink + '</div>';
40548    	
40549    	var htm = '<div>' + msg1 + msg2 + msg3 + '</div>';
40550		var ojInfo = GLO.UI.openHelp2(h1, htm, 'pop-help-rep-mgmt');
40551		var jpop = ojInfo.getPopup().addClass('pop-info2');
40552    }
40553    _constructor.openHelpAllowUnConfirm = function() {
40554    	var h1 = 'Allow Client to Un-Confirm Appointment';
40555    	var msg1 = '<p>You can allow your clients to un-confirm appointments from both the text reminder and email reminder</p>';
40556    	var msg2 = '<p>When a client un-confirms it does not delete the appointment, it adds a red vertical bar to the appointment on the calendar</p>';
40557    	
40558    	var alink = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=appointment&id=faq-appt-unconfirm-question\', this, event, true)">More on Client Un-Confirms</a>';
40559    	var msg3 = '<div style="margin-bottom: 24px;">' + alink + '</div>';
40560    	
40561    	var htm = '<div>' + msg1 + msg2 + msg3 + '</div>';
40562		var ojInfo = GLO.UI.openHelp2(h1, htm, 'pop-help-allow-unconfirm');
40563		var jpop = ojInfo.getPopup().addClass('pop-info2');
40564    }
40565    
40566    _constructor.openHelpBookEvery = function(isIncludeLink, isRequestAppt) {
40567    	var h1 = 'Time of Hour that Clients can Book Online';
40568		var arrow = ' <i>&#10143;</i></b> ';
40569		
40570		var cssTop = 'margin-bottom: 12px; color: #666;';
40571		
40572		if (innerWidth > 600) { cssTop += 'margin-left: -32px;'; }
40573		if (innerWidth < 720) { cssTop += 'letter-spacing: 0;'; }
40574		
40575		var msgTop = '<p style="' + cssTop + '">Determines times clients can book appointments (when you are available)</p>';
40576		
40577		var msg1 = '<p><b> 5 Minutes, on the hour' + arrow + '12:00, 12:05, 12:10, 12:15, 12:20, 12:25, ...</p>';
40578		var msg2 = '<p><b>10 Minutes, on the hour' + arrow + '12:00, 12:10, 12:20, 12:30, ...</p>';
40579		var msg3 = '<p><b>15 Minutes, on the hour' + arrow + '12:00, 12:15, 12:30, 12:45, 1:00, 1:15, ...</p>';
40580		var msg4 = '<p><b>30 Minutes, on the hour' + arrow + '12:00, 12:30, 1:00, 1:30, ...</p>';
40581		var msg5 = '<p><b>60 Minutes, on the hour' + arrow + '12:00, 1:00, 2:00, 3:00, ...</p>';
40582		
40583		if (UTIL.isEmpty(isIncludeLink)) {
40584			isIncludeLink = ($('#report-main.staff-profile-report').length === 0);
40585		}
40586		
40587		if (isIncludeLink) {
40588			var urlMoreInfo = 'reports/StaffProfile#tab=report-client-config&highlight=report-column-online-on-the-hour';
40589			var alink = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlMoreInfo + '\', this, event, true)" title="View & Change Book on the Hour Restriction">View & Change</a>';
40590	    	var msgLink = '<div style="margin-bottom: 24px;">' + alink + '</div>';
40591    	} else {
40592    		var msgLink = '';
40593    	}
40594    	
40595    	if (isRequestAppt) {
40596    		var htmRequestAppt = '<p style="margin-top: 32px;">Setting this value to anything other than <b class="narrow-text">Any Time</b> restricts the time range allowed to only normal business hours</p>';
40597    	} else {
40598    		var htmRequestAppt = '';
40599    	}
40600    	
40601    	var htm = '<div>' + msgTop + msg1 + msg2 + msg3 + msg4 + msg5 + msgLink + htmRequestAppt + '</div>';
40602		
40603    	var ojInfo = GLO.UI.openHelp2(h1, htm, 'pop-help-book-every');
40604		var jpop = ojInfo.getPopup().addClass('pop-info2');
40605    }
40606    
40607    _constructor.openHelpNeighborOpenings = function() {
40608    	var link = '<a onclick="GLO.Uri.gotoUri2(\'reports/StaffProfile?highlight=report-column-online-neighbor-only#tab=report-client-config\')">Neighbor Openings</a>';
40609    	var bNeighbor = '<b class="narrow-text">Neighbor Openings</b>';
40610    	var bOnHr = '<b class="narrow-text">On the Hour</b>';
40611    	var bArrow = '<b class="arrow-right">&#10140;</b>';
40612    	
40613    	var msg1 = '<p>' + bNeighbor + bArrow + ' available time on the calendar that begin or end next to an already existing appointment</p>';
40614    	
40615    	var msg2 = '<p>Can Allow ' + bNeighbor + ' close to the day of the appointment to book time that does not match your ' + bOnHr + ' setting</p>';
40616    	var msg3 = '<p style="margin-top: 0; font-size: 80%;">for example: useful if only allow appointments on the hour, but have some services that take less than 60 minutes</p>';
40617    	
40618    	var msg4 = '<p>Can only allow neighbor appointments <span class="narrow-text">(when day already has 2 or more appointments)</span></p>';
40619    	var msg5 = '<p></p>';
40620    	
40621    	var htm = '<div>' + msg1 + msg2 + msg3 + msg4 + msg5 + '</div>';
40622    	var ojInfo = GLO.UI.openHelp2('Neighbor Openings', htm, 'pop-help-neighbor-openings');
40623		var jpop = ojInfo.getPopup().addClass('pop-info2');
40624    }
40625	
40626    _constructor.askServicePriceDiff = function(staffid, priceDiffCount) {
40627    	if (priceDiffCount > 0) {
40628    		var htm = '<p>Update ' + UTIL.pluralLabel(priceDiffCount, 'upcoming appointment') + ' to the new price?</p>';
40629    		var fnYes = function() { Wiz5.updateNewServicePrice(staffid); };
40630    		
40631    		GLO.Popup.Confirm.open(htm, 'Update to New Price?', fnYes);
40632    	}
40633    }
40634    
40635    _constructor.updateNewServicePrice = function(staffid, sgid) {
40636    	var url = GLO.Link.Object.Provider.Ajax + 'ScheduleUpdatePrice?staff=' + UTIL.cleanString(staffid) + '&sgid=' + UTIL.cleanString(sgid);
40637        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
40638                .success(function(data, textStatus, jqXHR) {
40639                    
40640                })
40641                .error(function(jqXHR, textStatus, errorThrown) {
40642                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
40643                });
40644    }
40645    
40646    return _constructor;
40647})();
40648
40649
40650var Wiz6 = (function() {
40651    function _conWiz6(name) { }
40652	
40653	_conWiz6.init = function() {
40654		WIZ.init(6, '#wiz6-main');
40655	    _initWizButtons();
40656	    
40657	    $('#wiz-arrowRight').addClass('hide');
40658	    Wiz6.changeCardType();
40659	    _displaySuccessPopup();
40660	    _initNewCard();
40661	    _initWiz6Url();
40662	}
40663	function _initWiz6Url() {
40664		var warning = UTIL.cleanString(GLO.Uri.url('warning'));
40665		
40666		if (!UTIL.isEmpty(warning)) {
40667			GLO.Popup.Warning.open('<div id="pop-warn-wiz6">' + warning + '</div>', 'Card Not Updated');
40668		}
40669		
40670		GLO.Report.Other.initUrl();
40671	}
40672	function _initNewCard() {
40673		var jexpire = $('#wiz6-main #upgrade-package-trial-expiration-days');
40674		
40675		if (jexpire.length == 0) {
40676			jexpire = $('#wiz6-main #upgrade-package-trial-expiration-date');
40677	    }
40678	    
40679	    if (jexpire.length > 0) {
40680		    var dtUpdate = $('#wiz6-main #Last_Update_dt').val();
40681		    var dtToday = new Date(new Date().toGloDate());
40682		    var trialExpiresInDays = $('#upgrade-package-trial-expiration-days').attr('trial_ends_in_days_sr');
40683		    
40684		    if (GLO.Data.provider.payment_progress_cd == 10) {
40685		    //if (UTIL.isDate(dtUpdate) && UTIL.isToday(dtUpdate)) {
40686		    	if (trialExpiresInDays > 0) {
40687		    		var msg = '<div>Your trial expires in ' + UTIL.pluralLabel(trialExpiresInDays, 'day') + '</div>';
40688		    	} else {
40689		    		var msg = '<div>Thank you for updating your card information</div>';	// <div>Your card will be processed tonight</div>';
40690		    	}
40691		    	
40692		    	jexpire.after('<div class="upgrade-package-trial-expire" style="margin-top: 20px;">' + msg + '</div>');
40693		    }
40694	    }
40695	}
40696	
40697	function _initWizButtons() {
40698		var jwizBtns = $('.wiz-buttons').removeClass('hide');
40699	    var jwiz6cc = $('#wiz6-creditcard');
40700	    
40701	    if (jwiz6cc.length > 0) {
40702	    	jwizBtns.css({ "position": "relative", "bottom": "inherit", "height": "60px", "margin-top": "32px", "margin-bottom": "80px", "padding-top": "12px", "padding-bottom": "16px" });
40703	    	jwiz6cc.after(jwizBtns);
40704	    }
40705	    
40706	    if (!UTIL.isEmpty(jwiz6cc.find('#Card_Number_vc').val())) {
40707	    	var btnText = SA.Resource.UpdateCreditCard;
40708	    } else if (GLO.Data.provider.signupDetail == 20) {
40709	    	var btnText = SA.Resource.Upgrade;
40710	    } else {
40711	    	var btnText = SA.Resource.AddCreditCard;
40712	    }
40713	    
40714	    var pstatus = parseInt($.cookies.get('pstatus'));
40715	    var cssJson = { "position": "relative", "right": "inherit", "margin-left": "0" };
40716	    
40717	    if (GLO.Provider.isPaidAccount()) {
40718	        $('#wiz6-trial').removeClass('hide');
40719	        $('#Provider_Status_cd1').prop('checked', true);
40720	    } else if (pstatus < 11) {       // > 7, but not 11 (ie. trial or inactive)
40721	        btnText = SA.Resource.SignUp;
40722	        cssJson = { };
40723        }
40724
40725	    var btnNext = jwizBtns.find('#btnNext').css(cssJson).find('a').text(btnText).css({ "letter-spacing": "1px" });
40726
40727	    if (WIZ.isWizard) {
40728	    	jwizBtns.find('#btnPrev').removeClass('hide').css({ "margin-right": "90px" });
40729	    } else {
40730	    	btnNext.css({ "padding": "8px 16px 6px", "font-size": "20px" });
40731	    }
40732	}
40733	
40734	function _displaySuccessPopup() {
40735		var upgrade = UTIL.cleanString(GLO.Uri.url('upgrade')).toLowerCase();
40736	    
40737	    if (upgrade === 'success') {
40738	    	var packageName = SA.Upgrade.getPackageName(GLO.Info.providerPackage);
40739	    	
40740	    	if (GLO.Info.providerPackage == 2) {
40741	    		var h1 = SA.Resource.UpgradeSuccessful;
40742	    		var msg = SA.Resource.AccountSuccessfullyUpgraded + ' ' + packageName + ' ' + SA.Resource.Package;
40743	    	} else {
40744	    		var h1 = SA.Resource.PackageChanged;
40745	    		var msg = SA.Resource.AccountSuccessfullyChanged + ' ' + packageName + ' ' + SA.Resource.Package;
40746	    	}
40747	    	
40748	    	//var fnReload = function() { location.reload(); }
40749	    	
40750	    	var htm = '<div id="pop-success-apple-subscription"> <div class="friendly-msg2" style="padding-bottom: 8px;">' + msg + '</div></div>';		//<h1 class="friendly-msg2">' + h1 + '</h1>
40751	    	var jpop = GLO.Popup.Processing.open(htm, h1);		//, fnReload		//.getPopup().css({ "padding-bottom": "8px" });
40752	    	//jpop.find('.pop-icon').attr('id', 'success-icon');
40753	    	//setTimeout(fnReload, 9500);
40754	    }
40755	}
40756	
40757	_conWiz6.changeCardType = function () {
40758        var tmp = $('#Card_Type_cd').val();
40759        
40760        if (tmp == "3") {
40761            $("#Card_Number_vc").mask("cccc cccccc c9999");
40762            $("#CCV_Code_vc").mask("bbbb");
40763            $("#Card_Number_vc").focus();
40764        } else {		//if (tmp == "1" || tmp == "2" || tmp == "3") {
40765            $("#Card_Number_vc").mask("cccc cccc cccc 9999");
40766            $("#CCV_Code_vc").mask("bbb");
40767            $("#Card_Number_vc").focus();
40768        }
40769    }
40770
40771    _conWiz6.signupClick = function (me) {
40772        me = $(me);
40773
40774        if ($.cookies.get('pstatus') == '11') {
40775            $('#btnNext').find('a').text(SA.Resource.Save);
40776        } else {
40777            if (me.attr('id') === 'Provider_Status_cd1') {
40778                $('#btnNext').find('a').text(SA.Resource.SignUp);
40779                $('#wiz6-main .reqlater').removeClass('reqlater').addClass('required');
40780                $('#wiz6-creditcard').removeClass('hide2');
40781            } else {
40782                $('#btnNext').find('a').text(SA.Resource.SignUp);
40783                $('#wiz6-main .required').removeClass('required').addClass('reqlater');
40784                $('#Zip_vc').removeClass('required');
40785                $('#wiz6-creditcard').addClass('hide2');
40786                UTIL.Validate.resetForm(WIZ.pageContext);
40787            }
40788        }
40789    }
40790	
40791    return _conWiz6;
40792})();
40793
40794
40795SA.Profile = (function() {
40796    function _conProfile() { }
40797    
40798    _conProfile.initTraveler = function() {
40799    	GLO.Info.init();
40800    	var j = $('#traveler-edit.main-screen');
40801    	
40802    	//if (GLO.Provider.isManagerCheck('Travelers', j, true)) {
40803	    	j.find('input, select, textarea').change( function() { 
40804	            j.find('.btnSave a').addClass('unsaved-change');
40805	        });
40806	        
40807	        j.find(':text, textarea').keyup( function() { 
40808	            j.find('.btnSave a').addClass('unsaved-change');
40809	        });
40810        //}
40811    }
40812    _conProfile.saveTraveler = function() {
40813    	var url = GLO.Link.Page.Provider.Home + 'manage/traveler';
40814    	var j = $('#traveler-edit');
40815    	
40816    	var qr = j.find('#Traveler_QR_fl').prop('checked');
40817    	var noteFontSize = j.find('#Traveler_Note_Font_Size_sr').val();
40818    	var note = UTIL.htmlEncode(j.find('#Traveler_Note_vc').val());
40819    	var jd = { "qr": qr, "note": note, "noteSize": noteFontSize };
40820    	
40821        GLO.UI.Form.beginProcessing( j.find('.btnSave') );
40822        
40823        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
40824            .success(function (data, textStatus, jqXHR) {
40825                GLO.UI.Form.resetProcessing();
40826                GLO.Popup.Success.open('Receipt Changes Saved', 'Edit Receipt');
40827                
40828                j.find('.btnSave a').removeClass('unsaved-change');
40829            })
40830            .error(function (jqXHR, textStatus, errorThrown) {
40831                GLO.UI.Form.resetProcessing();
40832                //new GLO.Popup.Warning('Saving note processing taking longer than normal');
40833            });
40834    }
40835    
40836    _conProfile.initReceipt = function(merchantIdString) {
40837    	GLO.Info.init();
40838    	var j = $('#receipt-edit');
40839    	
40840    	//if (GLO.Provider.isManagerCheck('Receipt', j, true)) {
40841	    	j.find('input, select, textarea').change( function() { 
40842	            j.find('.btnSave a').addClass('unsaved-change');
40843	        });
40844        //}
40845        
40846        if (!UTIL.isEmpty(merchantIdString)) {
40847			var isDisplayPrintOptions = !UTIL.isEmpty($.cookies.get('emv-print'));
40848			
40849			if (isDisplayPrintOptions) {
40850				SA.POS.CCBolt.displayPrinterOptions('Clover');
40851			}
40852			
40853			SA.POS.CCBolt.listTerminalDetailsWithCallback(merchantIdString, function(json) {           //GLO.Data.provider.merchants[0].idString
40854			    SA.POS.CCBolt.loadPrinterSettings(json);
40855			});
40856		}
40857    }
40858    _conProfile.saveReceipt = function() {
40859    	var url = GLO.Link.Page.Provider.Home + 'manage/receipt';
40860    	var j = $('#receipt-edit');
40861    	
40862    	var rtype = j.find('#Auto_Receipt_cd').val();
40863    	var drawer = j.find('#Cash_Drawer_Setting_cd').val();
40864    	var space = j.find('#Receipt_White_Space_cd').val();
40865    	var layout = j.find('#Receipt_Layout_cd').val();
40866    	var lineItem = j.find('#Receipt_Line_Item_cd').val();
40867    	
40868    	var fontSize = j.find('#Receipt_Font_Size_sr').val();
40869    	var note = UTIL.htmlEncode(j.find('#Receipt_Note_vc').val());
40870    	var noTip = !j.find('#Receipt_Display_Tip_fl').prop('checked');			//Receipt_No_Tip_fl
40871    	var hideLoyalty = j.find('#Display_Loyalty_On_Receipt_fl').length && !j.find('#Display_Loyalty_On_Receipt_fl').prop('checked');
40872    	var linkSetting = j.find('#Receipt_Link_cd').val();
40873    	
40874    	var jd = { "rtype": rtype, "drawer": drawer, "space": space, "layout": layout, "lines": lineItem
40875    			, "fontsize": fontSize, "notip": noTip, "note": note, "hideLoyalty": hideLoyalty, "link": linkSetting };
40876    	
40877        GLO.UI.Form.beginProcessing( j.find('.btnSave') );
40878        
40879        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
40880            .success(function (data, textStatus, jqXHR) {
40881                GLO.UI.Form.resetProcessing();
40882                GLO.Popup.Success.open('Receipt Changes Saved', 'Edit Receipt');
40883                
40884                j.find('.btnSave a').removeClass('unsaved-change');
40885            })
40886            .error(function (jqXHR, textStatus, errorThrown) {
40887                GLO.UI.Form.resetProcessing();
40888                //new GLO.Popup.Warning('Saving note processing taking longer than normal');
40889            });
40890    }
40891    
40892    _conProfile.Reminder = (function() {
40893    	function _conReminder() {};
40894    	var _isLoading = true;
40895    	
40896    	_conReminder.init = function() {
40897    		GLO.Info.init();
40898    		SA.TextEditor.init($('#appointment-policy-full .sa-text-editor'), 'Appointment Policy Summary');
40899    		SA.TextEditor.init($('#appointment-policy-full .sa-text-editor'), 'Full Appointment Policy');
40900    		
40901    		if (GLO.Info.roleType < 220) {
40902    			var msg = 'To make changes logout and login as a manager or admin';
40903    			GLO.Popup.Warning.open(msg, 'Read-Only Mode');
40904    			
40905    			$('#customize-reminder').find('input').prop('disabled', true);
40906    		} else {
40907    			var j = $('#customize-reminder');
40908    			var btnSave = j.find('.btnSave');
40909    			
40910    			j.find(':radio, :checkbox, select').change(function() { UI.buttonDisplayChange(btnSave); });
40911    			j.find(':text, textarea, .sa-text-editor').keyup(function() { UI.buttonDisplayChange(btnSave); });
40912    		}
40913    		
40914    		_conReminder.changeMessageGenerate();
40915    		_initUrlActions();
40916    		_isLoading = false;
40917    	}
40918    	
40919    	function _initUrlActions() {
40920	    	//var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
40921	    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
40922	    	
40923	    	if (!UTIL.isEmpty(highlight)) {
40924				var jhighlight = $('#' + highlight + ', .' + highlight);
40925				
40926				if (jhighlight.length > 0) {
40927					UI.highlight(jhighlight, 800, 6400, true);
40928				}
40929			}
40930		}
40931    	
40932    	_conReminder.changeMessageGenerate = function() {
40933    		var j2 = $('#customize-reminder #customize-reminder-note2');
40934    		var gen2 = j2.find('input[type="radio"][name="Text2_Reminder_Generate_cd"]:checked').val();
40935    		var jnote2 = j2.find('#Text2_Reminder_Note_vc');
40936    		var orig = UTIL.cleanString(jnote2.attr('original_value'));
40937    		var pname = GLO.Data.provider.name.replace('&amp;', '&').replace('&quot;', '"').replace('&apos;', '"');
40938    		var defaultCustomNote = 'Hi {client-first-name}, this is ' + pname + '. We look forward to seeing you {appointment-day} at {appointment-time} for your appointment';
40939    		
40940    		if (gen2 == 20) {
40941    			j2.addClass('generate-message-custom').removeClass('generate-message-default');
40942    			
40943    			if (!_isLoading) {
40944    				jnote2.attr('original_value', jnote2.val());
40945    				jnote2.val( UTIL.coalesceString(orig, defaultCustomNote) );
40946    			}
40947    		} else {
40948    			if (!_isLoading) {
40949    				jnote2.attr('original_value', jnote2.val());
40950    				jnote2.val(orig);
40951    			}
40952    			
40953    			j2.addClass('generate-message-default').removeClass('generate-message-custom');
40954    		}
40955    	}
40956    	
40957    	_conReminder.helpCustomMessage = function() {
40958			var ulstyle = 'text-align: left;', style = 'white-space: pre-wrap; line-height: 170%;';
40959			var p = '<p style="margin-bottom: 12px;">';
40960			
40961			if (GLO.Info.isMobile()) {
40962				ulstyle = 'margin-left: -36px; margin-right: 0;';
40963				style += ' padding-right: 8px;';
40964			}
40965			
40966			var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">' + SA.Resource.HowMessageIsCreatedUsingAutofills + '</h1>'
40967						+'<div>'
40968							+ '<div class="friendly-msg" style="' + style + '">'
40969								+ p + 'You can change the message as desired.  Some information in the message can be populated for you.</p>'
40970								+ p + 'For example, <i><b>{client-name}</b></i> indicates that the client\'s name will be placed there in the message.</p>'
40971								+ p + 'Text message can only be 160 characters so if longer message will be truncated.</p>'
40972								+ p + 'Below are some other auto-fills:</p>'
40973								+ '<ul style="' + ulstyle + '">'
40974									+ '<li><i style="padding-right: 6px;"><b>{client-first-name}</b></i> Client First Name</li>'
40975									+ '<li><i style="padding-right: 6px;"><b>{client-name}</b></i> Client Name</li>'
40976									+ '<li><i style="padding-right: 6px;"><b>{business-name}</b></i> Business Name</li>'
40977									
40978									+ '<li><i style="padding-right: 6px;"><b>{staff-first-name}</b></i> Staff First Name</li>'
40979									+ '<li><i style="padding-right: 6px;"><b>{staff-name}</b></i> Staff Name</li>'
40980									+ '<li><i style="padding-right: 6px;"><b>{service-name}</b></i> Service Name</li>'
40981									
40982									+ '<li><i style="padding-right: 6px;"><b>{appointment-day}</b></i> Appointment day<span class="narrow-text">today, tomorrow, or actual day if further in future</span></li>'
40983									+ '<li><i style="padding-right: 6px;"><b>{appointment-time}</b></i> Appointment time</li>'
40984								+ '</ul>'
40985							+ '</div>'
40986							+ '<div style="margin-left: -32px; margin-top: 20px; margin-bottom: 24px;"> <i style="padding-right: 8px;">Have More Questions?</i>  <a href="/contact">Contact Us</a></div>'
40987						+ '</div>'
40988					+ '</div>');
40989			 var oj = new GLO.Popup.Info(htm);
40990			 
40991			 if (GLO.Info.isMobile()) {
40992			 	oj.getPopup().find('.msg').css({ "padding-right": "4px" });
40993			 }
40994			 
40995			 return oj
40996		}
40997    	
40998    	_conReminder.save = function() {
40999    		var j = $('#customize-reminder');
41000    		var url = GLO.Link.WebsiteDomain + 'message/CustomizeReminder';
41001			
41002			var displayStaff = j.find('#customize-reminder-display-staff').find('input[name="display-staff"]:checked').val();
41003			var note = UTIL.htmlEncode(j.find('#Text_Reminder_Note_vc').val());
41004			var note2 = UTIL.htmlEncode(j.find('#Text2_Reminder_Note_vc').val());
41005			var gen2 = j.find('input[type="radio"][name="Text2_Reminder_Generate_cd"]:checked').val();
41006			var isDisplayDate = j.find('#Text_Reminder_Display_DateTime_fl').prop('checked');
41007			var policyHeader = UTIL.htmlEncode(j.find('#Policy_Header_vc').val());
41008			
41009			var policyQuick = '', customHtmQuick = j.find('#appointment-policy-quick .sa-text-editor')[0].innerHTML;
41010			var policyFull = '', customHtmFull = j.find('#appointment-policy-full .sa-text-editor')[0].innerHTML;
41011			
41012			if (!UTIL.isEmpty(customHtmQuick)) {
41013				policyQuick = UTIL.htmlEncode(DOMPurify.sanitize(customHtmQuick));
41014			}
41015			if (!UTIL.isEmpty(customHtmFull)) {
41016				policyFull = UTIL.htmlEncode(DOMPurify.sanitize(customHtmFull));
41017			}
41018			
41019			var jd = { "note": note, "note2": note2, "displayStaff": displayStaff, "isDisplayDate": isDisplayDate, "generate2": gen2
41020					, "policyHeader": policyHeader, "policyQuick": policyQuick, "policyFull": policyFull };
41021			
41022    		GLO.UI.Form.beginProcessing(j.find('.btnSave'));
41023			
41024	        var jqxhr = $.ajax({ type: "POST", url: url, "data": jd, "cache": false })
41025	            .success(function(data, textStatus, jqXHR) {
41026	                GLO.UI.Form.resetProcessing(null, true);
41027	                var jd = $(data);
41028	                var newSampleText = jd.find('#sample-text-reminder').outerHTML();
41029	                var jsample = j.find('#customize-reminder-sample');
41030	                
41031	                if (jd.hasClass('warning')) {
41032	                	//GLO.Popup.Warning.open(jd.outerHTML(), 'Unable to Save Changes');
41033	                	var ojpop = new GLO.Popup.Custom(jd);
41034						var jpop = ojpop.getPopup().addClass('no-persist').attr('id', 'pop-bulk-deliverability-score');
41035						//var score = jd.find('h2 b').text();
41036						
41037						GLO.Popup.Custom.singleButton(jpop, 'Close');
41038						ojpop.realign(); ojpop.realign();
41039	                } else if (jd.hasClass('is-success')) {
41040		                if (gen2 > 0) {
41041		                	GLO.Popup.Success.open('Changes Saved, Loading Changes..', 'Save Successful');
41042		                	
41043		                	setTimeout(function() { location.reload(); }, 1500);
41044		                }
41045		                
41046		                jsample.find('.sample').html(newSampleText);
41047		                UI.highlight(jsample, 200, 3600);
41048		                
41049		                setTimeout(function() {
41050		                	jsample.removeClass('highlight-background-undo');
41051		                }, 4200);
41052	                }
41053	            })
41054		        .error(function(jqXHR, textStatus, errorThrown) {
41055		            GLO.UI.Form.resetProcessing();
41056		            GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41057		        });
41058	    }
41059    	
41060	    return _conReminder;
41061	})();
41062    
41063    return _conProfile;
41064})();
41065
41066
41067SA.Profile.Language = (function() {
41068    function _conLang() { }
41069    
41070    _conLang.openPopup = function() {
41071		var jpop = $('#pop-language-change');
41072		
41073		jpop = new GLO.Popup.Custom(jpop).getPopup();
41074    	var jbtns = jpop.find('.pop-buttons').css({ "width": "300px" });
41075		
41076		jbtns.find('.btnSave').remove();
41077		jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css( { "float": "none", "width": "60px", "margin": "inherit", "letter-spacing": "1px" }).find('a').text(SA.Resource.Close);
41078	}
41079	
41080	_conLang.save = function(newLanguage, btn) {
41081		var icon = $('#select-language-icon');
41082		GLO.UI.Form.beginProcessing(icon);
41083		
41084		$(btn).fadeOut(2400, function() {
41085		    var jpop = $('#pop-language-change');
41086		    var msg = '<div class="is-reloading">' + jpop.find('.pop-language-select').attr('loading') + '</div>';
41087		    
41088		    //jpop.find('.pop-language-select').remove();
41089		    jpop.find('div.friendly-msg2').html(msg);
41090		    jpop.find('.is-reloading').fadeIn(2400);
41091		  });
41092		
41093		var url = GLO.Link.WebsiteDomain + "provider/ajax/language?language=" + newLanguage;
41094        
41095        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
41096            .success(function(data, textStatus, jqXHR) {
41097                location.reload();
41098                //GLO.UI.Form.resetProcessing();
41099                //var j = el.closest('#language-icons').find('.hide').removeClass('hide');
41100				//$.cookies.set("language", language);
41101            })
41102	        .error(function(jqXHR, textStatus, errorThrown) {
41103	            GLO.UI.Form.resetProcessing();
41104	            
41105	            var jpop = $('#pop-language-change').closest('.glopop');
41106	            GLO.Popup.close(jpop);
41107	            
41108	            GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);		//GLO.Popup.Error('An error occurred.  Unable to make save your changes at this time.');
41109	        });
41110	}
41111	
41112    return _conLang;
41113})();
41114
41115
41116SA.Profile.Email = (function() {
41117    function _conProfileEmail(name) { }
41118    
41119    _conProfileEmail.init = function() {
41120		$('#Email_Appt_Footer_vc, #From_Email_vc, #From_Email_Display_vc, .sa-text-editor').on('keyup', function() {
41121			$('#email-footer-container').find('.btnSave > a').css({ "border": "3px solid Red" });
41122		});
41123		
41124		$('.wiz-buttons, #wiz-button-top-padding').remove();
41125		
41126		SA.TextEditor.init($('.sa-text-editor'), 'Email Footer');
41127		//GLO.Info.displayHelloBarBack('Advanced Setup', '/provider/manage/advanced');
41128	}
41129	
41130	function _fromIsValid(email) {
41131		var msg = null;
41132		email = email.toLowerCase();
41133		
41134		if (!UTIL.Validate.email(email)) {
41135			_displayFromInvalidPopup(SA.Resource.PleaseEnterValidEmail);
41136			return false;
41137		}
41138		
41139		if (email.indexOf('@yahoo') !== -1) {
41140			msg = 'Cannot Use Yahoo Email Address';
41141		} else if (email.indexOf('@hotmail') !== -1) {
41142			msg = 'Cannot Use Hotmail Email Address';
41143		} else if (email.indexOf('@live') !== -1) {
41144			msg = 'Cannot Use Microsoft Live Email Address';
41145		} else if (email.indexOf('@outlook') !== -1) {
41146			msg = 'Cannot Use Outlook Email Address';
41147		} else if (email.indexOf('@apple') !== -1) {
41148			msg = 'Cannot Use Apple Email Address';
41149		} else if (email.indexOf('@aol') !== -1) {
41150			msg = 'Cannot Use Aol Email Address';
41151		} else if (email.indexOf('@mail') !== -1 || email.indexOf('@gmx') !== -1) {
41152			msg = 'Cannot Use GMX Email Address';
41153		} else if (email.indexOf('@facebook') !== -1 || email.indexOf('@gmx') !== -1) {
41154			msg = 'Cannot Use Facebook Email Address';
41155		} else if (email.indexOf('@gmail') !== -1 || email.indexOf('@gmx') !== -1) {
41156			msg = 'Cannot Use Gmail Email Address';
41157		}
41158		
41159		if (msg !== null) {
41160			var h4style = 'margin-left: -44px; letter-spacing: 1px; font-size: 16px;';
41161			var p = '<p style="min-width: 260px; margin-top: 16px; line-height: 180%;">';
41162			var p3 = ' does many things to ensure deliverability, so we suggest keeping the default from email address the same and instead change the <b class="narrow-text">From Display Name</b>';
41163			
41164			var htm = '<div style="margin-bottom: 12px; padding-bottom: 16px;"> <h4 style="' + h4style + '">' + msg + '</h4>'
41165			 				+ p + SA.Resource.EmailSetup1 + '</p>'
41166							+ p + SA.Resource.EmailSetup2 + '</p>'
41167							+ p + GLO.Info.getScheduleAnyoneHtm() + p3 + '</p>'
41168						+ '</div>';
41169			
41170			$('#From_Email_vc').val('[email protected]');
41171			
41172			_displayFromInvalidPopup(htm);
41173			return false;
41174		} else {
41175			return true;
41176		}
41177	}
41178	
41179	function _displayFromInvalidPopup(msg) {
41180		var htm = $('<div>' + msg + '</div>');
41181		return new GLO.Popup.Warning(htm, function() {
41182			$('#From_Email_vc').focus();
41183		});
41184	}
41185	
41186	_conProfileEmail.fromHelp = function() {
41187		var style = 'white-space: pre-wrap; line-height: 170%;';
41188		var p = '<p style="margin-bottom: 12px; line-height: 1.3;">';
41189		var p2 = '<p style="margin-top: 24px; line-height: 1.3;">';
41190		
41191		var msgAutomatedEmails = 'automated emails <span class="narrow-text">(like confirmations, reminders, receipts, follow-ups, etc)</span>';
41192		var hrefGoogleRequirements = 'https://support.google.com/a/answer/81126?visit_id=638569182043216159-3939602876&rd=1#zippy=%2Crequirements-for-all-senders';
41193		var aGoogleRequirements = '<a href="' + hrefGoogleRequirements + '" style="font-family: Arial; font-stretch: condensed;">https://support.google.com/a/answer/81126</a>';
41194		var bArrow = '<b class="html-arrow"></b>';
41195		
41196		var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">' + SA.Resource.SendEmailsFromYourDomain + '</h1>'
41197					+'<div style="margin-bottom: 20px;">'
41198						+ '<div class="friendly-msg" style="' + style + '">'
41199							+ p + SA.Resource.SendEmailsFromYourDomainHelp1 + '</p>'
41200							+ p + SA.Resource.SendEmailsFromYourDomainHelp2 + '</p>'
41201							+ p + SA.Resource.SendEmailsFromYourDomainHelp3 + '</p>'
41202							
41203							+ p2 + 'Many of the major email apps (like Yahoo and Gmail) have been requiring more security settings from the domain sending the emails' + '</p>'
41204							+ p + 'If you send ' + msgAutomatedEmails + ' from your own domain then you might not have these DNS settings on your domain which could reduce deliverability' + '</p>'
41205							
41206							+ p + GLO.Info.getScheduleAnyoneHtm() + ' is continuously evolving with the changing standards and requirements.  '
41207								+ 'If clients are having issues receiving emails, then we suggest not using your custom email address '
41208								+ 'and instead use the <b class="narrow-text">From Email Display Name</b> feature; '
41209								+ 'this way even though the emails are sent from <span class="narrow-text">[email protected]</span> ' + bArrow 
41210								+ ' your clients will see your <b class="narrow-text">From Email Display Name</b></p>'
41211							
41212							+ p2 + 'If you want to continue sending emails from your domain then here are Google\'s requirements for sending to gmail addresses: ' + aGoogleRequirements + '</p>'
41213						+ '</div>'
41214						+ '<div style="margin-top: 20px;"> <i style="padding-right: 8px;">' + SA.Resource.HaveMoreQuestions + '?</i>  <a href="/contact">' + SA.Resource.ContactUs + '</a></div>'
41215					+ '</div>'
41216				+ '</div>');
41217		return new GLO.Popup.Info(htm);
41218	}
41219	
41220	_conProfileEmail.fromDisplayNameHelp = function() {
41221		var style = 'white-space: pre-wrap; line-height: 170%;';
41222		var p = '<p style="margin-bottom: 12px;">';
41223		
41224		var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">From Email Display Name</h1>'
41225					+'<div>'
41226						+ '<div class="friendly-msg" style="' + style + '">'
41227							+ p + 'When ' + GLO.Info.getScheduleAnyoneHtm() + ' sends emails to your clients the from email address will use this <b>Display Name</b></p>'
41228						+ '</div>'
41229					+ '</div>'
41230				+ '</div>');
41231		return new GLO.Popup.Info(htm);
41232	}
41233	
41234	_conProfileEmail.saveEmailApptFooter = function() {
41235		var j = $('#email-attributes');
41236		var jsave = j.find('.btnSave');
41237		var efrom = UTIL.cleanString(j.find('#From_Email_vc').val());
41238		var efromDisplay = UTIL.cleanString(j.find('#From_Email_Display_vc').val());
41239		
41240		if (efrom !== '') {
41241			if ( !_fromIsValid(efrom)) { return; }
41242		}
41243		
41244		var efooter = '';			//UTIL.htmlEncode(j.find('#Email_Appt_Footer_vc').val());
41245        var customHtm = j.find('.sa-text-editor')[0].innerHTML;
41246        
41247		if (!UTIL.isEmpty(customHtm)) {
41248			efooter = UTIL.htmlEncode(DOMPurify.sanitize(customHtm));
41249		}
41250		
41251        var url = GLO.Link.Page.Provider.WebTemplate + 'SaveEmailTemplate';
41252        GLO.UI.Form.beginProcessing(jsave);
41253
41254        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "Email_Appt_Footer_vc": efooter, "From_Email_vc": efrom, "From_Email_Display_vc": efromDisplay } })
41255            .success(function(data, textStatus, jqXHR) {
41256                GLO.UI.Form.resetProcessing();
41257                $('.btnSave:visible a').css({ "border": "3px solid transparent" });
41258                
41259                new GLO.Popup.Success(SA.Resource.ChangesSaved);
41260            })
41261            .error(function(jqXHR, textStatus, errorThrown) {
41262                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41263            });
41264	}
41265	
41266    return _conProfileEmail;
41267})();
41268
41269
41270SA.Note = (function() {					//= Client Note History
41271    function _conNote(name) { }
41272    
41273    _conNote.init = function() {
41274		$('#note-header').find('textarea').on('keyup', SA.Note.changeNote);
41275		
41276		var h2 = $('#note-history').find('h2');
41277		var cname = '<span>' + h2.find('span').text() + '</span>';
41278		
41279		//if (innerWidth > 600) { cname += ' <i>' + SA.Resource.Notes + '</i>'; }
41280		h2.html(cname + ClientProfile.getDropIcon());
41281		ClientProfile.clearUnlockPassword();
41282		
41283		$('#note-history').find('.client-image img').on('click', UserPortal.StaffNote.openImage);
41284		_initNoteLinks();
41285	}
41286	
41287	function _initNoteLinks() {
41288    	var jhistory = $('#note-history');
41289    	var jclientNote = jhistory.find('#Other_Note_vc');
41290    	var japptNotes = jhistory.find('.note-staff-only');
41291    	
41292    	var clientNote = $.trim(jclientNote.val());
41293    	
41294    	const urlPattern = /(?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\/[^\s]*)?/gi;
41295    	const urls = clientNote.match(urlPattern);
41296    	
41297    	if (urls && urls.length > 0) {
41298	    	for (var i = urls.length; i > 0; i--) {
41299	    		var maxWidth = (jhistory.width() - 40);
41300	    		var onClick = 'SA.App.openLinkInBrowser(\'' + urls[i-1] + '\', this, event, true)';
41301	    		var htmLink = '<div class="client-note-link"><a onclick="' + onClick + '" style="max-width: ' + maxWidth + 'px;">' + urls[i-1] + '</a></div>';
41302	    		
41303	    		jclientNote.after(htmLink);
41304	    	}
41305    	}
41306    	
41307    	for (var c = 0; c < japptNotes.length; c++) {
41308    		var note = japptNotes.eq(c).text();
41309    		const urls = note.match(urlPattern);
41310    		
41311    		if (urls && urls.length > 0) {
41312	    		for (var i = urls.length; i > 0; i--) {
41313		    		var onClick = 'SA.App.openLinkInBrowser(\'' + urls[i-1] + '\', this, event, true)';
41314		    		var htmLink = '<div class="client-note-link"><a onclick="' + onClick + '">' + urls[i-1] + '</a></div>';
41315		    		
41316		    		note = note.replace(urls[i-1], htmLink);
41317		    	}
41318		    	
41319		    	japptNotes.eq(c).html(note);
41320	    	}
41321    	}
41322    }
41323	
41324	_conNote.openHelp = function() {
41325		var jpop = $('#pop-note-history-help');
41326    	var jpop = new GLO.Popup.Custom(jpop).getPopup()
41327    	
41328    	var jbtns = jpop.find('.pop-buttons');
41329    	jbtns.find('.btnSave').remove();
41330    	jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').find('a').text('Close');
41331	}
41332	
41333	_conNote.changeNote = function() {
41334		var div = $(this).parent().addClass('edit-note');
41335		div.find('.btnSave > a').css({ "border": "3px solid red" });
41336	}
41337	
41338	_conNote.open = function(cid, useCurrentModal, smid) {
41339		var url = location.protocol + '//' + location.host + '/provider/NoteHistory?clientId=' + cid;
41340		
41341		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
41342            .success(function(data, textStatus, jqXHR) {
41343            	if (ClientProfile.isFullPageProfile()) {
41344            		UI.closeAllPopups();
41345            		var jcontainer = $('.shadow-content0').html(data);
41346            	} else if (useCurrentModal) {
41347            		var throbber = $('.loading-client-quick-view').remove();
41348            		var jcontainer = $('#simplemodal-container');
41349            		
41350            		if (jcontainer.length === 1) {
41351            			jcontainer.find('> .simplemodal-wrap').html(data);
41352            		} else if (throbber.length === 1) {
41353            			$('.shadow-content0').html(data);
41354            		}
41355            	}
41356            	
41357            	_conNote.postOpen(smid);
41358        	})
41359            .error(function(jqXHR, textStatus, errorThrown) {
41360                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41361            });
41362	}
41363	
41364	_conNote.postOpen = function(smid) {
41365		if (innerWidth > 780) {				//if (!GLO.Info.isMobile()) { $.modal.update(620, 670); }
41366			$.modal.update(600, 760);
41367		} else {
41368			$('#simplemodal-container').css({ "width": "inherit" });
41369			$.modal.update(600, null);
41370		}
41371        
41372        var pop = $('#simplemodal-container').css({ "padding": "0", "background": "" });
41373        pop.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
41374        pop.find('.simplemodal-data').css({ "padding": "0" });
41375        
41376        if (pop.width() < 760 && innerWidth > 780) {
41377        	$.modal.update(600, 760);
41378        } else if (pop.width() < 700 && innerWidth > 720) {
41379        	$.modal.update(600, 700);
41380        } else if (pop.width() < 600 && innerWidth > 620) {
41381        	$.modal.update(600, 600);
41382        }
41383        
41384        ClientProfile.openNoteHistoryCompleted(smid);
41385	}
41386	
41387	_conNote.save = function(btn) {
41388		var cid = $('#note-history').find('h2').attr('client_id');
41389		var jsave = $(btn);
41390		var div = jsave.closest('.edit-note');
41391		var jtext = div.find('textarea');
41392		var note = UTIL.htmlEncode(jtext.val());
41393		
41394		if (jtext.attr('id').toLowerCase() === 'important_note_vc') {
41395			var noteType = 1;
41396		} else if (jtext.attr('id').toLowerCase() === 'other_note_vc') {
41397			var noteType = 2;
41398		}
41399		
41400		var url = location.protocol + '//' + location.host + '/provider/NoteClient?clientId=' + cid + '&noteType=' + noteType;
41401        GLO.UI.Form.beginProcessing(jsave.parent());
41402
41403        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "note": note } })
41404            .success(function(data, textStatus, jqXHR) {
41405                GLO.UI.Form.resetProcessing();
41406                jsave.find('a').css({ "border": "3px solid transparent" });
41407                div.removeClass('edit-note');
41408                //new GLO.Popup.Success('Note Saved');
41409            })
41410            .error(function(jqXHR, textStatus, errorThrown) {
41411                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41412            });
41413	}
41414	
41415    return _conNote;
41416})();
41417
41418
41419SA.Upgrade = (function() {
41420    function _conUpgrade() { }
41421    
41422    _conUpgrade.initReadOnly = function(label, jcontainer, requiredPackage) {			//requiredPackage = 'gold' | 'silver' | null
41423		GLO.Info.init();
41424		var isPaidAccount = GLO.Provider.isPaidAccount(true);
41425		
41426		if ((isPaidAccount || UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 100) < 80) && GLO.Info.providerPackage != 1) { return false; }
41427		
41428		var url = 'hello/pricing';
41429    	var apaid = '<a onclick="GLO.Uri.gotoUri(\'/' + url + '\', this)" style="border-bottom: none;">';
41430    	var msgcss = '', requiredPackage2 = requiredPackage;
41431		
41432		if (innerWidth > 600) { msgcss += 'text-align: center;'; }
41433		if (innerWidth > 800) { msgcss += 'font-size: larger;'; }
41434		
41435		if (!isPaidAccount) {
41436			if (UTIL.isEmpty(requiredPackage)) {
41437				requiredPackage = 'paid account';
41438				requiredPackage2 = 'packages';
41439			}
41440		} else {
41441			if (UTIL.isEmpty(requiredPackage)) {
41442				requiredPackage = 'gold package';
41443				requiredPackage2 = 'gold package';	
41444			} else if (requiredPackage.toLower().indexOf('package') === -1) {
41445				requiredPackage += ' package';
41446			}
41447			
41448			url += '?tab=' + $.trim(requiredPackage).toLowerCase().replace('package', '');
41449		}
41450		
41451		var msg1 = '<div>' + label.substring(0,1).toUpperCase() + label.substring(1) + ' requires a ' + requiredPackage + ' to setup and use</div>';
41452		var msg2 = '<div style="min-width: 300px; margin-top: 12px; margin-bottom: 8px; font-weight: bold;">' + apaid + 'Press here to checkout our ' + requiredPackage2 + '</a></div>';
41453		var msg = '<div style="' + msgcss + '">' + msg1 + msg2 + '</div>';
41454		
41455		var btnCSS = 'position: absolute; left: 8px; text-transform: capitalize; font-family: Georgia;';
41456		var btn = '<span class="btnAdd btnAdd2" style="' + btnCSS + '"> <a onclick="GLO.Uri.gotoUri(\'' + url + '\', this)">View ' + requiredPackage2 + '</a> </span>';
41457    	
41458    	var h1 = '<b style="font-size: larger;">Read Only Mode</b>';
41459    	var jpop = GLO.Provider.Advanced.Help.open(h1, msg);
41460    	
41461    	if (btn) {
41462    		var jbtns = jpop.find('.pop-buttons').css({ "position": "relative" });
41463    		jbtns.prepend(btn);
41464    		jbtns.find('.btnCancel').addClass('btnClick').css({ "position": "absolute", "right": "8px", "width": "64px", "font-size": "100%" });
41465    	}
41466    	
41467    	if (jcontainer) {
41468    		_addReadOnlyOverlay(jcontainer, msg);
41469    	}
41470    	
41471    	return true;
41472	}
41473	
41474	function _addReadOnlyOverlay(jcontainer, message) {
41475		var msg = '<div class="block-msg">' + message + '</div>';
41476        var htmUpgrade = '<div class="block-container">' + msg + '</div>';
41477        
41478        var jmsg = jcontainer.css({ "opacity": ".4" });
41479        jmsg.parent().css({ "position": "relative" }).prepend(htmUpgrade);
41480	}
41481	
41482	_conUpgrade.gotoUpgradePackage = function(btn, reason, helloback) {
41483    	if (btn) {
41484    		btn = $(btn).parent();
41485			GLO.UI.Form.beginProcessing(btn);
41486    	}
41487    	
41488    	var ojProcessing = new GLO.Popup.Processing(SA.Resource.LoadingUpgradePage + '...');
41489    	
41490    	setTimeout(function() {
41491    		var url = GLO.Link.WebsiteDomain + 'provider/profile/6?';
41492    		if (!UTIL.isEmpty(reason)) { url += 'reason=' + reason; }
41493    		if (helloback) { url += '&helloback=' + helloback; }
41494    		
41495    		if (false && GLO.Info.isIosApp && GLO.Data.provider.signup == 50 && GLO.Info.providerPackage !== 1) {
41496    			SA.App.openLinkInBrowser(url);
41497    			
41498    			setTimeout(function() {
41499    				GLO.Popup.close(ojProcessing);
41500    			}, 2500);
41501    		} else {
41502    			document.location = url;
41503    		}
41504    	}, 150);
41505    	
41506    	/*
41507    	var msg = 'Contact your Schedule Anyone customer service rep to setup this feature or email us at <a href="mailto:[email protected]">[email protected]</a>';
41508		msg = '<div style="margin-bottom: 8px; padding: 12px 8px; letter-spacing: 1px; line-height: 200%;">' + msg + '</div>';
41509		new GLO.Popup.Info(msg);
41510		*/
41511    }
41512    
41513    _conUpgrade.getPackageName = function(packageType) {
41514    	if (packageType == 1) {
41515    		return SA.Resource.Individual;
41516    	} else if (packageType == 4) {
41517    		return SA.Resource.BusinessBasic;
41518    	} else if (packageType == 2) {
41519    		return SA.Resource.BusinessPremium;
41520    	} else if (packageType == 10) {
41521    		return SA.Resource.Retail;
41522    	} else {
41523    		return '';
41524    	}
41525    }
41526    
41527    _conUpgrade.getPackagePriceNumber = function(packageType) {
41528    	if (packageType == 1) {
41529    		return 9.99;
41530    	} else if (packageType != 2) {
41531    		return 39.99;
41532    	} else {
41533    		return null;
41534    	}
41535    }
41536    
41537    function _getPackagePrice(packageType) {
41538    	if (packageType == 1) {
41539    		return '<span class="package-price">$9.<i>99</i></span>';
41540    	} else if (packageType == 4) {
41541    		return '<span class="package-price">$39<i>.99</i></span>';
41542    	} else if (packageType == 2) {
41543    		return '$25 + $5 ' + SA.Resource.PerStaff.toLowerCase();
41544    	} else if (packageType == 10) {
41545    		return '<span class="package-price">$39.<i>99</i></span>';
41546    	} else {
41547    		return '';
41548    	}
41549    }
41550    
41551    _conUpgrade.businessToPersonal = function(packageName, packagePrice) {
41552    	var h1 = '<h1 class="friendly-msg2">' + SA.Resource.ConfirmChangePackage + '</h1>';
41553    	var msg1 = '<div>' + SA.Resource.ChangeToThe + ' ' + packageName + ' ' + SA.Resource.Package.toLowerCase() + '?</div>';
41554    	var msg2 = '<div style="margin-top: 12px;">' + SA.Resource.NewMonthlyPrice + ' ' + packagePrice + '</div>';
41555		var htm = $('<div id="pop-confirm-downgrade">' + h1 + '<div class="friendly-msg2" style="padding-left: 8px; padding-bottom: 12px;">' + msg1 + msg2 + '</div> </div>');
41556    	
41557    	var oj = new GLO.Popup.Custom(htm, SA.Upgrade.businessToPersonal2);
41558		var jpop = oj.getPopup().addClass('no-persist');
41559		var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');					//.css({ "height": "40px", "text-align": "center" });
41560		jbtns.find('a').css({ "outline": "none", "webkit-appearance": "none" });
41561		jbtns.find('.btnSave > a').text('  Go  ').css({ "letter-spacing": "2px" });
41562    }
41563    
41564    _conUpgrade.businessToPersonal2 = function() {
41565    	var jpop = $('#pop-confirm-downgrade').closest('.glopop');
41566    	GLO.Popup.close(jpop);
41567    	
41568    	var jbtn = $('#wiz5-UpgradePersonalToBusiness');
41569        if (jbtn.length) { GLO.UI.Form.beginProcessing(jbtn); }
41570    	
41571    	if ( $('#wiz6-creditcard').length > 0 ) {
41572        	SA.Upgrade.save(1);
41573        	return;
41574        }
41575    }
41576    
41577    _conUpgrade.personalToBusiness = function() {
41578    	var htm = $('<div id="pop-default-role-type" style="text-align: center;"> <h2 class="friendly-msg2">My Staff Is Primarily</h2> <ul>'
41579		    		+ '<li>'
41580			    		+ '<input type="radio" id="staff-role-independent" name="Default_Role_Type_cd" value="170"/>'
41581				    	+ '<label for="staff-role-independent">Independent Contractors</label>'
41582				    + '</li>'
41583				    + '<li>'
41584			    		+ '<input type="radio" id="staff-role-commission" name="Default_Role_Type_cd" value="150" checked="checked"/>'
41585				    	+ '<label for="staff-role-commission">Commission</label>'
41586				    + '</li>'
41587				    + '<li>'
41588			    		+ '<input type="radio" id="staff-role-employees" name="Default_Role_Type_cd" value="140"/>'
41589				    	+ '<label for="staff-role-employees">Employees</label>'
41590				    + '</li>'
41591    			+ '</ul></div>');
41592    	
41593    	var oj = new GLO.Popup.Custom(htm, SA.Upgrade.personalToBusiness2);
41594		var jpop = oj.getPopup().addClass('no-persist');
41595		var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');					//.css({ "height": "40px", "text-align": "center" });
41596		jbtns.find('a').css({ "outline": "none", "webkit-appearance": "none" });
41597		jbtns.find('.btnSave > a').text('  Go  ').css({ "letter-spacing": "2px" });
41598    }
41599    
41600    _conUpgrade.personalToBusiness2 = function() {
41601    	var jpop = $('#pop-default-role-type').closest('.glopop');
41602    	var rt = jpop.find('input[name="Default_Role_Type_cd"]:checked').val();
41603    	GLO.Popup.close(jpop);
41604    	
41605    	if ( $('#wiz6-creditcard').length > 0 ) {
41606        	SA.Upgrade.saveConfirm(null, 4, rt);
41607        	return;
41608        }
41609        
41610        var url = GLO.Link.Object.Provider.Ajax + "UpdatePersonalToBusiness?DefaultRoleType=" + rt;
41611        var jbtn = $('#wiz5-UpgradePersonalToBusiness');
41612        GLO.UI.Form.beginProcessing(jbtn);
41613        
41614        //Upgrading to multi-user account...
41615        //Adding Staff...
41616        
41617        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: {} })
41618            .success(function(data, textStatus, jqXHR) {
41619                GLO.UI.Form.resetProcessing();
41620                
41621                if (data) {
41622                	var jpop = new GLO.Popup.Info(data, function() {
41623                		var jbtn = $('#wiz5-UpgradePersonalToBusiness');
41624                		GLO.UI.Form.beginProcessing(jbtn);
41625                		new GLO.Popup.Info('Loading New Mult-User Account...');
41626                		
41627                		setTimeout(function() {
41628                			var refreshUrl = document.location.href;
41629                			document.location = refreshUrl;					//location.reload(true);
41630                		}, 900);
41631                	}).getPopup();
41632                	
41633                	if (innerWidth < 400 || GLO.Info.isMobile()) {
41634                		jpop.find('.msg').css({ "padding-left": "6px", "padding-right": "4px", "background-color": "rgb(189, 229, 248)" });
41635                	}
41636                }
41637            })
41638	        .error(function(jqXHR, textStatus, errorThrown) {
41639	            //GLO.Popup.Error('An error occurred.  Unable to make save your changes at this time.');
41640                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41641	        });
41642    }
41643    
41644    function _navigateToPackageProfile(newPackage, packageName) {
41645    	var jpop = $('#pop-navigate-to-upgrade');
41646		var jsonCSS = { "padding": "12px 4px 12px 8px", "letter-spacing": "2px", "line-height": "180%", "text-align": "center", "color": "white" };
41647		
41648		jpop.find('#pop-note').html('Navigating to package change profile page...').css(jsonCSS);
41649		jpop.bsModal();
41650		
41651		setTimeout(function() {
41652			document.location = GLO.Link.WebsiteDomain + 'provider/profile/6?package=display';
41653		}, 400);
41654    }
41655    
41656    function _ccIsPopulated(newPackage, packageName) {
41657    	var j = $('#wiz6-creditcard');
41658    	var fieldId, missingField = null;
41659    	
41660    	if (j.length === 0) {
41661    		_navigateToPackageProfile(newPackage, packageName);
41662    		return false;
41663    	}
41664    	
41665    	if (UTIL.isEmpty(j.find('#Card_Type_cd').val())) {
41666    		missingField = SA.Resource.CardType;
41667    		fieldId = 'Card_Type_cd';
41668    	} else if (UTIL.isEmpty(j.find('#Card_Number_vc').val())) {
41669    		missingField = SA.Resource.CardNumber;
41670    		fieldId = 'Card_Number_vc';
41671    	} else if (UTIL.isEmpty(j.find('#Expiration_Month_sr').val())) {
41672    		missingField = SA.Resource.ExpirationMonth;
41673    		fieldId = 'Expiration_Month_sr';
41674    	} else if (UTIL.isEmpty(j.find('#Expiration_Year_sr').val())) {
41675    		missingField = SA.Resource.ExpirationYear;
41676    		fieldId = 'Expiration_Year_sr';
41677    	}
41678    	
41679    	if (missingField !== null) {
41680    		var msg = '<div> <h1>' + SA.Resource.PleaseEnterCreditCard + '</h1> <div>' + SA.Resource.PleaseEnterThe + ' ' + missingField + '</div> </div>';
41681    		var fn = function() { $('#wiz6-creditcard').find('#' + fieldId).focus(); };
41682    		
41683    		var jpop = new GLO.Popup.Warning(msg, fn);
41684    		return false;
41685    	} else {
41686    		return true;
41687    	}
41688    }
41689    
41690    _conUpgrade.saveConfirm = function(btn, newPackage, Default_Role_Type_cd) {
41691    	var packageName = _conUpgrade.getPackageName(newPackage);
41692    	var packagePrice = _getPackagePrice(newPackage);
41693    	
41694    	if (GLO.Info.isIosApp) {
41695    		SA.App.buySubscriptionStart(newPackage);
41696    		
41697    		if (btn) {
41698	    		GLO.UI.Form.beginProcessing( $(btn).parent() );
41699	    		setTimeout(function() { GLO.UI.Form.resetProcessing(); }, 8000);
41700    		}
41701    		
41702    		return;
41703    	} else if (!_ccIsPopulated(newPackage, packageName)) {
41704    		return;
41705    	} else if (newPackage == 4 && UTIL.isEmpty(Default_Role_Type_cd)) {
41706    		return SA.Upgrade.personalToBusiness();
41707    	} else if (newPackage == 1 && GLO.Info.providerPackage != 1) {
41708    		return SA.Upgrade.businessToPersonal(packageName, packagePrice);
41709    	}
41710    	
41711    	var fnCancel = function() {
41712    		SA.Upgrade.log(newPackage, 'ignore');
41713    	};
41714    	
41715    	var msgCSS = 'friendly-msg2';
41716    	
41717    	if (GLO.Info.isMobile()) { msgCSS = 'friendly-msg'; }
41718    	
41719    	var h1 = '<h1 class="friendly-msg2">' + SA.Resource.ConfirmUpgradeAccount + '</h1>';
41720    	var msg1 = '<div>' + SA.Resource.UpgradeToThe + ' ' + packageName + ' ' + SA.Resource.Package.toLowerCase() + '?</div>';
41721    	var msg2 = '<div style="margin-top: 12px;">' + SA.Resource.NewMonthlyPrice + ' ' + packagePrice + '</div>';
41722    	
41723    	var jexpire = $('#upgrade-package-trial-expiration-days');
41724    	
41725    	if (jexpire.length) {
41726    		jexpire.find('span').css({ "color": "inherit" });
41727    		msg2 += '<div style="margin-left: -20px; margin-bottom: 20px; font-size: 12px; font-weight: bold;">After Your ' + jexpire.html().replace('*', '') + '</div>';
41728    	}
41729    	
41730    	var htm = '<div id="pop-confirm-upgrade">' + h1 + '<div class="' + msgCSS + '">' + msg1 + msg2 + '</div> </div>';
41731    	
41732    	var jpop = new GLO.Popup.Confirm(htm, function() {
41733    		SA.Upgrade.save(newPackage, null, Default_Role_Type_cd);
41734    	}, fnCancel).getPopup();
41735    	
41736    	jpop.find('.modalClose, .btnCancel > a').click(fnCancel);
41737    	
41738    	GLO.UI.Form.beginProcessing( $(btn).parent() );
41739    	setTimeout(function() { GLO.UI.Form.resetProcessing(); }, 4000);
41740    }
41741    
41742    _conUpgrade.save = function(newPackage, jsonReceiptObj, Default_Role_Type_cd) {
41743
41744		//dont process receipt if no provider
41745		if (GLO.Data === undefined || GLO.Data.provider === undefined) { return; }
41746		
41747    	var url = GLO.Link.Object.Provider.Ajax + "UpgradePackage";
41748        var ojProcessing, jbtn = $('#upgrade-package').find('.btnUpgrade');
41749        // var contentType = '';
41750        if (jsonReceiptObj !== undefined && jsonReceiptObj !== null && jsonReceiptObj.constructor == Object) {
41751        	var jd = {};
41752        	jd.package_cd = newPackage;
41753        	jd.default_role_type_cd = Default_Role_Type_cd;
41754			jd.receipt_vc = JSON.stringify(jsonReceiptObj);
41755			// contentType = 'application/json';
41756			url = GLO.Link.Object.Provider.Ajax + "UpgradePackage";
41757			GLO.Log.insertSimple('Package type from iOS Subscription before UpgradePackage call', newPackage, 'high');
41758        } else {
41759        	var jd = { "package_cd": newPackage, "default_role_type_cd": Default_Role_Type_cd, "receipt_vc": '' };
41760        }
41761        
41762        _addCCtoJson(jd);
41763        
41764        if (UTIL.isEmptyObject(jbtn)) { $('.btnUpgrade'); }
41765        
41766        if (!UTIL.isEmptyObject(jbtn)) {
41767        	GLO.UI.Form.beginProcessing(jbtn);
41768        } else {
41769        	var ojProcessing = new GLO.Popup.Processing('Processing Subscription...');
41770        }
41771        
41772        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd})
41773            .success(function(data, textStatus, jqXHR) {
41774                //GLO.UI.Form.resetProcessing();
41775                var packageName = _conUpgrade.getPackageName(newPackage);
41776        		var payIntermediary = UTIL.coalesceInt($('#Payment_Intermediary_cd').val(), 0);
41777        		var url = GLO.Link.WebsiteDomain + 'provider/manage/UpgradePackageSuccess'
41778        		
41779				//data will be empty string if its just a receipt update without package change
41780				if (data.length > 2)  {
41781					new GLO.Popup.Success(SA.Resource.UpgradedTo + ' ' + packageName + ' ' + SA.Resource.Package + '!', 9000);
41782					
41783					if (!_conUpgrade.displayMultipleSubscriptionWarning(payIntermediary, url)) {
41784						setTimeout(function() {
41785							document.location = url;
41786						}, 1500);
41787					}
41788				}
41789            })
41790	        .error(function(jqXHR, textStatus, errorThrown) {
41791	            //GLO.Popup.Error('An error occurred.  Unable to make save your changes at this time.');
41792                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41793	        });
41794    }
41795    
41796    _conUpgrade.displayMultipleSubscriptionWarning = function(payIntermediary, url) {
41797    	if (payIntermediary < 10 || payIntermediary > 49) { return false; }
41798    	
41799    	var fn = function() { document.location = url; }
41800    	var appleLink = '<a href="https://support.apple.com/en-us/HT202039">';
41801    	var div = '<div style="padding-bottom: 16px;">';
41802    	
41803    	var msg = div + 'You have signed up for multiple subscriptions with Schedule Anyone using this iTunes account</div>'
41804    				+ div + 'You can review your iTunes subscriptions, on your iPhone/iPad by going to ' + appleLink + 'Settings > iTunes & the App Store > View Apple ID</a></div>'
41805    				+ div + 'Here are the full instructions: ' + appleLink + 'support.apple.com</a></div>'
41806    				+ div + 'Please <a onclick="GLO.Log.openContactSAPopup()">Contact Schedule Anyone</a> if you have any questions</div>';
41807    	
41808    	var h1 = '<h1 class="friendly-msg4">Verify Schedule Anyone Subscriptions with Apple</h1>';
41809    	var htm = '<div id="pop-warn-multi-subscription">' + h1 + '<div class="friendly-msg4" style="text-align: left; font-size: 14px;">' + msg + '</div> </div>';
41810    	
41811    	var jpop = new GLO.Popup.Warning(htm, fn).getPopup().css({ "padding-bottom": "8px" });
41812    	var jmsg = jpop.find('.msg').css({ "padding-top": "0", "padding-bottom": "0", "padding-right": "8px" });
41813    	var jdiv1 = jmsg.find('.friendly-msg4 > div:first').css({ "margin-left": "-36px" });
41814    	
41815    	jpop.find('.pop-icon').css({ "top": "42%" });
41816    	
41817    	if (innerWidth > 800) { jdiv1.css({ "text-align": "center" }); }
41818    	
41819    	return true;
41820    }
41821    
41822    function _addCCtoJson(jd) {
41823    	if (GLO.Info.isIosApp) { return; }
41824    	
41825    	var j = $('#wiz6-creditcard');
41826    	
41827    	jd.card_type_cd = j.find('#Card_Type_cd').val();
41828    	jd.card_number_vc = j.find('#Card_Number_vc').val();
41829    	jd.expiration_month_sr = j.find('#Expiration_Month_sr').val();
41830    	jd.expiration_year_sr = j.find('#Expiration_Year_sr').val();
41831    }
41832    
41833    _conUpgrade.iosInit = function(newPackage) {
41834    	var url = GLO.Link.Object.Provider.Ajax + "IosSubscriptionBegin";
41835        var jd = { "package_cd": newPackage };
41836        
41837        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
41838            .success(function(data, textStatus, jqXHR) {
41839                
41840            })
41841	        .error(function(jqXHR, textStatus, errorThrown) {
41842	            //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41843	        });
41844    }
41845    
41846    _conUpgrade.iosFailed = function(newPackage, reason, jsonReceipt) {
41847    	var url = GLO.Link.Object.Provider.Ajax + "IosSubscriptionFailed";
41848        
41849        if (!UTIL.isEmpty(jsonReceipt)) {
41850        	var jd = jsonReceipt;
41851        	jd.receipt_vc = JSON.stringify(jsonReceipt);
41852        	jd.package_cd = newPackage;
41853        } else {
41854        	var jd = { "package_cd": newPackage };
41855        }
41856        
41857        jd.reason_vc = UTIL.cleanString(reason);
41858        
41859        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
41860            .success(function(data, textStatus, jqXHR) {
41861                var msg = SA.Resource.UpgradeTo + ' ' + SA.Upgrade.getPackageName(newPackage) + ' ' + SA.Resource.Failed;
41862                new GLO.Popup.Warning(msg);
41863                GLO.UI.Form.resetProcessing();
41864            })
41865	        .error(function(jqXHR, textStatus, errorThrown) {
41866	            GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41867	        });
41868    }
41869    
41870    _conUpgrade.log = function(newPackage, action) {
41871    	var url = GLO.Link.Object.Provider.Ajax + "UpgradePackageLog?package=" + newPackage + '&action=' + action;
41872        
41873        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
41874            .success(function(data, textStatus, jqXHR) {
41875            })
41876	        .error(function(jqXHR, textStatus, errorThrown) {
41877	            //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
41878	        });
41879    }
41880    
41881    return _conUpgrade;
41882})();
41883
41884SA.ClientServer = (function() {
41885
41886	const _printerLocalApiBase = 'http://localhost:5152/api/Printer/';
41887	const _pathGetHello = 'hello';
41888	const _pathGetPrinters = 'getprinters';
41889	const _pathPostOpenDrawer = 'opendrawer?printerName=';
41890	function _cClientServer() { }
41891
41892	_cClientServer.checkApiStatus = async function() {
41893		
41894		try {
41895			var apiEndpoint = _printerLocalApiBase + _pathGetHello;
41896			const response = await fetch(apiEndpoint , {
41897				method: 'GET',
41898				headers: {
41899					'Content-Type': 'application/text'
41900				}
41901			});
41902
41903			if (response.ok) {
41904				console.log(`SA ClientServer API is running. Status: ${response.status}`);
41905				const data = await response.text();
41906				console.log(`SA ClientServer API response. Data: ${data}`);
41907				return true;
41908			} else {
41909				GLO.Log.insertSimple('SA ClientServer API returned an error status: ' + response.status, 'SA.ClientServer.checkApiStatus', 'warning');
41910				console.log(`SA ClientServer API returned an error status. Status: ${response.status}`);
41911      			return false;
41912			}
41913		}
41914		catch (error) {
41915			GLO.Log.insertSimple('SA ClientServer API is not reachable due to a network error: ' + error.message, 'SA.ClientServer.checkApiStatus', 'warning');
41916			console.error('SA ClientServer API is not reachable due to a network error:', error.message);
41917    		return false;
41918		}
41919	}
41920
41921	_cClientServer.getLocalPrinters = async function() {
41922		try {
41923			var apiEndpoint = _printerLocalApiBase + _pathGetPrinters;
41924			const response = await fetch(apiEndpoint , {
41925				method: 'GET',
41926				headers: {
41927					'Content-Type': 'application/json'
41928				}
41929			});
41930
41931			if (response.ok) {
41932				console.log(`SA ClientServer API is running. Status: ${response.status}`);
41933				const data = await response.json();
41934				console.log(`SA ClientServer API response. Data: ${data}`);
41935				return data;
41936			}
41937			else {
41938				console.log(`SA ClientServer API returned an error status. Status: ${response.status}`);
41939      			return [];
41940			}
41941		}
41942		catch (error) {
41943			console.error('SA ClientServer API is not reachable due to a network error:', error.message);
41944    		return [];
41945		}
41946	}
41947
41948	_cClientServer.postOpenDrawer = async function(printerName) {
41949		try {
41950			const formData = new FormData();
41951			formData.append('printerName',printerName);
41952			var apiEndpoint = _printerLocalApiBase + _pathPostOpenDrawer + printerName;
41953			const response = await fetch(apiEndpoint , {
41954				method: 'POST',
41955				headers: {
41956					'Accept': 'application/json'
41957				}
41958			});
41959
41960			if (response.ok) {
41961				console.log(`SA ClientServer API is running. Status: ${response.status}`);
41962				const data = await response.text();
41963				console.log(`SA ClientServer API response. Data: ${data}`);
41964				return data;
41965			}
41966			else {
41967				console.log(`SA ClientServer API returned an error status. Status: ${response.status}`);
41968      			return [];
41969			}
41970		}
41971		catch (error) {
41972			console.error('SA ClientServer API is not reachable due to a network error:', error.message);
41973    		return [];
41974		}		
41975	}
41976
41977	_cClientServer.getReceiptPrinterFromCookie = function() {
41978		var name = '_sa_receiptprinter' + "=";
41979		var decodedCookie = decodeURIComponent(document.cookie);
41980		var ca = decodedCookie.split(';');
41981		for(var i = 0; i <ca.length; i++) {
41982		  var c = ca[i];
41983		  while (c.charAt(0) == ' ') {
41984			c = c.substring(1);
41985		  }
41986		  if (c.indexOf(name) == 0) {
41987			return c.substring(name.length, c.length);
41988		  }
41989		}
41990		return "";
41991	}
41992
41993	return _cClientServer;
41994})();
41995
41996SA.Profile.OnlineBooking = (function() {
41997    var _autoSaveOnlineBkgTimeout, _autoSaveOnlineBkgInProgress = false, _isNoteChange = false, _isRequireDepositChange = false;
41998    
41999    function _conOnlineBkg() { }
42000    
42001    _conOnlineBkg.init = function() {
42002    	var tbl = $('#config-client-pay-online #service-group-list');
42003    	UI.initTableSorter(tbl);
42004    	tbl.find('th:first-child').click();
42005    	
42006    	var tr = tbl.find('tr');
42007    	
42008    	for (var i=0; i < tr.length; i++) {
42009    		var row = tr.eq(i);
42010    		_displayAmount(row);
42011    	}
42012    	
42013    	tr.find('.client_pay_type_sr').keyup(SA.Profile.OnlineBooking.changeRequiredAmount);
42014    	
42015    	if ($('#warn-no-merchant-account').length > 0) {
42016    		_displayNoMerchantPopup();
42017    	}
42018    	
42019    	$('#config-client-payment-group-booking').find('input').keyup(SA.Profile.OnlineBooking.changeRequiredAmount)
42020    	
42021    	_iniUrl();
42022    }
42023    function _iniUrl() {
42024    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
42025    	
42026    	if (!UTIL.isEmpty(highlight)) {
42027			var jhigh = $('#' + highlight);
42028    		
42029    		if (jhigh.length) {
42030    			UI.highlight(jhigh, 100, 9500, true);
42031    		}
42032		}
42033    }
42034    
42035    function _displayNoMerchantPopup() {
42036    	var msg = 'To Require Payment, Deposit, and/or Card on File with Online Booking';
42037    	var btnAddMerchant = '<span class="btnAdd">
42037<a onclick="SA.Profile.OnlineBooking.requestAddMerchant()">Add a Merchant Account</a></span>';
42038    	var htm = '<div id="warn-no-merchant-account">' + msg + ' ' + btnAddMerchant + '</div>';
42039    }
42040    
42041    _conOnlineBkg.requestAddMerchant = function() {
42042    	var url = GLO.Link.Page.Provider.Home + 'manage/RequestAddMerchant';
42043    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
42044            .success(function (data, textStatus, jqXHR) {
42045                var h1 = 'Add Merchant Account';
42046                var htm = '<div id="pop-request-merchant">We will give you a call within 24 hours to answer all your questions and help you setup a merchant account</div>';
42047                
42048                GLO.Popup.Success.open(htm, h1);
42049            })
42050            .error(function (jqXHR, textStatus, errorThrown) {
42051            	//GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
42052            });
42053    }
42054    
42055    function _displayAmount(row) {
42056    	var cptype = UTIL.coalesceInt(row.find('.client_pay_type_cd').val(), 0);
42057    	
42058    	if (cptype > 0 && cptype < 50) {
42059			if (cptype === 1 || cptype === 11 || cptype === 30 || cptype === 31) {
42060				row.find('.dollar-sign').addClass('not-displayed');
42061				row.find('.percent-sign').removeClass('not-displayed');
42062			} else if (cptype === 2 || cptype === 12) {
42063				row.find('.percent-sign').addClass('not-displayed');
42064				row.find('.dollar-sign').removeClass('not-displayed');
42065			}
42066			
42067			row.find('.client-pay-type-amount').removeClass('not-displayed');
42068		} else {
42069			row.find('.client-pay-type-amount').addClass('not-displayed');
42070		}
42071    }
42072    
42073    _conOnlineBkg.changeRequiredAmount = function() {
42074    	var jthis = $(this);
42075    	var id = jthis.attr('id');
42076    	var tr = jthis.closest('tr')
42077    	var jamt = tr.find('.client_pay_type_sr');
42078    	
42079    	if (this.value != jamt.attr('original_amount_sr')) {
42080    		_isRequireDepositChange = (id == 'Client_Pay_Require_Deposit_mn' || id == 'Client_Pay_Require_Deposit_pct');
42081    		_beginSave(tr);
42082    	}
42083    }
42084    
42085    _conOnlineBkg.changeType = function(element) {
42086    	var row = $(element).closest('tr');
42087    	_displayAmount(row);
42088    	_beginSave(row);
42089    }
42090    
42091    _conOnlineBkg.changeNote = function(element) {
42092    	$(element).addClass('has-change');
42093    	_isNoteChange = true;
42094    	_beginSave();
42095    }
42096    
42097    function _beginSave(tr) {
42098    	if (tr && tr.length) {
42099    		tr.addClass('has-change');
42100    	}
42101    	
42102    	clearTimeout(_autoSaveOnlineBkgTimeout);
42103    	_autoSaveOnlineBkgTimeout = setTimeout(SA.Profile.OnlineBooking.saveConfig, 2400);
42104    }
42105    
42106    _conOnlineBkg.saveAllowPayFullAmount = function(checkbox) {
42107    	var url = url = GLO.Link.Page.Provider.Home + 'manage/ClientPayAllowFullPayment?isAllow=' + checkbox.checked;
42108    	
42109        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
42110            .success(function (data, textStatus, jqXHR) {
42111                GLO.Popup.Success.open('Allow Client to Pay Full Amount when Booking Online = ' + checkbox.checked, 'Change Saved');
42112            })
42113            .error(function (jqXHR, textStatus, errorThrown) {
42114            	var test = 123;
42115            });
42116    }
42117    _conOnlineBkg.saveConfig = function() {
42118    	if (_autoSaveOnlineBkgInProgress) {
42119    		_autoSaveOnlineBkgTimeout = setTimeout(SA.Profile.OnlineBooking.saveConfig, 2400);
42120    		return;
42121    	}
42122    	
42123    	var j = $('#config-client-pay-online');
42124    	var tr = j.find('#service-group-list tr.has-change');
42125    	
42126    	if (!_isNoteChange && !_isRequireDepositChange && tr.length === 0) { return; }
42127    	_autoSaveOnlineBkgInProgress = true;
42128    	
42129    	tr.removeClass('has-change').addClass('processing-change');
42130    	var xml = '', note = '', url = GLO.Link.Page.Provider.Home + 'manage/ClientPayOnlineUpdate';
42131    	
42132    	for (var i=0; i < tr.length; i++) {
42133    		var amt = '', row = tr.eq(i);
42134    		var sgid = row.attr('service_group_id');
42135    		var cptype = row.find('.client_pay_type_cd').val();
42136    		var jamt = row.find('.client_pay_type_sr');
42137            
42138    		if (cptype > 0 && cptype < 90) { amt = jamt.val(); }
42139    		
42140    		jamt.attr('original_amount_sr', jamt.val());
42141    		
42142    		xml += '<li service_group_id="' + sgid + '" client_pay_type_cd="' + cptype + '" client_pay_type_sr="' + amt + '"/>';
42143    	}
42144    	
42145    	if (_isNoteChange) {
42146    		var jnote = j.find('#Client_Pay_Note_vc').removeClass('has-change').addClass('processing-change');
42147    		note = UTIL.htmlEncode(jnote.val());
42148    	}
42149    	
42150    	xml = UTIL.htmlEncode('<ul>' + xml + '</ul>');
42151        //GLO.UI.Form.beginProcessing( j.find('.btnSave') );
42152        
42153        var requireDepositAmount = $.trim(j.find('#Client_Pay_Require_Deposit_mn').val()).replace(',', '');
42154        var requireDepositPercent = j.find('#Client_Pay_Require_Deposit_pct').val();
42155        
42156        var jd = { "input_xml": xml, "client_pay_note_vc": note, "is_note_update_fl": _isNoteChange
42157        		, "client_pay_require_deposit_mn": requireDepositAmount, "client_pay_require_deposit_pct": requireDepositPercent };
42158        
42159        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
42160            .success(function (data, textStatus, jqXHR) {
42161                tr.removeClass('processing-change');
42162                $('#Client_Pay_Note_vc.processing-change').removeClass('processing-change');
42163                
42164                _isNoteChange = _isRequireDepositChange = _autoSaveOnlineBkgInProgress = false;
42165                new GLO.Popup.Success('Changes Saved');
42166            })
42167            .error(function (jqXHR, textStatus, errorThrown) {
42168            	tr.removeClass('processing-change').addClass('has-change');
42169            	_autoSaveOnlineBkgInProgress = false;
42170            });
42171    }
42172    
42173    return _conOnlineBkg;
42174})();
42175
42176
42177SA.Profile.Payment = (function() {
42178	function _cProfilePayment() { }
42179	var _jpopSetupTax;
42180	var _jpopSetupTipPercents;
42181	var _jpopSetupConfirmationText;
42182
42183	_cProfilePayment.openEditTax = function() {
42184		if (UTIL.isEmpty(_jpopSetupTax)) {
42185			_jpopSetupTax = $('#pop-tax-setup').outerHTML();
42186			$('#pop-tax-setup').remove();
42187		}
42188		
42189		var jpop = GLO.Popup.Custom.openSimple(_jpopSetupTax, 'Tax Rate', SA.Profile.Payment.saveEditTax);
42190		
42191	}
42192	_cProfilePayment.saveEditTax = function() {
42193		var url = GLO.Link.Page.Provider.Home + 'manage/SaveTax';
42194		var jpop = $('#pop-tax-setup').closest('.glopop');
42195		var ptax = jpop.find('#Inventory_Tax_Rate_pct').val(), stax = jpop.find('#Service_Tax_Rate_pct').val(), isTaxTip = jpop.find('#Tax_Tips_fl').prop('checked');
42196		var jd = { "inventory_tax_rate_pct": ptax, "service_tax_rate_pct": stax, "tax_tips_fl": isTaxTip };
42197		
42198		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
42199		
42200		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
42201            .success(function (data, textStatus, jqXHR) {
42202                var jhtm = $(_jpopSetupTax);			//= update popup html.
42203                jhtm.find('#Inventory_Tax_Rate_pct').attr('value', ptax)
42204                jhtm.find('#Service_Tax_Rate_pct').attr('value', stax)
42205                
42206                if (isTaxTip) {
42207                	jhtm.find('#Tax_Tips_fl').attr('checked', 'checked');
42208                } else {
42209                	jhtm.find('#Tax_Tips_fl').removeAttr('checked');
42210                }
42211                
42212                _jpopSetupTax = jhtm.outerHTML();
42213                
42214                GLO.serviceTax = UTIL.coalesceFloat(stax);
42215				GLO.hasTaxOnTips = isTaxTip;
42216                
42217                GLO.Popup.close(jpop);
42218                GLO.Popup.Success.open('Tax Rates Saved', 'Changes Saved');
42219            })
42220            .error(function (jqXHR, textStatus, errorThrown) {
42221            	GLO.UI.Form.resetProcessing();
42222            	GLO.Popup.close(jpop);
42223            });
42224	}
42225	
42226	_cProfilePayment.changeDeviceCardReader = function(element, event) {
42227		//var expireDate = new Date();
42228		//expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 5));
42229		//$.cookies.set('card_reader', element.value, { "expiresAt": expireDate });
42230		UTIL.setCookie('card_reader', element.value);
42231	}
42232	_cProfilePayment.changeDeviceCardAddress = function(element, event) {
42233		//var expireDate = new Date();
42234		//expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 5));
42235		//$.cookies.set('card_reader_address', element.value, { "expiresAt": expireDate });
42236		UTIL.setCookie('card_reader_address', element.value);
42237	}
42238	_cProfilePayment.displayMerchantAccountRequired = function(msg) {
42239		var btn = '<span class="btnAdd" style="position: absolute; left: 0; margin-top: 2px;">
42239<a onclick="SA.Profile.OnlineBooking.requestAddMerchant()">Add a Merchant Account</a></span>';
42240		var htm = '<p style="margin-bottom: 16px;">' + msg + '</p>';
42241		
42242		var jpop = GLO.Popup.Warning.open(htm, 'Merchant Account Required').getPopup().attr('id', 'pop-warn-change-auto-receipt');
42243		var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
42244		
42245		jbtns.prepend(btn);
42246		jbtns.find('.btnOk > a').text('Close').css({ "display": "block" });
42247	}
42248	_cProfilePayment.changeNonCCPayment = function(element, event) {
42249		var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99);
42250    	
42251    	if (mt > 79) {
42252			var msg = 'To Automate Receipts Must Setup Merchant Account in ' + GLO.Info.getScheduleAnyoneHtm();
42253			_cProfilePayment.displayMerchantAccountRequired(msg);
42254			element.value = 0;			//= reset to 'Do Nothing'
42255		}
42256	}
42257    _cProfilePayment.changeAutoReceipt = function(element, event) {
42258    	var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99);
42259    	
42260    	if (mt > 79) {
42261    		var msg = 'To Automate Credit Card Receipts Must Setup Merchant Account to Process Credit Cards in ' + GLO.Info.getScheduleAnyoneHtm();
42262    		_cProfilePayment.displayMerchantAccountRequired(msg);
42263    		
42264    		element.value = 3;			//= reset to 'Print Receipt'
42265    	} else if (element.value == 2) {
42266    		var msg = 'Text Receipts cost 1 cent per message';
42267    		GLO.Popup.Info.open(msg, 'Text Receipt');
42268    	}
42269    	
42270    	GLO.Provider.Advanced.saveField(element, event);
42271    }
42272    
42273	_cProfilePayment.changeDeviceTipConfig = function() {
42274		var j = $('#bolt-tip-percent-setup');
42275		
42276		if (j.find('#Enable_Bolt_Tip_fl').prop('checked')) {
42277			$('#tipConfigFieldset').prop('disabled',false);
42278			$('#tipPercentsFieldset').prop('disabled',false);
42279			$('#tipCalculationFieldset').prop('disabled',false);
42280			$('#Tip_Percent_1').val('15');
42281			$('#Tip_Percent_2').val('20');
42282			$('#Tip_Percent_3').val('25');
42283		} else {
42284			$('#tipConfigFieldset').prop('disabled',true);
42285			$('#tipPercentsFieldset').prop('disabled',true);
42286			$('#tipCalculationFieldset').prop('disabled',true);
42287		}
42288	}
42289
42290	_cProfilePayment.changeDeviceGetConfirmationConfig = function() {
42291		var j = $('#bolt-get-confirmation-setup');
42292		
42293		if (j.find('#Enable_Bolt_Get_Confirmation_fl').prop('checked')) {
42294
42295			$('#getConfirmationFieldset').prop('disabled',false);
42296
42297		} else {
42298			$('#getConfirmationFieldset').prop('disabled',true);
42299
42300		}
42301	}
42302
42303	_cProfilePayment.openTipPercentConfig = function(mId) {
42304		if (UTIL.isEmpty(_jpopSetupTipPercents)) {
42305			_jpopSetupTipPercents = $('#bolt-tip-percent-setup').outerHTML();
42306			$('#bolt-tip-percent-setup').remove();
42307		}
42308		
42309		var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetTipPercents/' + mId;
42310		var fnYes = function () { return SA.Profile.Payment.saveTipPercents(mId); };
42311		
42312		var ojpop = GLO.Popup.Custom.openSimple(_jpopSetupTipPercents, 'Tip Setup', fnYes, null, true);
42313		ojpop.getPopup().find('#Split_Tip_cd').val(GLO.Data.provider.split_tip_cd);
42314		
42315        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
42316            .success(function(data, textStatus, jqXHR) {
42317                window.onbeforeunload = null;
42318                // GLO.UI.Form.resetProcessing();
42319				var jsonMR = JSON.stringify(data);
42320				
42321				if (data.TipEnabled) {
42322					$('#Enable_Bolt_Tip_fl').attr('checked','checked');
42323					$('#Tip_Percent_1').val(data.Tip1Percent);
42324					$('#Tip_Percent_2').val(data.Tip2Percent);
42325					$('#Tip_Percent_3').val(data.Tip3Percent);
42326
42327					if (data.TipMode == 0) {
42328						//percent
42329						$('#tip-by-amount').removeAttr('checked');
42330						$('#tip-by-percent').attr('checked','checked');
42331						$('#tipPercentsFieldset').removeClass('hide');
42332					} else {
42333						//amount
42334						$('#tip-by-amount').attr('checked','checked');
42335						$('#tip-by-percent').removeAttr('checked');
42336						$('#tipPercentsFieldset').addClass('hide');
42337					}
42338
42339					if (data.UseListPrice) {
42340						$('#Enable_Bolt_Tip_On_List_Price_fl').attr('checked','checked');
42341					}
42342				}
42343				
42344				ojpop.realign();
42345            })
42346            .error(function(jqXHR, textStatus, errorThrown) {
42347                GLO.UI.Form.resetProcessing();
42348                new GLO.Popup.Error('Unable to get Tip Settings for device', 'Changes Not Saved');
42349            });
42350	}
42351
42352
42353	_cProfilePayment.openBoltGetConfirmationConfig = function(mId) {
42354		if (UTIL.isEmpty(_jpopSetupConfirmationText)) {
42355			_jpopSetupConfirmationText = $('#bolt-get-confirmation-setup').outerHTML();
42356			$('#bolt-get-confirmation-setup').remove();
42357		}
42358
42359		var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetConfirmationSettings/' + mId;
42360
42361        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
42362            .success(function(data, textStatus, jqXHR) {
42363                window.onbeforeunload = null;
42364                // GLO.UI.Form.resetProcessing(); 		
42365				var jsonMR = JSON.stringify(data);
42366				if (data.GetConfirmationEnabled) {
42367					$('#Enable_Bolt_Get_Confirmation_fl').attr('checked','checked');
42368					$('#Get_Confirmation_Text_vc').val(data.ConfirmationPromptText);
42369					$('#Get_Confirmation_Text_vc').keyup();
42370
42371				}
42372            })
42373            .error(function(jqXHR, textStatus, errorThrown) {
42374                GLO.UI.Form.resetProcessing(); 		
42375                new GLO.Popup.Error('Unable to get Confirmation Settings for device');
42376            });
42377
42378		var jpop = GLO.Popup.Custom.openSimple(_jpopSetupConfirmationText, 'Ask Client a question on Clover', function () { return SA.Profile.Payment.saveGetConfirmationText(mId); });
42379
42380		//character count display for clover confirmation text
42381		$('#Get_Confirmation_Text_vc').keyup(function() {
42382    
42383	        var characterCount = $(this).val().length,
42384		        current = $('#current'),
42385		        maximum = $('#maximum'),
42386		        theCount = $('#the-count');
42387    
42388	        current.text(characterCount);
42389  
42390			//scrolling needed after 241 characters on mini
42391	        if (characterCount >= 241) {
42392		        maximum.css('color', '#8f0001');
42393		        current.css('color', '#8f0001');
42394		        theCount.css('font-weight','bold');
42395	        } else {
42396		        current.css('color', '#666');
42397		        maximum.css('color','#666');
42398		        theCount.css('font-weight','normal');
42399	        }
42400
42401			var initVal = $(this).val();
42402			outputVal = initVal.replace(/[^ \+-_\*\$(\r\n|\r|\n)0-9a-zA-Z\?]/g,"");       
42403			if (initVal != outputVal) {
42404				$(this).val(outputVal);
42405			}
42406        });
42407
42408		$('#Get_Confirmation_Text_vc').blur(function() {
42409			var initVal = $(this).val();
42410			outputVal = initVal.replace(/[^ \+-_\*\$(\r\n|\r|\n)0-9a-zA-Z\?]/g,"");       
42411			if (initVal != outputVal) {
42412				$(this).val(outputVal);
42413			}
42414		});
42415		
42416	}
42417	
42418	_cProfilePayment.openHelpConnectDevice = function() {
42419		var urlHelp = 'https://ScheduleAnyone.notion.site/Clover-Troubleshooting-Connection-Issue-2a0dbd7c625041b4bdca966bd6934720';
42420		var aHelp = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlHelp + '\', this, event, true)">Troubleshoot Connection Issue</a>';
42421		var checkbox = '<b class="checkmark-icon" title="checkbox"></b>';
42422		
42423		var msg1 = '<p>Indicates the Clover <i class="narrow-text">(or other payment device)</i> is connected to the Fiserv payment network</p>';
42424		var msg2 = '<p style="letter-spacing: 0;">If there is no ' + checkbox + ' then the Clover needs to be <b class="narrow-text">Activated</b> or there is a <b class="narrow-text">Connection Issue</b></p>';
42425		var msg3 = '<p>Go here to ' + aHelp + '</p>';
42426		var msg4 = '<p> </p>';
42427		
42428		var htm = '<div id="pop-help-connect-pay-device" style="padding-left: 12px; padding-right: 6px; ">' + msg1 + msg2 + msg3 + msg4 + '</div>';
42429		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Is Payment Device Connected?', null, null, true);
42430		var jpop = ojpop.getPopup();
42431		
42432		jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" });
42433		GLO.Popup.Custom.singleButton(jpop);
42434		ojpop.realign();
42435	}
42436	
42437	_cProfilePayment.openHelpTipAmount = function() {
42438		var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;';
42439		var msg1 = '<p style="' + css1 + '">Clover can be setup to show client tip options by <b class="narrow-text">Percent</b> or <b class="narrow-text">Dollar Amount</b></p>';
42440		var pctCustom = '<i class="narrow-text">(client still has option to enter dollar amount by pressing <b class="narrow-text">Custom Tip</b> button)</i>';
42441		
42442		var hPct = '<h3>Percentage</h3>';
42443		var msgPct = '<p> Clover device displays easy percent tip buttons' + pctCustom + '</p>';
42444		var imgPct = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-percent.png" style="width: 90%; max-width: 480px; margin: auto;"/>';
42445		
42446		var hDollar = '<h3>Dollar Amount</h3>';
42447		var msgDollar = '<p>Clover device prompts client to enter dollar amount</p>';
42448		var imgDollar = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-dollar-amount.png" style="width: 90%; max-width: 480px; margin: auto;"/>';
42449		
42450		var htm = '<div id="pop-help-tip-percent-or-dollar">' + msg1 + hPct + msgPct + imgPct + hDollar + msgDollar + imgDollar + '</div>';
42451		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Tip By Percent or Dollar Amount', null, null, true);
42452		var jpop = ojpop.getPopup();
42453		
42454		jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" });
42455		GLO.Popup.Custom.singleButton(jpop);
42456		ojpop.realign();
42457		
42458		if (GLO.Info.isMobile(true)) {
42459			setTimeout(function() { ojpop.realign(); }, 900);
42460		} else {
42461			jpop.css({ "top": "40px" });
42462		}
42463	}
42464
42465	_cProfilePayment.openHelpTipCalculation = function() {
42466		var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;';
42467		var label = '<b class="narrow-text">Ticket Service Price Only</b>'
42468		var arrow = '<b class="arrow-right">&#10140;</b>';
42469		
42470		var msg1 = '<p style="' + css1 + '">Enabling tip calculation based on ' + label + ' displays tip percent suggestions based on only the service price, does not include: '
42471		 			+ 'any products and is before discounts and add-on fees are applied (if any)</p>';
42472		var msg2 = '<p>We suggest enabling this setting, if you run many discounts or promotions ' + arrow + ' this helps staff increase their tip income!</p>';
42473		
42474		var pctCustom = '<i class="narrow-text">(enable this setting if you run a lot of discounts or promotions)</i>';
42475		
42476		var hTicket = '<h4>Example ticket with discounts, taxes and fees</h4>';
42477		var msgTicket = '<p>See Clover tip suggestions below without and with ticket  enabled.</p>';
42478		var imgTicket = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-calculation-ticket.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>';
42479
42480		var hPct = '<h3>Tip Calculation with ' + label + ' <b>NOT</b> Enabled</h3>';
42481		var msgPct = '<p> Clover tip suggestions are based on amount after discounts, gift cards, etc. resulting in lower tip amount</p>';
42482		var imgPct = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-suggestions-with-ticket-list-price-disabled.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>';
42483		
42484		var hDollar = '<h3>With ' + label + ' <b>Enabled</b></h3>';
42485		var msgDollar = '<p>Clover tip suggestions are based on original ticket amount resulting in higher tip amount</p>';
42486		var imgDollar = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/tip-suggestions-with-ticket-list-price-en
42486abled.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>';
42487		
42488		var htm = '<div id="pop-help-tip-percent-or-dollar">' + msg1 + hTicket + msgTicket + imgTicket + hPct + msgPct + imgPct + hDollar + msgDollar + imgDollar + '</div>';
42489		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Tip Suggestions on Clover', null, null, true);
42490		var jpop = ojpop.getPopup();
42491		
42492		jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" });
42493		GLO.Popup.Custom.singleButton(jpop);
42494		ojpop.realign();
42495		
42496		if (GLO.Info.isMobile(true)) {
42497			setTimeout(function() { ojpop.realign(); }, 900);
42498		} else {
42499			jpop.css({ "top": "40px" });
42500		}
42501	}
42502
42503	_cProfilePayment.openHelpSplitTip = function() {
42504		var msg1 = '<p style="margin: 0; margin-top: 8px; text-align: center;">By default, set how to Split Tip on Ticket between Staff</p>';
42505		var msg2 = '<p class="narrow-text" style="text-align: center;">(the tip on any ticket can be changed as needed)</p>';
42506		
42507		var list = '', jSplitOptions = $('#split-tip-options #Split_Tip_cd').find('option');
42508		
42509		for (var i=0; i < jSplitOptions.length; i++) {
42510			var label = '<h5>' + jSplitOptions.eq(i).text().replace('(default)', 'Default') + '</h5>';
42511			//var description = '<p style="margin-bottom: 8px;">' + jSplitOptions.eq(i).attr('title').replace(' | ', '<br/>') + '</p>';
42512			var title = jSplitOptions.eq(i).attr('title')
42513			var description = GLO.Report.CellSummary.getCellDescription(title);
42514			
42515			list += '<li>' + label + description + '</li>';
42516		}
42517		
42518		list = '<ul>' + list + '</ul>';
42519		var disclaimer = _getSplitTipDisclaimer();
42520		var htm = '<div id="pop-help-tip-split">' + msg1 + msg2 + list + disclaimer + '</div>';
42521		var ojpop = GLO.Popup.Custom.openSimple(htm, 'How Split Tip on Ticket Between Staff', null, null, true);
42522		var jpop = ojpop.getPopup();
42523		
42524		jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" });
42525		GLO.Popup.Custom.singleButton(jpop);
42526	}
42527	function _getSplitTipDisclaimer() {
42528		if (GLO.Data.provider.merchants && GLO.Data.provider.merchants.length > 1) {
42529			return '<div id="pop-help-tip-split-disclaimer" class="narrow-text" style="font-style: italic;">'
42530					+ '<p><b>Split Tip = "evenly"</b>, is not supported on tickets with multiple merchant accounts (when the client tips on the Clover device)</p>'
42531					+ '<p>For these tickets the tip will be split by <b>Total Price</b> (default) or <b>Service Price</b></p>'
42532				+ '</div>';
42533		}
42534		
42535		return '';
42536	}
42537	
42538	_cProfilePayment.saveTipPercents = function(mId) {
42539		var url = GLO.Link.WebsiteDomain + 'api/Bolt/SaveTipPercents/' + mId;
42540		var jpop = $('#bolt-tip-percent-setup').closest('.glopop');
42541		var tip1 = jpop.find('#Tip_Percent_1').val(), tip2 = jpop.find('#Tip_Percent_2').val(), tip3 = jpop.find('#Tip_Percent_3').val();
42542		var enableTipOnDevice = jpop.find('#Enable_Bolt_Tip_fl').prop('checked');
42543		var tipMode = jpop.find("input[name='tip-config']:checked").val();
42544		var splitTip = jpop.find('#Split_Tip_cd').val();
42545		var useListPriceForTipCalc = jpop.find('#Enable_Bolt_Tip_On_List_Price_fl').prop('checked');
42546
42547		var jd = { "deviceTipSettings": {"tipEnabled": enableTipOnDevice, "tipMode": tipMode, "tip1percent": tip1, "tip2percent": tip2, "tip3percent": tip3, "splitTip": splitTip, "useListPrice": useListPriceForTipCalc }};
42548		
42549		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
42550		
42551		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
42552            .success(function (data, textStatus, jqXHR) {
42553                if ($(data).hasClass('error')) {
42554                	GLO.UI.Form.resetProcessing();
42555                	GLO.Popup.Warning.open(data, 'Unable to Save');
42556                } else {
42557	                GLO.Popup.close(jpop);
42558	                GLO.Popup.Success.open('Clover Tip Settings Updated', 'Changes Saved');
42559	                GLO.Data.provider.split_tip_cd = splitTip;
42560                }
42561            })
42562            .error(function (jqXHR, textStatus, errorThrown) {
42563            	GLO.UI.Form.resetProcessing();
42564            	GLO.Popup.close(jpop);
42565            });
42566	}
42567
42568	_cProfilePayment.saveGetConfirmationText = function(mId) {
42569		var url = GLO.Link.WebsiteDomain + 'api/Bolt/SaveGetConfirmationText/' + mId;
42570		var jpop = $('#bolt-get-confirmation-setup').closest('.glopop');
42571		var getConfirmationText = jpop.find('#Get_Confirmation_Text_vc').val();
42572		var enableGetConfirmationOnDevice = jpop.find('#Enable_Bolt_Get_Confirmation_fl').prop('checked');
42573
42574		
42575		var jd = { "deviceConfirmationSettings": {"getConfirmationEnabled": enableGetConfirmationOnDevice, "confirmationPromptText": getConfirmationText }};
42576		
42577		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
42578		
42579		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
42580            .success(function (data, textStatus, jqXHR) {
42581                if ($(data).hasClass('error')) {
42582                	GLO.UI.Form.resetProcessing();
42583                	GLO.Popup.Warning.open(data, 'Unable to Save Text');
42584                } else {
42585	                GLO.Popup.close(jpop);
42586	                GLO.Popup.Success.open('Clover Settings Updated', 'Changes Saved');
42587                }
42588            })
42589            .error(function (jqXHR, textStatus, errorThrown) {
42590            	GLO.UI.Form.resetProcessing();
42591            	GLO.Popup.close(jpop);
42592            });
42593	}	
42594
42595	_cProfilePayment.LogConfirmationToApptUpdateLog = function(scheduleMultiId) {
42596		var url = GLO.Link.WebsiteDomain + 'schedule/SaveConfirmationToApptUpdates?smid=' + scheduleMultiId;
42597		// var jpop = $('#bolt-get-confirmation-setup').closest('.glopop');
42598		// var getConfirmationText = jpop.find('#Get_Confirmation_Text_vc').val();
42599		// var enableGetConfirmationOnDevice = jpop.find('#Enable_Bolt_Get_Confirmation_fl').prop('checked');
42600		
42601		// GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
42602		
42603		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: null })
42604            .success(function (data, textStatus, jqXHR) {
42605                if ($(data).hasClass('error')) {
42606                	GLO.UI.Form.resetProcessing();
42607                	GLO.Popup.Warning.open(data, 'Unable to Save Confirmation to Appointment Updates');
42608                } else {
42609	                // GLO.Popup.close(jpop);
42610	                GLO.Popup.Success.open('Appointment Updated', 'Changes Saved');
42611                }
42612            })
42613            .error(function (jqXHR, textStatus, errorThrown) {
42614            	GLO.UI.Form.resetProcessing();
42615            	// GLO.Popup.close(jpop);
42616            });
42617	}
42618
42619
42620	_cProfilePayment.openHelpCloverConfirmation = function() {
42621		var css1 = 'padding-left: 12px; padding-right: 6px; letter-spacing: 0;';
42622		var msg1 = '<p style="' + css1 + '">Clover can be setup to ask client to confirm a <b class="narrow-text">Question</b> or a <b class="narrow-text">Policy</b></p>';
42623		var pctCustom = '<i class="narrow-text">(if client does not confirm message payment will be canceled.)</i>';
42624		
42625		var hPct = '<h3>Question or Message on Clover</h3>';
42626		var msgPct = '<p> Clover can display a question or message like policy text and require client to confirm it.' + pctCustom + '</p>';
42627		var imgPct = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/read-confirmation.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>';
42628		
42629		var hDollar = '<h3>Client Confirmation</h3>';
42630		var msgDollar = '<p>Client confirmation gets recorded in the appointment update history.</p>';
42631		var imgDollar = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/Clover/Mini/confirmation-log.jpg" style="width: 90%; max-width: 480px; margin: auto;"/>';
42632		
42633		var htm = '<div id="pop-help-tip-percent-or-dollar">' + msg1 + hPct + msgPct + imgPct + hDollar + msgDollar + imgDollar + '</div>';
42634		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Ask a question on Clover', null, null, true);
42635		var jpop = ojpop.getPopup();
42636		
42637		jpop.find('a.modalClose').css({ "top": "2px", "right": "2px" });
42638		GLO.Popup.Custom.singleButton(jpop);
42639		ojpop.realign();
42640		
42641		if (GLO.Info.isMobile(true)) {
42642			setTimeout(function() { ojpop.realign(); }, 900);
42643		} else {
42644			jpop.css({ "top": "40px" });
42645		}
42646	}
42647
42648    return _cProfilePayment;
42649})();
42650
42651SA.Profile.Referral = (function() {
42652	function _cProfileReferral() { }
42653	var _jpopNewReferralForm;
42654
42655	_cProfileReferral.openSubmitNewReferral = function() {
42656		if (UTIL.isEmpty(_jpopNewReferralForm)) {
42657			_jpopNewReferralForm = $('#new-referral-form').outerHTML();
42658			$('#new-referral-form').remove();
42659		}
42660		
42661		var jpop = GLO.Popup.Custom.openSimple(_jpopNewReferralForm, 'Submit New Referral', function () { return SA.Profile.Referral.saveReferral(); });
42662		//phone mask for referral phone
42663		UI.phoneMask(jpop.find('#Referral_Phone_vc'));
42664	}
42665
42666	_cProfileReferral.saveReferral = function() {
42667		var url = GLO.Link.WebsiteDomain + 'provider/manage/SaveReferral';
42668		var jpop = $('#new-referral-form').closest('.glopop');
42669		//fields
42670		var fname = jpop.find('#Referral_First_Name_vc').val();
42671		var lname = jpop.find('#Referral_Last_Name_vc').val();
42672		var bizname = jpop.find('#Referral_Business_Name_vc').val();
42673		var bizsize = jpop.find('#Referral_Business_Size_vc').val();
42674		var email = UTIL.coalesceString(jpop.find('#Referral_Email_vc').val(),'');
42675		var phone = jpop.find('#Referral_Phone_vc').val();
42676		var address = UTIL.coalesceString(jpop.find('#Referral_Street_vc').val(),'');
42677		var city = jpop.find('#Referral_City_vc').val();
42678		var state = $('#Referral_State_cc').val();
42679		var zip = jpop.find('#Referral_Zip_vc').val();
42680		var notes = UTIL.coalesceString(jpop.find('#Notes_vc').val(),'');
42681		
42682
42683		var jd = { "newReferral": {"FirstName": fname, "LastName": lname, "BusinessName": bizname, 
42684			"BusinessSize": bizsize, "Email": email, "Phone": phone, "Address": address, 
42685			"City": city, "State": state, "PostalCode": zip, "Notes": notes
42686		 }};
42687		
42688		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
42689		
42690		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
42691            .success(function (data, textStatus, jqXHR) {
42692                if (data && Object.keys(data).length > 0) {
42693					if (data.status != 'success') {
42694						GLO.UI.Form.resetProcessing();
42695                		GLO.Popup.Warning.open(data.message, 'Unable to Save New Referral. Please try again. Email [email protected]');
42696					}
42697					else {
42698						GLO.Popup.close(jpop);
42699						GLO.Popup.Success.open('Thank you for your referral', 'New Referral Submitted');
42700						SA.Profile.Referral.getReferrals();
42701					}
42702
42703                } else {
42704					GLO.UI.Form.resetProcessing();
42705					GLO.Popup.Warning.open(data, 'Unable to Save New Referral. Please try again. Email [email protected]');
42706                }
42707            })
42708            .error(function (jqXHR, textStatus, errorThrown) {
42709            	GLO.UI.Form.resetProcessing();
42710            	GLO.Popup.close(jpop);
42711            });
42712	}
42713
42714	_cProfileReferral.getReferrals = function() {
42715
42716		var uri = GLO.Link.WebsiteDomain + 'provider/manage/getreferrals';
42717	
42718		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
42719			.done(function(data, textStatus, jqXHR) {
42720				window.onbeforeunload = null;
42721				if(data!=null && data!== '') {
42722					//if data has status property then there was an issue
42723					if (Object.hasOwnProperty('status')) {
42724						if (data.status == 'fail') { 
42725							new GLO.Popup.Error('Could not get the referrals - ' + data.message);
42726						}
42727						else {
42728							new GLO.Popup.Error('Could not get the referrals');
42729						}
42730					}
42731					
42732					var referrals = data;
42733					if (referrals.length > 0) {
42734						generateReferralsList(referrals);
42735					}
42736					else {
42737						generateReferralsListEmptyState();
42738					}
42739
42740				  } else {
42741					new GLO.Popup.Error('Could not get the referrals');
42742				  }				
42743			})
42744			.fail(function(jqXHR, textStatus, errorThrown) {
42745				GLO.UI.Form.resetProcessing(); 		
42746				new GLO.Popup.Error('Could not get the referrals');
42747			});
42748	}
42749
42750	_cProfileReferral.shareReferralLinkEmail = function() { 
42751		//not implemented
42752	}
42753
42754	_cProfileReferral.shareReferralLinkSms = function() { 
42755        var url = GLO.Link.WebsiteDomain + 'message/sharereferralsms';
42756        
42757        var jpop = $('#send-referral-container');
42758        var jsave = jpop.find('.btnSave');
42759        GLO.UI.Form.beginProcessing(jsave);
42760        
42761        var referralName = UTIL.cleanString(jpop.find('#Send_Referral_Name_vc').val());
42762        var referralPhone = UTIL.cleanString(jpop.find('#Send_Referral_Phone_vc').val().replace(/\D/g, ''));
42763
42764		if (0 < referralPhone.length && referralPhone.length < 10) {
42765			GLO.Popup.Warning.open(data.message, 'Invalid Phone');
42766			event.preventDefault();
42767			return;
42768		  }
42769
42770        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { referralShare: { "Name": referralName, "Phone": referralPhone }  } })
42771            .success(function(data, textStatus, jqXHR) {
42772                
42773                if (data && Object.keys(data).length > 0) {
42774					if (data.status != 'success') {
42775						GLO.UI.Form.resetProcessing();
42776                		GLO.Popup.Warning.open(data.message, 'Send Referral Error');
42777					}
42778					else {
42779						GLO.UI.Form.resetProcessing();
42780						GLO.Popup.Success.open('Thank you for spreading the word about us', 'Invitation Sent');
42781						// SA.Profile.Referral.getReferralShares(); //future
42782					}
42783
42784                } else {
42785					GLO.UI.Form.resetProcessing();
42786					GLO.Popup.Warning.open(data.message, 'Send Referral Error');
42787                }
42788            })
42789            .error(function(jqXHR, textStatus, errorThrown) {
42790                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
42791            });
42792	}
42793
42794
42795	var generateReferralsList = function(json) {
42796		var deviceCount = 0;
42797		
42798		//clear all the rows
42799		$('#referral-table-body').empty();
42800
42801		if (UTIL.isJson(json)) {				//typeof json.length !== 'undefined'
42802			// $('#pax-column-header').addClass('hide');
42803			$('#referral-column-header').removeClass('hide');
42804			
42805			var referrals = json;
42806
42807			
42808			for (var i = 0; i < referrals.length; i++) {				//Append each row to html table
42809
42810			    var tr = $('<tr/>');
42811			    tr.append('<td class="referral-column-name">' + referrals[i].BusinessName + '</td>');
42812			    tr.append('<td class="referral-column-signup-date">' + ( referrals[i].SignupDateTime  == null ? '' : referrals[i].SignupDateTime )+ '</td>');
42813			    tr.append('<td class="referral-column-payout">' + ( referrals[i].NextPayoutDateTime == null ? '' : referrals[i].NextPayoutDateTime ) + '</td>');
42814			    tr.append('<td class="referral-column-bonus">' + ( referrals[i].BonusPayoutDateTime == null ? '' : referrals[i].BonusPayoutDateTime ) + '</td>');
42815			    tr.append('<td class="referral-column-status">' + referrals[i].Status + '</td>');
42816				$('table#ReferralList').append(tr);
42817			
42818			}
42819			
42820			
42821			UI.initTableSorter($('#report-main table.tablesorter'));
42822		}
42823		
42824	}
42825
42826	var generateReferralsListEmptyState = function() {
42827		var tr = $('<tr/>');
42828		tr.append('<td class="referral-empty-state" colspan="5">' + 'No referrals yet. Click "Submit a Referral" above to submit a referral.' + '</td>');
42829		$('table#ReferralList').append(tr);
42830	}
42831
42832
42833
42834	return _cProfileReferral;
42835})();
42836
42837
42838GLO.MyAppts = (function() {
42839    function _constructor(name) { }
42840    _constructor.currentTab = 1;
42841    _constructor.MAX_TAB = 4;
42842    _constructor.isActivityView = false;
42843
42844    _constructor.init = function() {
42845        _constructor.isActivityView = true;
42846        GLO.Info.init();
42847        
42848        //Step I: Setup Tabs
42849            UI.initTableSorter( $('#myAppointments-updates table') );                   //= Recent Activity.
42850            UI.initTableSorter( $('#myAppointments-upcoming table') );                  //= Upcoming.
42851            GLO.WaitList.init();
42852            UI.initTableSorter( $('#myOtherEdits table') );                             //= Other Edits.
42853        
42854        //Step II: Setup Search on each tab
42855            GLO.MyAppts.initSearch('#myAppointments-updates', 7, 0, true);
42856            GLO.MyAppts.initSearch('#myAppointments-upcoming', 0, 7);
42857            GLO.MyAppts.initSearch('#myOtherEdits', 7, 0, true);
42858        
42859       //Step III: Display Tabs
42860            $('#displayProfile-Client').addClass('hide');
42861            $('#searchResults-Client').parent().addClass('hide');    
42862            $('#staff-portal-header').removeClass('hide');
42863
42864            var initTab = GLO.Uri.url('tab');
42865
42866            if (!UTIL.isEmpty(initTab)) { 
42867                initTab = initTab.toLowerCase();
42868                
42869                if (initTab === 'recent' || initTab == 1) {
42870                    initTab = 1;
42871                } else if (initTab === 'upcoming' || initTab == 2) {
42872                    initTab = 2;
42873                } else if (initTab === 'other' || initTab == 3) {
42874                    initTab = 3;
42875                } else if (initTab === 'wait' || initTab == 4) {
42876                    initTab = 4;
42877                    
42878                    if (UTIL.parseBool(GLO.Uri.url('add'))) {
42879                    	$('#waiting-list-buttons').find('.btnAdd > a').click();
42880                    }
42881                }
42882            } else {
42883                initTab = GLO.MyAppts.currentTab;
42884            }
42885        
42886            var mustSearch = GLO.MyAppts.goToTab(initTab, true);
42887        
42888        //Step IV: Setup header buttons, Tab/HelpIcon Titles, search f
42888ilter
42889            _addAllToFilter();
42890            _setupHeader();
42891            _setTitle();
42892            
42893            $('.appt-list-search:visible').find('.btnSearch > a:visible').click();			//_initUrlAction(mustSearch);
42894            $('#hd-waiting-list').remove();
42895            GLO.Report.enableFullPageCheck();
42896        
42897        //Step V: Shortcut Keys
42898            $(document).keydown(function(event) {
42899                if (event.ctrlKey) {
42900                    switch (event.which) {
42901                        case 37:                    //left arrow key.
42902                            GLO.MyAppts.goToTab(--GLO.MyAppts.currentTab);
42903                            break;
42904                        case 39:                    //right arrow key.
42905                            GLO.MyAppts.goToTab(++GLO.MyAppts.currentTab);
42906                            break;
42907                    }
42908                }
42909            });
42910
42911            $(window).bind('keypress', function(event) {
42912                if (event.ctrlKey) {
42913                    switch (event.which) {
42914                        case 37:                    //left arrow key.
42915                        case 39:                    //right arrow key.
42916                            event.preventDefault();
42917                    }
42918                }
42919            });
42920    }
42921    
42922    function _addAllToFilter() {
42923    	if (GLO.Info.isMobile() && GLO.Info.roleType > 199) {
42924        	var jfilter = $('#staff-filter');
42925        	
42926        	if (jfilter.find('option').length > 1) {
42927	        	var jfirst = jfilter.find('option:first');
42928	        	
42929	        	if (UTIL.isEmpty(jfirst.val())) {
42930	        		jfirst.text(' All').attr('value', 'all');
42931	        	} else {
42932	        		jfilter.prepend('<option value="all"> ALL</option>');
42933	        		jfirst = jfilter.find('option:first');
42934	        	}
42935	        	
42936	        	var sfilter = GLO.Uri.url('sfilter');
42937	        	var isNotInFilter = (jfilter.find('option[value="' + sfilter + '"]').length === 0);		//= can happen when receptionist not assigned to any services.
42938	        	
42939	        	if (UTIL.coalesce(sfilter, 'all') == 'all' || isNotInFilter) {
42940	        		jfirst.prop('selected', true);
42941	        		
42942	        		if (UTIL.coalesce(sfilter, 'all') != 'all') {
42943	        			GLO.Report.setStaffFilter('all');
42944	        		}
42945	        	}
42946        	}
42947        }
42948    }
42949    
42950    function _initUrlAction(mustSearch) {
42951    	var begin = UTIL.coalesce(GLO.Uri.hash('begin'), GLO.Uri.hash('start'));
42952    	var end = GLO.Uri.hash('end');
42953    	var beginEdit = UTIL.coalesce(GLO.Uri.hash('beginEdit'), GLO.Uri.hash('startEdit'));
42954    	var endEdit = GLO.Uri.hash('endEdit');
42955    	
42956    	var cid = GLO.Uri.hash('cid');
42957    	var client = GLO.Uri.hash('client');
42958    	var isBookedByClient = UTIL.parseBool(GLO.Uri.hash('BookedByClient'));
42959    	var service = UTIL.cleanString(GLO.Uri.hash('service')).toLowerCase();
42960    	var hasFilter = false;
42961    	var jfilter = $('.appt-list-search:visible');
42962    	
42963    	if (UTIL.isDate(begin)) {
42964    		hasFilter = true;
42965    		jfilter.find('.Begin_dt').val(begin);
42966    	}
42967    	
42968    	if (UTIL.isDate(end)) {
42969    		hasFilter = true;
42970    		jfilter.find('.End_dt').val(end);
42971    	}
42972    	
42973    	if (jfilter.closest('.activity-view-panel').attr('id') == 'myAppointments-updates') {
42974    		if (UTIL.isDate(beginEdit)) {
42975	    		hasFilter = true;
42976	    		jfilter.find('.Edit_Begin_dt').val(beginEdit);
42977	    	}
42978	    	
42979	    	if (UTIL.isDate(endEdit)) {
42980	    		hasFilter = true;
42981	    		jfilter.find('.Edit_End_dt').val(endEdit);
42982	    	}
42983    	}
42984    	
42985    	if (!UTIL.isEmpty(cid)) {
42986    		hasFilter = true;
42987    		var jclient = jfilter.find('.search-Client_id');
42988    		
42989    		jclient.attr('autoId', cid);
42990    		jclient.val(client);
42991    	}
42992    	
42993    	if (!UTIL.isEmpty(service)) {
42994    		hasFilter = true;
42995    		jfilter.find('.Service_Filter').val(service);
42996    	}
42997    	
42998    	if (isBookedByClient) {
42999    		jfilter.find('.Update_By_Client_fl').prop('checked', true);
43000    	}
43001    	
43002    	if (hasFilter) {
43003    		jfilter.find('.btnSearch > a:visible').click();
43004    		UI.highlight(jfilter, 800, 6400, true);
43005    	} else if (mustSearch) {
43006    		jfilter.find('.btnSearch > a:visible').click();
43007    	}
43008    }
43009    
43010    function _setupHeader() {
43011        var jHeaderBtns = $('#apptPortal-cal-btns');
43012        UI.addButtonEffects( jHeaderBtns.find('#calAll-button') );
43013        jHeaderBtns.find('#calList-button').addClass('ui-state-active');
43014            
43015        UI.addButtonEffects( jHeaderBtns.find('.fc-button-month') );
43016        UI.addButtonEffects( jHeaderBtns.find('.fc-button-agendaWeek') );
43017        UI.addButtonEffects( jHeaderBtns.find('.fc-button-agendaDay') );
43018
43019        if (GLO.Info.isMobile(true)) {
43020            setTimeout( function() {      //so overrides style set on _providerLayout.cshtml.
43021                $('#apptPortal-cal-btns').css({ "font-size": "116%" });
43022                //$('#bd').css({ "margin-top": "15px" });
43023            }, 400);
43024
43025            $('.hasDatepicker').click(function() { 
43026                $(this).blur();
43027            });
43028
43029            $('.ui-datepicker-next, .ui-datepicker-prev').on('mouseup', function() { 
43030                $(document.activeElement).blur();
43031            });
43032            
43033            //if ($('#hd-mobile').length === 0) {
43034            //	$('#easySearch_text').css({ "width": "18.1em" });		//.attr('title', 'Client search by name or phone');
43035            //}
43036        } else {
43037            //$('#easySearch_text').css({ "width": "17.25em" });
43038            //$('#easySearch_text').css({ "width": "17em" });			//.attr('title', 'Client search by name or phone');
43039        }
43040
43041        if ($('#inactiveStaffBar:visible').length > 0 && $('#staffFilter:visible').length > 0) {
43042            var top = 25;
43043            if ( $('.hello-bar-container').length > 0) { top = 50; }
43044            
43045            $('#inactiveStaffBar:visible').css({ "top": (top + "px") });
43046            $('#doc3').css({ "margin-top": (top + 25 + "px") });
43047        } else if ($('#staffFilter:visible').length > 0) {
43048            var top = 30;
43049            if ( $('.hello-bar-container').length > 0) { top = 58; }
43050            
43051            $('#doc3').css({ "margin-top": (top + "px") });
43052        }
43053    }
43054
43055    function _setTitle() {
43056        GLO.Info.init();
43057        var sfilter = GLO.Uri.query('sfilter');
43058        var stitle;
43059
43060        if (UTIL.isEmpty(sfilter)) {
43061            if (GLO.Info.providerPackage == 1) {
43062                stitle = SA.Resource.My.toLowerCase();
43063            } else if (GLO.Info.roleType > 209) {
43064                stitle = SA.Resource.AnyStaffMembers.toLowerCase();
43065            } else {
43066                stitle = SA.Resource.My.toLowerCase();
43067            }
43068        } else if (sfilter.toLowerCase() === 'all') {
43069            stitle = SA.Resource.AnyStaffMembers.toLowerCase();
43070        } else if (sfilter.indexOf(",") === -1) {
43071            if (sfilter == GLO.Info.getStaffId()) {
43072                stitle = SA.Resource.My.toLowerCase();
43073            } else {
43074                stitle = $('#sfilter-hello-bar-label').text()
43075                
43076                if (UTIL.isEmpty(stitle)) { stitle = $('#staff-filter').find('option:selected').text(); }
43077                
43078                stitle += "'s";
43079            }
43080        } else {
43081            stitle = SA.Resource.SpecifiedStaffMembers.toLowerCase();
43082        }
43083
43084        var u = stitle.substring(0, 1).toUpperCase() + stitle.substring(1);
43085
43086        if (GLO.Info.roleType > 209) {
43087            var descEdit = SA.Resource.DescendingEdit;
43088            var descRecent = SA.Resource.DescendingRecent;
43089            var descUpcoming = SA.Resource.DescendingUpcoming;
43090        } else {
43091            var descEdit = SA.Resource.DescendingEdit2;
43092            var descRecent = SA.Resource.DescendingRecent2 + ' ' + stitle + ' ' + SA.Resource.Appointments;
43093            var descUpcoming = SA.Resource.DescendingRecent2 + ' ' + stitle + ' ' + SA.Resource.Appointments;
43094        }
43095
43096        var jtabs = $('#staff-portal-header');
43097        var jhelpicons = $('.helpIcon2');
43098        
43099        var titleRecent = SA.Resource.DescendingRecent2 + ' ' + stitle + ' ' + SA.Resource.Appointments;
43100        jtabs.find("#sfilter-tab-recent").attr("title", titleRecent);
43101        jhelpicons.eq(0).attr('title', titleRecent).attr('alt', descRecent);
43102
43103        var titleUpcoming = u + ' ' + SA.Resource.UpcomingAppointments;
43104        jtabs.find("#sfilter-tab-upcoming").attr("title", titleUpcoming);
43105        jhelpicons.eq(1).attr('title', titleUpcoming).attr('alt', descUpcoming);
43106
43107        var titleEdit = SA.Resource.MyEditsTo + ' ' + stitle + ' ' + SA.Resource.Appointments;
43108        jtabs.find("#sfilter-tab-other-edits").attr("title", titleEdit);
43109        jhelpicons.eq(2).attr('title', titleEdit).attr('alt', descEdit);
43110
43111        var titleWaiting = u + ' ' + SA.Resource.ClientWaitingList.toLowerCase();
43112        jtabs.find("#sfilter-tab-waiting-list").attr("title", titleWaiting);
43113        jhelpicons.eq(3).attr('title', titleWaiting).attr('alt', titleWaiting);
43114    }
43115
43116    _constructor.removeRecentRow = function(jTR) {
43117        var url = GLO.Link.Object.AppointmentAjax + 'UpdateSimple';
43118        var dbXml = UTIL.htmlEncode('<tr schedule_id="' + jTR.attr('id').substr(1) + '" update_status_cd="2" input_type_cd="10"/>');
43119        
43120        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { xml: dbXml } })
43121                .success(function(data, textStatus, jqXHR) { })
43122                .error(function(jqXHR, textStatus, errorThrown) { });
43123    }
43124
43125    _constructor.search = function(btn) {
43126        btn = $(btn);
43127        var jSheet = btn.closest('.appt-list-sheet');
43128        var jResult = jSheet.find('.appt-list-result');
43129        var jTabBodyId = jSheet.parent().attr('id');
43130        
43131        if (jResult.find('.must-load-data').length === 0) {
43132        	jResult.html('');
43133        }
43134        
43135        if (jTabBodyId === 'myAppointments-updates') {
43136            var listType = '1';
43137        } else if (jTabBodyId === 'myAppointments-upcoming') {
43138            var listType = '2';
43139        } else if (jTabBodyId === 'myOtherEdits') {
43140            var listType = '3';
43141        }
43142
43143        var begin = jSheet.find('.Begin_dt').val();
43144        var end = jSheet.find('.End_dt').val();
43145        var beginEdit = jSheet.find('.Edit_Begin_dt').val();
43146        var endEdit = jSheet.find('.Edit_End_dt').val();
43147        
43148        var jclient = jSheet.find('.search-Client_id');
43149        var cid = '', bookingNumber = $.trim(jSheet.find('.Booking_nr').val());
43150        var isEditByClient = jSheet.find('.Update_By_Client_fl').prop('checked');
43151        
43152        if (!UTIL.isEmpty(jclient.val())) {						//= if client search text box is empty don't include (in case they did search with client, then cleared client name box).
43153        	cid = UTIL.cleanString(jclient.attr('autoId'));
43154        }
43155        
43156        if (new Date(begin).getTime() > new Date(end).getTime() ) {
43157            new GLO.Popup.Warning('<h1 style="margin-bottom: 15px; margin-top: -20px; color: White;">' + SA.Resource.InvalidDateRange + '</h1><div style="margin-left: 10px; margin-bottom: -15px;">' + SA.Resource.BeginDateWarning + '</div>');
43158            return;
43159        }
43160        
43161        var rows = UTIL.coalesceString(jSheet.find('.activity-row-count').val(), GLO.Uri.url('rows'));
43162        var searchData = '<tr client_id="' + cid + '" start_dt="' + begin + '" end_dt="' + end + '" edit_start_dt="' + beginEdit + '" edit_end_dt="' + endEdit
43163        				+ '" booking_vc="' + bookingNumber + '" rows="' + rows + '" list_type_cd="' + listType
43164                        + '" staff_id="' + GLO.Uri.query('sfilter') + '" service_filter="' + jSheet.find('.Service_Filter').val() + '" update_by_client_fl="' + isEditByClient + '"/>';
43165        
43166        var dbXml = UTIL.htmlEncode(searchData);
43167        var url = GLO.Link.Object.Provider.ApptList;
43168        GLO.UI.Form.beginProcessing(btn.parent());
43169
43170        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { xml: dbXml } })
43171                .success(function(data, textStatus, jqXHR) {
43172                    GLO.UI.Form.resetProcessing();
43173                    
43174                    var jd = $(data);
43175                    var jno = jd.find('.noResults');
43176                    
43177                    if (jno.length > 0) {
43178                    	jResult.html(jno.outerHTML()).removeClass('hide');
43179                    } else {
43180                    	jResult.html(jd.find('.tablesorter')).removeClass('hide');
43181                    	UI.initTableSorter( $('#' + jSheet.parent().attr('id') + ' table') );
43182                    }
43183                    
43184                    _finishLoadActivityViewData(jResult);
43185                })
43186                .error(function(jqXHR, textStatus, errorThrown) {
43187                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
43188                });
43189    }
43190    
43191    function _finishLoadActivityViewData(jResult) {
43192    	var colSpan = jResult.find('table thead th:visible').length;
43193    	jResult.find('table tr.infoRow th').attr('colspan', colSpan);
43194    }
43195
43196    _constructor.goToTab = function(tab, isInit) {
43197        if (tab > _constructor.MAX_TAB) { 
43198            tab = 1;
43199        } else if (tab < 1) {
43200            tab = _constructor.MAX_TAB;
43201        }
43202        
43203        $('#myAppointments-upcoming').addClass('hide');
43204        $('#myAppointments-updates').addClass('hide');
43205        $('#myAppointments-wait').addClass('hide');
43206        $('#myOtherEdits').addClass('hide');
43207        
43208        if (tab === 1) {
43209            var jvw = $('#myAppointments-updates').removeClass('hide');
43210        } else if (tab === 2) {
43211            var jvw = $('#myAppointments-upcoming').removeClass('hide');
43212        } else if (tab === 3) {
43213            var jvw = $('#myOtherEdits').removeClass('hide');
43214        } else if (tab === 4) {
43215            var jvw = $('#myAppointments-wait');
43216            var jwaitPop = jvw.closest('.glopop');
43217            
43218            if (jwaitPop.length === 1) { jvw = jwaitPop; }
43219            
43220            var h2 = jvw.find('h2');
43221            
43222            if (h2.length === 1) {
43223                jvw.find('#waiting-list-container').css({ "clear": "both" });
43224                h2.remove();
43225                jvw.find('#waiting-list-th-note').css({ "width": "500px" });
43226                //jvw.prepend( jvw.find('#waiting-list-buttons').css({ "padding-top": "20px", "padding-bottom": "50px", "margin-left": "100px" }) );
43227            }
43228
43229            jvw.removeClass('hide');
43230        }
43231
43232        var backColor = $('.shadow-content0').css('backgroundColor');
43233        var oj = $('#staff-portal-header table tr td span b');
43234        
43235        oj.each(function() {
43236            $(this).parent().parent().removeClass('staff-tab').css('backgroundColor', '');
43237        });
43238        
43239        _constructor.currentTab = tab;
43240        if (tab == 4 && GLO.Info.providerPackage === 1) { tab = 3; }
43241        
43242        oj = oj.eq(tab - 1).parent().parent();
43243        oj.addClass('staff-tab');
43244        oj.css('backgroundColor', backColor);
43245        
43246        if (jvw.find('.must-load-data').length > 0) {
43247        	jvw.find('.must-load-data').addClass('loading-data');			//.removeClass('must-load-data');
43248        	
43249        	if (isInit) {
43250        		return true;
43251        	} else {
43252        		jvw.find('.btnSearch').find('a').click();
43253        	}
43254        }
43255        
43256        _changeTabSetHashUriKey(tab);
43257        return false;
43258    }
43259    
43260    function _changeTabSetHashUriKey(tab) {
43261    	if (!UTIL.isEmpty(GLO.Uri.query('tab'))) { return; }
43262    	
43263    	GLO.Uri.hash('tab', tab);
43264    }
43265
43266    _constructor.initSearch = function(selector, ibegin, iend, maxIsToday) {
43267        var j = $(selector);
43268        var jclient = j.find('.search-Client_id');
43269        
43270        Search.init(selector + ' .search-Client_id', GLO.Link.Object.Provider.UserSearch);
43271        UI.initAutoComplete(jclient, GLO.Link.Object.Provider.UserSearch);
43272        UI.setAccessKey(selector, GLO.MyAppts.search);
43273        
43274        var start = GLO.Uri.url('start'), end = GLO.Uri.url('end');
43275        var startEdit = GLO.Uri.url('startEdit'), endEdit = GLO.Uri.url('endEdit');
43276        
43277        var svc = UTIL.coalesceString(GLO.Uri.url('servicefilter'), GLO.Uri.url('service'));
43278        var clientId = GLO.Uri.url('clientid'), clientName = GLO.Uri.url('clientname');
43279        var isBookedByClient = UTIL.parseBool(GLO.Uri.url('BookedByClient')) || UTIL.parseBool(GLO.Uri.url('isclient'));
43280    	
43281        if (UTIL.isNumber(clientId) && !UTIL.isEmpty(clientName)) {
43282        	jclient.attr('autoId', clientId).val(clientName);
43283        }
43284        
43285        if (UTIL.isDate(start)) {
43286        	var Begin_dt = new Date(start);
43287        } else {
43288	        var Begin_dt = new Date();
43289	        Begin_dt.setDate(Begin_dt.getDate() - ibegin);
43290        }
43291        
43292        if (UTIL.isDate(end)) {
43293        	var End_dt = new Date(end);
43294        } else {
43295	        var End_dt = new Date();
43296	        End_dt.setDate(End_dt.getDate() + iend);
43297        }
43298        
43299        var jStart = j.find('.Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
43300        								, numberOfMonths: UI.getDatepickerMonths(1480) });
43301        var jEnd = j.find('.End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
43302        								, numberOfMonths: UI.getDatepickerMonths(1080) });
43303        
43304        var jStartEdit = j.find('.Edit_Begin_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
43305        								, numberOfMonths: UI.getDatepickerMonths(1480), maxDate: 0 });
43306        var jEndEdit = j.find('.Edit_End_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
43307        								, numberOfMonths: UI.getDatepickerMonths(1080), maxDate: 0 });
43308        
43309        if (selector != '#myAppointments-updates' || UTIL.isDate(start)) {
43310        	jStart.val(Begin_dt.toGloDate());
43311        }
43312        if (selector != '#myAppointments-updates' || UTIL.isDate(end)) {
43313        	jEnd.val(End_dt.toGloDate());
43314        }
43315        
43316        if (jStartEdit.length && UTIL.isDate(startEdit)) {
43317        	jStartEdit.val(new Date(startEdit).toGloDate());
43318        }
43319        if (jEndEdit.length && UTIL.isDate(endEdit)) {
43320        	jEndEdit.val(new Date(endEdit).toGloDate());
43321        }
43322        
43323        if (maxIsToday) {
43324            var jEditBegin = j.find('.Edit_Begin_dt');
43325            
43326            if (jEditBegin.length) {
43327            	j.find('.Edit_Begin_dt').datepicker('option', 'maxDate', 0);
43328    	        j.find('.Edit_End_dt').datepicker('option', 'maxDate', 0);
43329            } else {
43330	            j.find('.Begin_dt').datepicker('option', 'maxDate', 0);
43331    	        j.find('.End_dt').datepicker('option', 'maxDate', 0);
43332            }
43333        }
43334        //$(selector + ' .Begin_dt').value = (Begin_dt.getMonth() + 1) + '/' + Begin_dt.getDate() + '/' + Begin_dt.getFullYear();
43335        //$(selector + ' .End_dt').value = (End_dt.getMonth() + 1) + '/' + End_dt.getDate() + '/' + End_dt.getFullYear();
43336        
43337        if (!UTIL.isEmpty(svc)) {
43338        	j.find('.Service_Filter').val(svc);
43339        }
43340        
43341        if (isBookedByClient) {
43342    		j.find('.Update_By_Client_fl').prop('checked', true);
43343    	}
43344    }
43345
43346    _constructor.openHelp = function(event, thisIcon) {
43347        thisIcon = $(thisIcon);
43348        var desc = '<p>' + thisIcon.attr('alt') + '</p>';					//var desc = $('.staff-tab').attr('title');
43349        var tabBody = thisIcon.closest('.appt-list-sheet').parent();
43350        var tabBodyId = tabBody.attr('id');
43351        
43352        if (tabBodyId === 'myAppointments-updates') {
43353            var bYellow = '<b class="narrow-text" style="padding: 2px 4px; white-space: nowrap; background-color: Yellow;">';
43354            var bGreen  = '<b class="narrow-text" style="padding: 2px 4px; white-space: nowrap; background-color: GreenYellow;">';
43355            
43356            tabBody.find('.lastUpdateDate, .recent-activity-last-edit').addClass('help-list-view-column-highlight');
43357            tabBody.find('.apptListDate, .recent-activity-appointment-start').addClass('help-list-view-column-highlight2');
43358            
43359            desc += '<p style="margin-top: 24px;">' + bYellow + 'Last Edit</b> date range that appointments have been ' + bYellow + SA.Resource.LastUpdated.toLowerCase() + '</b></p>';
43360            desc += '<p style="margin-bottom: 24px;">' + bGreen + 'Appointment</b> date range of ' + bGreen + 'appointment start date</b></p>';
43361        } else if (tabBodyId === 'myOtherEdits') {
43362            tabBody.find('.lastUpdateDate').addClass('help-list-view-column-highlight');
43363            desc += '<p>' + SA.Resource.LookForAppts + ' <b style="background-color: Yellow; padding: 2px 5px;">' + SA.Resource.LastUpdated.toLowerCase() + '</b> ' + SA.Resource.WithinThatRange + '</p>';
43364        } else if (tabBodyId === 'myAppointments-upcoming') {
43365            tabBody.find('.apptListDate').addClass('help-list-view-column-highlight');
43366            desc += '<p>' + SA.Resource.DateLookFor + ' <b style="background-color: Yellow; padding: 2px 5px;">' + SA.Resource.when_the_appointment_occurs + '</p>';
43367        }
43368        
43369        var rptName = $('#list-view-tabs').find('.staff-tab').text().substring(2);
43370        var rptNameCss = 'padding: 4px; letter-spacing: 2px; font-size: larger; border-bottom-left-radius: 0; border-bottom-right-radius: 0; color: white;';
43371        
43372        var htm = '<div id="pop-list-view-help">' + desc + '</div>';
43373        var ojInfo = new GLO.Popup.Info(htm, GLO.MyAppts.closeHelp).getPopup();
43374        
43375        ojInfo.prepend('<h1 style="' + rptNameCss + '">' + rptName + ' Report</h1>');
43376        ojInfo.find('#pop-list-view-help')
43377        	.append('<p style="margin-top: 20px;">Click the last updated column to see a list of all the changes made to an appointment</p>')
43378        	.append('<p style="margin-top: 20px; padding-bottom: 12px;">You can search for updates to a specific client\'s appointments by entering their name below, changing the dates as desired, and pressing search</p>');
43379    }
43380
43381    _constructor.closeHelp = function() {
43382        $('.help-list-view-column-highlight').removeClass('help-list-view-column-highlight');
43383        $('.help-list-view-column-highlight2').removeClass('help-list-view-column-highlight2');
43384    }
43385
43386    _constructor.displayEditReason = function(event, reason) {
43387        if (event.target.tagName.toUpperCase() !== 'A') {
43388            GLO.Popup.Info("<h1 style='color: White; margin-top: -18px; margin-bottom: 15px;'>" + SA.Resource.CancellationReason + "</h1><div style='margin-bottom: -10px;'>" + reason + "</div>");
43389        }
43390    }
43391
43392    _constructor.openHistory = function(event, thisTD) {
43393        var me = $(thisTD);
43394        GLO.UI.Form.beginProcessing(me);
43395        
43396        var tr = me.closest('tr');
43397        var sutype = tr.attr('sutype');
43398        var apptid = tr.attr('id');
43399        var scid = tr.attr('schedule_client_id');
43400        var day = tr.attr('appt_dt');
43401        var staffId = tr.attr('staff_id');
43402        
43403        _constructor.openHistory2(apptid, scid, sutype, day, staffId);
43404    }
43405    
43406	_constructor.openHistory2 = function(apptid, scid, sutype, day, staffId) {
43407        var url = null;
43408        
43409        if (UTIL.isNumber(sutype)) {
43410            sutype = parseInt(sutype);
43411			
43412            if (sutype > 99 && sutype < 120) {
43413                apptid = null;
43414                url = GLO.Link.Page.Provider.Home + 'schedule/history/' + UTIL.replaceAll(day, '/', '-') + '?sutype=' + sutype + '&staff=' + staffId;
43415            }
43416        }
43417		
43418        if (apptid !== null) {
43419        	url = GLO.Link.Page.Provider.Home + 'appointment/history/' + apptid;
43420        	
43421        	if (!UTIL.isEmpty(scid)) {
43422        		url += '?scid=' + scid;
43423        	}
43424        }
43425        
43426        if (UTIL.isEmpty(url)) {
43427        	GLO.Popup.Warning.open('Unable to Lookup History', 'History Not Found');
43428        	return;
43429        }
43430        
43431        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
43432            .success(function(data, textStatus, jqXHR) {
43433                GLO.UI.Form.resetProcessing();
43434
43435                var h1 = "<h1 id='appointment-history-header'>" + SA.Resource.AppointmentEditHistory + "</h1>";
43436                var htm = $(data).prepend(h1);
43437                
43438                var oj = new GLO.Popup.Custom(htm);
43439                var jpop = oj.getPopup().addClass('wide-popup').css({ "background-color": "white" });
43440                
43441                var jbtns = jpop.find('.pop-buttons').css({ "width": "300px" });
43442                jbtns.find('.btnCancel').remove();
43443                jbtns.find('.btnSave').removeClass('btnSave').addClass('btnOk').find('a').text('Ok').css({ "padding": "7px 20px" }).focus();
43444                
43445                oj.realign();
43446                $('#ba-EditAppointment').find('#imgThrobber').remove();
43447                
43448                var jtbl = jpop.find('.tablesorter');
43449                GLO.Report.CellSummary.initReport(jtbl, true);
43450            })
43451            .error(function(jqXHR, textStatus, errorThrown) {
43452                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
43453            });
43454    }
43455    
43456    _constructor.undeleteAppt = function(smid, scheduleId, dtDeleteDay) {
43457        if (GLO.Info.roleType < 220) {
43458        	var msg = '<p style="letter-spacing: 1px;">Manager or Admin required to un-delete appointment?</p>';
43459        	var htm = '<div id="pop-warn-undelete-appt">' + msg + '</div>';
43460        	
43461        	GLO.Popup.Confirm.open(htm, 'Permission Warning');
43462        	return;
43463        }
43464        
43465        var msg = '<p style="letter-spacing: 1px;">Are you sure you want to un-delete this appointment?</p>';
43466        var htm = '<div id="pop-confirm-undelete-appt">' + msg + '</div>';
43467        var fnYes = function() { GLO.MyAppts.undeleteApptConfirmed(smid, scheduleId, dtDeleteDay); };
43468        
43469        GLO.Popup.Confirm.open(htm, 'Confirm Appointment Un-Delete', fnYes);
43470    }
43471    _constructor.undeleteApptConfirmed = function(smid, scheduleId, dtDeleteDay) {
43472        var url = GLO.Link.WebsiteDomain + 'schedule/UnDeleteAppointment?smid=' + smid + '&scheduleId=' + scheduleId;
43473        var jpop = $('.glopop #apptHistory-container').closest('.glopop');		//= must do this way because opening popup does not remove popup html from original body
43474        var jbtn = jpop.find('#btnUndoDelete');
43475        
43476        if (UTIL.isEmpty(scheduleId)) {
43477        	url += '&cutoff=' + dtDeleteDay;
43478        }
43479        
43480        GLO.UI.Form.beginProcessing(jbtn);
43481        
43482        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
43483            .success(function(data, textStatus, jqXHR) {
43484                //GLO.UI.Form.resetProcessing();
43485                GLO.Popup.closeIfExist(jpop);
43486                GLO.Popup.Success.open('Appointment Successfully Un-Deleted', 'Appointment Un-Deleted');
43487                
43488                _constructor.refresh();
43489            })
43490            .error(function(jqXHR, textStatus, errorThrown) {
43491                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
43492            });
43493    }
43494    _constructor.refresh = function(delay) {
43495    	if (UTIL.parseBool(GLO.Uri.url('norefresh'))) {
43496    		return;
43497    	}
43498    	
43499    	var jbtn = $('#staffPortal-main').find('.btnSearch:visible > a');
43500    	
43501    	if (jbtn.length) {
43502    		jbtn.click();
43503    	} else {
43504    		var delay = UTIL.coalesceInt(delay, 5500);
43505    		
43506    		setTimeout(function() {
43507            	location.reload();
43508            }, delay);
43509    	}
43510    }
43511    
43512    _constructor.helpRecentActivity = function() {
43513    	var bFilter = '<b class="narrow-text" style="font-size: larger;">Filter:</b> ', bSort = '<b class="narrow-text" style="font-size: larger;">Sort:</b> ';
43514    	var bLastUpdated = '<b class="narrow-text" style="color: deeppink;">Last Updated</b>';
43515    	var bStart = '<b class="narrow-text" style="color: deeppink;">Appointment Start Date</b>';
43516    	
43517    	var p1 = '<p style="margin-bottom: 0; line-height: 1.4;">';
43518    	var p1b = '<p style="margin-top: 0; margin-bottom: 40px; margin-left: 40px; font-size: smaller; opacity: .6;">';
43519    	var li = '<li style="margin-bottom: 6px; line-height: 1;">';
43520    	
43521    	var msg1a = p1 + bFilter + '</p>';
43522    	var list1a = li + '<b class="narrow-text" style="color: #4F81BD;">Appointment</b> Begin / End Date filters on the ' + bStart + '</li>';
43523    	var list1b = li + '<b class="narrow-text" style="color: #4F81BD;">Last Edit</b> Begin / End Date filters when the appointment was ' + bLastUpdated + '</li>';
43524    	//var msg1b = p1b + 'On all other screens Begin / End Date filters by the ticket date <i class="narrow-text">(i.e. ' + bStart + ')</i></p>';
43525    	var msg1 = msg1a + '<ul>
43525' + list1a + list1b + '</ul>';
43526    	
43527    	var msg2a = p1 + bSort + 'On <b class="narrow-text">Recent Activity</b> the sort is the appointment ' + bLastUpdated + ' column</p>';
43528    	var msg2b = p1b + 'press column header <b>Date</b> to sort by ' + bStart + '</p>';
43529    	
43530    	var htm = '<div id="pop-help-recent-activity">' + msg1 + msg2a + msg2b + '</div>';
43531    	var header = 'Most Recent Appointment Create/Update/Delete';
43532    	GLO.Popup.Info.openSimple(htm, header);
43533    }
43534    _constructor.helpUpcomingList = function() {
43535    	var bFilter = '<b class="narrow-text" style="font-size: larger;">Filter:</b> ', bSort = '<b class="narrow-text" style="font-size: larger;">Sort:</b> ';
43536    	var bLastUpdated = '<b class="narrow-text" style="color: deeppink;">Last Updated</b>';
43537    	var bStart = '<b class="narrow-text" style="color: deeppink;">Appointment Start Date</b>';
43538    	
43539    	var p1 = '<p style="margin-bottom: 0; line-height: 1.4;">';
43540    	var p1b = '<p style="margin-top: 0; margin-bottom: 40px; margin-left: 40px; font-size: smaller; opacity: .8;">';
43541    	
43542    	var msg1a = p1 + bFilter + 'Begin / End Date filters on the ' + bStart + '</p>';
43543    	var msg1b = p1b + 'To filter based on when ticket ' + bLastUpdated + ' use <b>Recent Activity</b> tab</p>';
43544    	
43545    	var msg2a = p1 + bSort + 'Default sort uses the ' + bStart + '</p>';
43546    	var msg2b = p1b + 'press column header <b>Update</b> to sort by last updated date</p>';
43547    	
43548    	var htm = '<div id="pop-help-recent-activity">' + msg1a + msg1b + msg2a + msg2b + '</div>';
43549    	var header = 'Appointment List';
43550    	GLO.Popup.Info.openSimple(htm, header);
43551    }
43552    _constructor.helpMyEdits = function() {
43553    	var bFilter = '<b class="narrow-text" style="font-size: larger;">Filter:</b> ', bSort = '<b class="narrow-text" style="font-size: larger;">Sort:</b> ';
43554    	var bLastUpdated = '<b class="narrow-text" style="color: deeppink;">Last Updated</b>';
43555    	var bStart = '<b class="narrow-text" style="color: deeppink;">Appointment Start Date</b>';
43556    	var p1 = '<p style="margin-bottom: 0; line-height: 1.4;">';
43557    	var p1b = '<p style="margin-top: 0; margin-bottom: 40px; margin-left: 40px; font-size: smaller; opacity: .6;">';
43558    	
43559    	var msg1a = p1 + bFilter + 'Begin / End Date filters on ' + bLastUpdated + '</p>';
43560    	//var msg1b = p1b + 'To filter based on when ticket ' + bStart + ' use <b>Recent Activity</b> tab</p>';
43561    	
43562    	var msg2a = p1 + bSort + 'Default sort is by ' + bLastUpdated + ' column</p>';
43563    	var msg2b = p1b + 'press column header <b>Date</b> to sort by ' + bStart + '</p>';
43564    	
43565    	var htm = '<div id="pop-help-recent-activity">' + msg1a + msg2a + msg2b + '</div>';
43566    	var header = 'Your Recent Edits';
43567    	GLO.Popup.Info.openSimple(htm, header);
43568    }
43569    
43570    return _constructor;
43571})();
43572
43573
43574if (GLO.Reports === undefined) { GLO.Reports = {}; }
43575
43576GLO.Reports.MessageHistory = (function() {
43577	function _cMessageHistory() { }
43578	
43579	_cMessageHistory.init = function() {
43580		var jrpt = $('#table-message-history');
43581		
43582		UI.initTableSorter(jrpt);
43583		GLO.Report.CellSummary.initReport(jrpt, false, false);
43584		//GLO.Report.initShortcutKeys();
43585		GLO.Report.initUrlAction();
43586	}
43587	
43588	function _findRow(element, tableId) {
43589		var tr = $(element).closest('tr');
43590		
43591		if (tr.length === 0) {
43592			tr = $('#' + tableId).find('td.cell-summary-selected').closest('tr');
43593			
43594			if (tr.length === 0) {
43595				tr = $('table.tablesorter').find('td.cell-summary-selected').closest('tr');
43596			}
43597		}
43598		
43599		return tr;
43600	}
43601	
43602	_cMessageHistory.openTicket = function(element) {
43603		var tr = _findRow(element, 'table-message-history');
43604		var serviceCount = UTIL.coalesceInt(tr.attr('appt_count_sr'));
43605		var productCount = UTIL.coalesceInt(tr.attr('inventory_count_sr'));
43606		var smid = tr.attr('smid');
43607		
43608		GLO.Popup.closeIfExist( $('#report-message-sent-history').closest('.glopop') );
43609		
43610		if (serviceCount > 0) {
43611			UserPortal.Edit.get(null, smid);
43612		} else {
43613			UserPortal.Price.get(smid);
43614		}
43615	}
43616	_cMessageHistory.viewTicketMessages = function(element) {
43617		var tr = _findRow(element, 'table-message-history');
43618		var jsonClient = GLO.ClientProfile.getClientFromProfile();
43619		
43620		var smid = UTIL.coalesceInt(jsonClient.smid, tr.attr('smid'));
43621		var clientId = UTIL.coalesceInt(jsonClient.id, $('#report-message-sent-history').attr('client_id'));
43622		var bkg = UTIL.coalesceInt(jsonClient.bkg, tr.attr('bkg'));
43623		
43624		GLO.Popup.closeIfExist( $('#report-message-sent-history').closest('.glopop') );
43625		GLO.Popup.closeIfExist( $('#pop-help-cell-summary').closest('.glopop') );
43626		
43627		ClientProfile.openMessagesSentById(clientId, smid, bkg);
43628	}
43629	
43630    return _cMessageHistory;
43631})();
43632
43633GLO.Reports.StaffProfile = (function() {
43634	function _conRptProfile() { }
43635	
43636	_conRptProfile.init = function() {
43637		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
43638		var hashTab = _getHash();
43639		
43640		_conRptProfile.goToTab(hashTab);
43641		_conRptProfile.initReport();
43642		
43643		_initPermissionReport2();
43644		WIZ.isWizard = false;
43645		
43646		GLO.Report.initShortcutKeys();
43647		GLO.Report.portalName = 'Staff Profiles';
43648		
43649		if (innerWidth < 800) {
43650			var td = $('#report-portal-header').find('td > span');
43651			td.eq(0).html('<b>1</b>' + SA.Resource.Profile);
43652			td.eq(1).html('<b>2</b>' + SA.Resource.Config);
43653			td.eq(2).html('<b>3</b>' + SA.Resource.Services);
43654			td.eq(3).html('<b>4</b>' + SA.Resource.Hours);
43655			td.eq(4).html('<b>5</b>' + SA.Resource.Client);
43656			td.eq(5).html('<b>6</b>' + SA.Resource.Permissions);
43657		}
43658		
43659		GLO.Report.enableFullPageCheck();
43660		_initUrlForStaffProfile(highlight);
43661		
43662		var jrptClient = $('table#staff-client-config-list');
43663		GLO.Report.CellSummary.initReport(jrptClient, false, false);
43664	}
43665	function _initUrlForStaffProfile(highlight) {
43666		if (highlight.toLowerCase() == 'staff-alerts') {
43667			var jhighlight = $('#staff-notification-list').find('.report-column-alert-email, .report-column-alert-text');
43668			UI.highlight(jhighlight, 1200, 6400, true);
43669		} else if (!UTIL.isEmpty(highlight)) {
43670			var jhighlight = $('#report-main.staff-profile-report .tablesorter:visible').find('.' + highlight);
43671			UI.highlight(jhighlight, 1200, 6400, true);
43672		}
43673	}
43674	_conRptProfile.initReport = function() {
43675		$("#quick-view .tablesorter").tablesorter({ textExtraction: UI.tableSorterOrderBy });
43676        $('.wiz-buttons, #feedback-container').remove();
43677	}
43678	
43679	_conRptProfile.initPermissionReport = function() {
43680		UI.initTableSorter( $("#quick-view #staff-service-list.tablesorter") );		//_conRptProfile.initReport();
43681		$('.wiz-buttons, #feedback-container').remove();
43682		
43683		_initPermissionReport2();
43684	}
43685	
43686	function _initPermissionReport2() {
43687		$("#quick-view #staff-permission-list.tablesorter tbody").delegate('td','mouseover mouseleave', function(e) {
43688            if (e.type == 'mouseover') {
43689                var t = $(this);
43690                //t.parent().addClass("hover-column");
43691                $("colgroup").eq(t.index()).addClass("hover-column");
43692            } else {
43693                var t = $(this);
43694                //t.parent().removeClass("hover-column");
43695                $("colgroup").eq(t.index()).removeClass("hover-column");
43696            }
43697        });
43698
43699        $("#quick-view #staff-permission-list.tablesorter").delegate('tbody', 'mouseover mouseleave', function(e) {
43700            if (e.type == 'mouseover') {
43701                $(this).find('tr:even').removeClass('EveryOtherRowQuiet');
43702            } else {
43703                $(this).find('tr:even').addClass('EveryOtherRowQuiet');
43704            }
43705        });
43706	}
43707	
43708	_conRptProfile.goToTab = function(tab) {
43709		$('#report-profile').addClass('hide');
43710		$('#report-notification').addClass('hide');
43711		$('#report-service').addClass('hide');
43712
43713		$('#report-hour').addClass('hide');
43714		$('#report-client-config').addClass('hide');
43715		$('#report-inventory-permission').addClass('hide');
43716		
43717		$('#report-staff-address').addClass('hide');
43718		
43719		_setTabBackground(tab);
43720        _setHash(tab);
43721	}
43722	
43723	function _getHash() {
43724		var hashTab = GLO.Uri.hash('tab').toLowerCase();
43725		
43726		if (hashTab === 'report-profile') {
43727			return 1;
43728		} else if (hashTab === 'report-notification') {
43729			return 2;
43730		} else if (hashTab === 'report-service') {
43731			return 3;
43732		
43733		} else if (hashTab === 'report-hour') {
43734			return 4;
43735		} else if (hashTab === 'report-client-config') {
43736			return 5;
43737		} else if (hashTab === 'report-inventory-permission') {
43738			return 6;
43739		
43740		} else if (hashTab === 'report-staff-address') {
43741			return 7;
43742		} else {
43743			return 1;
43744		}
43745	}
43746	
43747	function _setHash(tab) {
43748		var hashTab = '';
43749		
43750		if (tab == 1) {
43751			hashTab = 'report-profile';
43752			$('#report-profile').removeClass('hide');
43753		} else if (tab == 2) {
43754			hashTab = 'report-notification';
43755			$('#report-notification').removeClass('hide');
43756		} else if (tab == 3) {
43757			hashTab = 'report-service';
43758			$('#report-service').removeClass('hide');
43759		
43760		} else if (tab == 4) {
43761			hashTab = 'report-hour';
43762			$('#report-hour').removeClass('hide');
43763		} else if (tab == 5) {
43764			hashTab = 'report-client-config';
43765			$('#report-client-config').removeClass('hide');
43766		} else if (tab == 6) {
43767			hashTab = 'report-inventory-permission';
43768			$('#report-inventory-permission').removeClass('hide');
43769		
43770		} else if (tab == 7) {
43771			hashTab = 'report-staff-address';
43772			$('#report-staff-address').removeClass('hide');
43773		}
43774		
43775		document.location.hash = 'tab=' + hashTab;
43776	}
43777	
43778	function _setTabBackground(tab) {
43779		var backColor = $('.shadow-content0').css('backgroundColor');
43780        var jhead = $('#report-portal-header');
43781        var oj = jhead.find('table tr td span b');
43782        
43783        oj.each(function() {
43784            $(this).parent().parent().removeClass('report-tab').css('backgroundColor', '');
43785        });
43786
43787        oj = jhead.find('table tr td span b').eq(tab - 1).parent().parent();
43788        oj.addClass('report-tab');
43789        oj.css('backgroundColor', backColor);
43790	}
43791	
43792	return _conRptProfile;
43793})();
43794
43795
43796GLO.Report.ClientRefer = (function() {		//Used by Payment Summary + Gift Card report
43797	function _conRptRefer() { }
43798    
43799    _conRptRefer.init = function() {
43800    	var jhead = $('.report-search-header');
43801        GLO.Report.Template.initDateRange(jhead, true);
43802        
43803        if (!GLO.Report.Sales.initStaffFilter()) {
43804			GLO.Report.Template.initStaffFilter(true);
43805		}
43806        
43807        //_setDateMax(jhead, "#report-end");
43808        //$('#header-icon-container').remove();
43809        
43810        GLO.Report.setupFastClick();
43811        GLO.Report.enableFullPage(true, true);				//= this report forces display all columns (because the # of columns depends on the # of referrals used during this date range period)
43812        //GLO.Report.enableFullPageCheck();					//= no need for this because all columns always displayed on this report
43813        
43814        _loadData();
43815    }
43816    
43817    function _loadData() {
43818    	var jrpt = $('#report-main');
43819    	UI.initTableSorter( jrpt.find('table.tablesorter:visible') );
43820    	jrpt.find('thead th.column-staff').click();
43821    	GLO.Report.CellSummary.initReport(jrpt, true, true);
43822    }
43823    
43824    function _setDateMax(j, id, maxDate) {
43825    	if (!UTIL.isDate(maxDate)) {
43826    		maxDate = new Date().toSADate(true);
43827    	}
43828    	
43829    	var jdt = j.find(id);
43830    	var val = jdt.val();
43831    	
43832    	jdt.datepicker("option", "maxDate", maxDate);
43833    	jdt.val(val);
43834    }
43835    
43836	_conRptRefer.search = function() {
43837    	var jrpt = $('#report-main');
43838    	var btnSearch = jrpt.find('#btnSearch');
43839    	var jRptData = jrpt.find('.report-container');
43840        var pageTitle = 'Client Referral Report: ' + start + ' - ' + end;
43841    	
43842    	var start = jrpt.find('#report-start:visible').val();
43843    	var end = jrpt.find('#report-end:visible').val();
43844    	var sfilter = GLO.Uri.query('sfilter');
43845    	var qstring = 'start=' + UTIL.fromSADate(start, true, true) + '&end=' + UTIL.fromSADate(end, true, true) + '&sfilter=' + sfilter;
43846    	var url = GLO.Link.WebsiteDomain + 'report/refer?' + qstring;
43847    	var jd = { "ispartial": 1 };
43848		
43849		if (!GLO.Report.hasReportPassword(jd)) {
43850	    	return;
43851	    }
43852	    
43853    	GLO.UI.Form.beginProcessing(btnSearch);
43854        
43855        $.ajax({ type: "POST", url: url, "cache": false, data: jd })
43856            .success(function(data, textStatus, jqXHR) {
43857                jRptData.html(data);
43858		        _loadData();
43859		        
43860                GLO.UI.Form.resetProcessing();
43861                window.history.pushState("", pageTitle, url);
43862            })
43863            .error(function(jqXHR, textStatus, errorThrown) {
43864                GLO.UI.Form.resetProcessing();
43865                GLO.Popup.Error('Unable to lookup data at this time<br/>Please try again');
43866                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
43867            });
43868    }
43869    
43870    return _conRptRefer;
43871})();
43872
43873
43874GLO.Report.CellSummary = (function() {
43875    function _conRptCell() { }
43876    var _isLookupDates = false;
43877    /*
43878    	Supports HTML attributes: title, report, reportName, oncellopen, celltitle, rowheader
43879    */
43880    
43881    _conRptCell.initReport = function(jrpt, isLookupDates, isIncludeFooter) {
43882        _isLookupDates = UTIL.parseBool(isLookupDates);
43883        
43884        if (!jrpt.hasClass('tablesorter')) {
43885        	jrpt = jrpt.find('table.tablesorter');
43886        }
43887        
43888        jrpt.addClass('cell-summary');
43889        jrpt.on('click', 'tbody td', GLO.Report.CellSummary.openCellSummary);
43890        
43891        if (isIncludeFooter) {
43892        	jrpt.on('click', 'tfoot td', GLO.Report.CellSummary.openCellSummary);
43893        }
43894        
43895        _isLookupDates = isLookupDates;
43896        _initCells(jrpt, isIncludeFooter);
43897	}
43898	
43899	function _initCells(jtbl, isIncludeFooter) {
43900		if (isIncludeFooter) {
43901			var tds = jtbl.find('tbody td, tfoot td');
43902		} else {
43903			var tds = jtbl.find('tbody td');
43904		}
43905		
43906		for (var i=0; i < tds.length; i++) {
43907			var td = tds.eq(i);
43908			
43909			if (_hasCellSummary(td)) {
43910				td.addClass('has-cell-summary');
43911			}
43912		}
43913	}
43914	
43915	function _hasCellSummary(td) {
43916		if (!UTIL.isEmpty(td.attr('onclick')) || td.find('a[onclick]').length > 0) { return false; }
43917    	if (UTIL.parseBool(td.attr('no-cell-summary'))) { return false; }
43918    	if (UTIL.isEmpty(td.html()) && !UTIL.parseBool(td.attr('is-force-cell-summary'))) { return false; }
43919    	if (UTIL.isEmpty(td.attr('title')) && UTIL.isEmpty(td.attr('report')) && UTIL.isEmpty(td.attr('popup')) && UTIL.isEmpty(td.attr('oncellopen'))) { return false; }
43920    	
43921    	return true;
43922	}
43923	
43924	_conRptCell.openCellSummary = function() {
43925    	var td = $(this);
43926    	_openCellSummary2(td);
43927    }
43928    
43929    function _openCellSummary2(td, htmInfo) {
43930    	if (!_hasCellSummary(td) && UTIL.isEmpty(htmInfo) && UTIL.isEmpty(td.attr('popup'))) { return; }
43931    	if ($('#pop-help-cell-summary').closest('.glopop').length > 0) { return; }
43932    	
43933    	var title = UTIL.coalesce(td.find('.title').html(), td.attr('title_htm'), td.attr('title'));
43934    	var msg = _conRptCell.getCellDescription(title);
43935    	var h1 = _getCellHelpHeader(td);
43936    	var htmReports = '';
43937    	
43938    	htmReports += _cellHelpAddReport(td, 'report', 'reportName');
43939    	htmReports += _cellHelpAddReport(td, 'report2', 'reportName2');
43940    	htmReports += _cellHelpAddReport(td, 'report3', 'reportName3');
43941    	htmReports += _cellHelpAddReport(td, 'report4', 'reportName4');
43942    	htmReports += _cellHelpAddReport(td, 'report5', 'reportName5');
43943    	
43944    	htmReports += _cellHelpAddPopup(td, 'popup', 'popupName');
43945    	htmReports += _cellHelpAddPopup(td, 'popup2', 'popupName2');
43946    	htmReports += _cellHelpAddPopup(td, 'popup3', 'popupName3');
43947    	htmReports += _cellHelpAddPopup(td, 'popup4', 'popupName4');
43948    	htmReports += _cellHelpAddPopup(td, 'popup5', 'popupName5');
43949    	
43950    	if (!UTIL.isEmpty(htmReports)) {
43951    		var relatedReportsTitle = UTIL.coalesceString(td.attr('relatedReportsTitle'), SA.Resource.RelatedReports);
43952    		htmReports = '<div id="pop-help-report-list"> <h3>' + relatedReportsTitle + '</h3>' + htmReports;
43953    	}
43954    	
43955    	var htmOnOpen = '<div id="cell-on-open"></div>';
43956    	var htmMsg = '<div id="pop-cell-description">' + msg + UTIL.cleanString(htmInfo) + '</div>';
43957    	var htm = '<div id="pop-help-cell-summary">' + htmMsg + htmOnOpen + htmReports + '</div> </div>';
43958    	var jpop = SA.Help.openSimple(h1, htm, true).addClass('no-persist');
43959    	jpop.find('.msg > div').css({ "padding": 0 });
43960    	
43961    	_cellOpenHighlight(td);
43962    	_cellOpenEvent(jpop, td);
43963    }
43964    
43965    function _cellOpenHighlight(td) {
43966    	var jtbl = td.closest('table.cell-summary');
43967    	
43968    	jtbl.find('td.cell-summary-selected-prev').removeClass('cell-summary-selected-prev');
43969    	jtbl.find('td.cell-summary-selected').removeClass('cell-summary-selected').addClass('cell-summary-selected-prev');
43970    	
43971    	td.addClass('cell-summary-selected');
43972    }
43973    
43974    function _cellOpenEvent(jpop, td) {
43975    	var fnstring = td.attr('oncellopen');
43976    	
43977    	if (fnstring) {
43978    		var fn = _getFunctionFromString(fnstring);
43979    		
43980    		if (typeof fn === 'function') {
43981    			fn.call(td);
43982    		}
43983    	}
43984    }
43985    
43986    _conRptCell.getCellDescription = function(title) {
43987    	var msg = '', arr = UTIL.cleanString(title).split('|');
43988    	
43989    	for (var i=0; i < arr.length; i++) {
43990    		if (!UTIL.isEmpty(arr[i])) {
43991    			msg += '<p>' + _pluralToSingular(arr[i]) + '</p>';
43992    		} else {
43993    			msg += '<br/>';
43994    		}
43995    	}
43996    	
43997    	return msg;
43998    }
43999    function _specialMessage(arr, tag) {
44000    	for (var i=1; i < arr.length-1; i++) {
44001    		
44002    	}
44003    }
44004    
44005    function _pluralToSingular(text) {
44006    	if (UTIL.isEmpty(text)) { return ''; }
44007    	
44008    	text = UTIL.replaceAll(UTIL.replaceAll(String(text),' 1 clients', ' 1 client'),'(1 clients', '(1 client');
44009    	text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 visits', ' 1 visit'),'(1 visits', '(1 visit');
44010    	
44011    	text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 services', ' 1 service'),'(1 services', '(1 service');
44012    	text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 tickets', ' 1 ticket'),'(1 tickets', '(1 ticket');
44013    	
44014    	text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 tips', ' 1 tip'),'(1 tips', '(1 tip');
44015    	text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 products', ' 1 product'),'(1 products', '(1 product');
44016    	text = UTIL.replaceAll(UTIL.replaceAll(text,' 1 discounts', ' 1 discount'),'(1 discounts', '(1 discount');
44017    	
44018    	text = UTIL.replaceAll(text, '{', '<small>');
44019    	text = UTIL.replaceAll(text, '}', '</small>');
44020    	
44021    	text = UTIL.replaceAll(text, '(', '<small>(');
44022    	text = UTIL.replaceAll(text, ')', ')</small>');
44023    	text = UTIL.replaceAll(text, '->', '<b class="arrow-right">&#10140;</b>');
44024    	
44025    	if (text.length > 2) {
44026    		if (text.substring(0,3) == '***') {
44027    			text = '<span class="highlight-cell-row">' + text.substring(3) + '</span>';
44028    		} else if (text.substring(0,2) == '??') {
44029    			text = '<b class="highlight-cell-row">' + text.substring(3) + '</b>';
44030    		} else if (text.substring(0,2) == '!!') {
44031    			text = '<span class="highlight-cell-row-good">' + text.substring(1) + '</span>';
44032    		} else if (text.substring(0,2) == '* ' || text.substring(0,3) == ' * ') {
44033    			text = '<ul class="highlight-cell-row-list"><li>' + text.substring(2) + '</li></ul>';
44034    		}
44035    	}
44036    	
44037    	return text;
44038    }
44039    
44040    function _cellHelpAddReport(td, reportUrl, reportName) {
44041    	reportUrl = td.attr(reportUrl);
44042    	reportName = UTIL.coalesce(td.attr(reportName), 'Report');
44043    	
44044    	if (!UTIL.isEmpty(reportUrl)) {
44045    		reportUrl = _conRptCell.getReport(reportUrl, td);
44046    		return '<span class="btnAdd cell-help-report-link"> <a onclick="GLO.Report.CellSummary.gotoReport(\'' + reportUrl + '\', this, event)">' + reportName + '</a></span>';
44047    	} else {
44048    		return '';
44049    	}
44050    }
44051    
44052    function _cellHelpAddPopup(td, popupFunction, popupName) {
44053    	popupFunction = td.attr(popupFunction);
44054    	popupName = UTIL.coalesce(td.attr(popupName), 'View');
44055    	
44056    	if (!UTIL.isEmpty(popupFunction)) {
44057    		//popupFunction = _getFunctionFromString(popupFunction);
44058    		var onclick = ' onclick="' + popupFunction + '(this, event)"';
44059    		var btnAttributes = _parseAttributes(td[0]);
44060    		
44061    		return '<span class="btnAdd cell-help-report-link"> <a' + onclick + btnAttributes + '>' + popupName + '</a></span>';
44062    	} else {
44063    		return '';
44064    	}
44065    }
44066    
44067    function _parseAttributes(htmElement) {
44068    	var attributes = '';
44069    	
44070    	$.each(htmElement.attributes, function(i, attrib) {
44071		     var name = attrib.name, value = attrib.value;
44072		     
44073		     if (name !== 'class' && name !== 'title' && name !== 'oncellopen' && name !== 'celltitle' && name !== 'rowheader' && !UTIL.startsWith(name, 'report') && !UTIL.startsWith(name, 'popup')) {
44074		     	attributes += ' ' + name + '="' + value + '"';
44075		     }
44076		});
44077		
44078		return attributes;
44079    }
44080    
44081    function _elementAttributesToJson(elem) {
44082	    for (var i = 0; i < elem.attributes.length; i++) {
44083		    var attrib = elem.attributes[i];
44084		    
44085		    if (attrib.specified) {
44086		        console.log(attrib.name + " = " + attrib.value);
44087		    }
44088		}
44089	}
44090    
44091    function _getCellHelpHeader(td) {
44092    	var tr = td.closest('tr');
44093    	var summaryTitle = UTIL.cleanString(td.attr('summarytitle'));
44094    	
44095    	if (!UTIL.isEmpty(summaryTitle)) {
44096    		return '<b>' + summaryTitle + '</b>';
44097    	}
44098    	
44099    	var headerText = UTIL.cleanString(td.attr('celltitle'));
44100    	var span1 = '<span style="white-space: nowrap; font-size: 150%; color: white;">', span2 = '</span>';
44101    	var cellIndex = td.parent().children().index(td);
44102    	
44103    	var th = td.closest('table').find('thead > tr:last').find('th').eq(cellIndex).clone();
44104    	th.find('.question-icon').remove();
44105    	th.find('.table-header-press-help').remove();
44106    	
44107    	var columnName = th.text();
44108    	var columnNameHtm = span1 + columnName + span2;
44109    	var jRowHeader = tr.find('.row-header');
44110    	
44111    	if (UTIL.isEmpty(headerText)) {
44112	    	headerText = UTIL.cleanString(tr.attr('rowheader'));
44113	    	
44114	    	for (var i=0; i < jRowHeader.length; i++) {
44115	    		if (i > 0) {
44116	    			//if (jRowHeader.length == 2) { headerText += ':'; }
44117	    			headerText += ' ';
44118	    		}
44119	    		
44120	    		headerText += jRowHeader.eq(i).text();
44121	    	}
44122	    	
44123	    	headerText = headerText.replace('$-', '-$');
44124    	}
44125    	
44126    	if (UTIL.isEmpty(headerText)) {
44127    		headerText = UTIL.directTagOnly(tr.find('td:first > a'));
44128    		
44129    		if (UTIL.isEmpty(headerText)) { headerText = UTIL.directTagOnly(tr.find('td:first')); }
44130    		if (UTIL.isEmpty(headerText)) { headerText = tr.find('td:first').text(); }
44131    	}
44132    	
44133    	if (UTIL.isEmpty(headerText) && tr.parent().prop("tagName") === 'TFOOT' && columnName != 'Total') {
44134    		var colIndex = td.parent().children().index(td);
44135    		headerText = 'Total';
44136    	}
44137    	
44138    	if (!UTIL.isEmpty(headerText)) {
44139    		headerText = span1 + headerText + span2 + '<b style="font-size: 150%;">&bull;</b> ';
44140    	}
44141    	
44142    	return '<b style="color: white;">' + headerText + columnNameHtm + '</b>';
44143    }
44144    
44145    _conRptCell.getReport = function(url, jelement) {
44146    	var dates = '', qs = '?', hash = '#', queryStart = url.indexOf('?'), hashStart = url.indexOf('#');
44147    	var isCal = (url.toLowerCase().indexOf('provider/calendar') !== -1), isActivityView = (url.toLowerCase().indexOf('provider/apptportal') !== -1);
44148    	var sfilter = _reportUrlStaff(jelement, url);
44149    	
44150    	if (_isLookupDates) {
44151    		dates = _reportUrlDates(url);
44152    	}
44153    	
44154    	if (hashStart !== -1) {
44155    		hash = url.substring(hashStart);
44156    		url = url.substring(0, hashStart);
44157    	}
44158    	
44159    	if (queryStart !== -1) {
44160    		qs = url.substring(queryStart);
44161    		url = url.substring(0, queryStart);
44162    	}
44163    	
44164    	if (isCal) {
44165    		qs += sfilter;
44166    	} else if (isActivityView) {
44167    		qs += sfilter;
44168    		hash += dates;
44169    	} else {
44170    		qs += sfilter + dates;
44171    	}
44172    	
44173    	return _getReport2(url, qs, hash);
44174    }
44175    
44176    function _reportUrlDates(url) {
44177    	if (url && url.indexOf && url.indexOf('start=') !== -1) {
44178    		return '';
44179    	}
44180    	
44181    	var output = '', jfilter = $('#report-main .report-search-header');
44182    	var start = UTIL.fromSADate(jfilter.find('#report-start').val(), true, true);
44183    	var end = UTIL.fromSADate(jfilter.find('#report-end').val(), true, true);
44184    	
44185    	if (UTIL.isDate(start)) {
44186    		output += '&start=' + start;
44187    	}
44188    	
44189    	if (UTIL.isDate(end)) {
44190    		 output += '&end=' + end;
44191    	}
44192    	
44193    	return output;
44194    }
44195    
44196    function _reportUrlStaff(jelement, url) {
44197    	if (url && url.indexOf && url.indexOf('sfilter=') !== -1) {
44198    		return '';
44199    	}
44200    	
44201    	if (jelement) {
44202    		var sfilter = jelement.closest('tr').attr('staff_id');
44203    	} else {
44204    		var sfilter = GLO.Uri.query('sfilter');
44205    	}
44206    	
44207    	if (!UTIL.isEmpty(sfilter)) {
44208    		return '&sfilter=' + sfilter;
44209    	} else {
44210    		return '';
44211    	}
44212    }
44213    
44214    function _getReport2(path, query, hash) {
44215    	query = query.replace('?&', '?');
44216    	
44217    	if (query && query.length > 1) { path += query; }
44218    	if (hash && hash.length > 1) { path += hash; }
44219    	
44220    	return path;
44221    }
44222    
44223    _conRptCell.gotoReport = function(url, btn, event) {
44224    	if (SA.Menu.isRequirePIN(url, btn, event)) {
44225    		return false;
44226    	}
44227    	
44228    	var test = url.toLowerCase();
44229    	
44230    	if (test.indexOf('/') !== 0 && test.indexOf('http') == -1 && test.indexOf('www.') === -1) {
44231    		url = '/' + url;
44232    	}
44233    	
44234    	if (btn) {
44235    		GLO.UI.Form.beginProcessing(btn);
44236    	}
44237    	
44238    	if (event && event.ctrlKey) {
44239    		var url = document.location.protocol + '//' + document.location.host + url;
44240    		var childWindow = UI.openChildWindow(url, '', true);
44241    		
44242    		setTimeout(function() {
44243    			GLO.UI.Form.resetProcessing(btn);
44244    		}, 2100);
44245    	} else {
44246    		setTimeout(function() {
44247    			document.location = url;
44248    		}, 100);
44249    	}
44250    }
44251    
44252    function _getFunctionFromString(string) {
44253	    var scope = window;
44254	    var scopeSplit = string.split('.');
44255	    
44256	    for (i = 0; i < scopeSplit.length - 1; i++) {
44257	        scope = scope[scopeSplit[i]];
44258	        if (scope == undefined) return;
44259	    }
44260		
44261	    return scope[scopeSplit[scopeSplit.length - 1]];
44262	}
44263    
44264    _conRptCell.viewProductSummary = function() {
44265    	var iid = (this).closest('tr').attr('inventory_id');
44266    	var uri = GLO.Link.Page.Provider.Home + 'Inventory/ItemSummary?id=' + iid;
44267    	
44268    	var throbber = GLO.Report.Template2.getBlueThrobber();
44269    	var jpop = $('#pop-help-cell-summary').closest('.glopop');
44270    	var jthrobber = jpop.find('#cell-on-open').html(throbber);
44271    	
44272    	var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false })
44273            .success(function(data, textStatus, jqXHR) {
44274                var tbl = $(data).find('table');
44275                jthrobber.replaceWith(tbl);
44276            })
44277            .error(function(jqXHR, textStatus, errorThrown) {
44278            	jthrobber.remove();
44279            });
44280    }
44281    
44282    _conRptCell.viewStaffServices = function(element, event) {			//= inline popup
44283    	var jbtn = $(element);
44284    	var sid = jbtn.attr('staff_id');
44285    	
44286    	if (!UTIL.isEmpty(sid)) {
44287    		Wiz5.openStaffQuickView(sid, event);
44288    	}
44289    	
44290    	_conRptCell.processingOpenPopup(jbtn);
44291    }
44292    
44293    _conRptCell.viewProductSummary = function(element, event) {			//= inline popup
44294    	var jbtn = $(element);
44295    	var iid = jbtn.attr('inventory_id'), gcid = jbtn.attr('gift_card_id');
44296    	
44297    	if (!UTIL.isEmpty(gcid)) {
44298    		var gcnr = UTIL.cleanString(jbtn.attr('gift_number_vc')), gcmn = UTIL.cleanString(jbtn.attr('gift_balance_mn'));
44299    		UserPortal.Price.GiftCard.openEdit(gcid, gcnr, gcmn);
44300    	} else if (!UTIL.isEmpty(iid)) {
44301    		GLO.Inventory.Item.openViewPopup(iid);
44302    	}
44303    	
44304    	_conRptCell.processingOpenPopup(jbtn);
44305    }
44306    
44307    _conRptCell.processingOpenPopup = function(jbtn) {
44308    	var jpop = jbtn.closest('.glopop');
44309		
44310		GLO.UI.Form.beginProcessing(jbtn);
44311		
44312		setTimeout(function() {
44313			GLO.Popup.close(jpop);
44314		}, 800);
44315    }
44316    
44317    
44318    _conRptCell.ClientList = (function() {
44319    	function _conRptCell_CL() {}
44320    	
44321    	_conRptCell_CL.init = function() {
44322    		var jtbl = $('#be-client-list').addClass('cell-summary');
44323	        
44324	        jtbl.on('click', 'tbody td', GLO.Report.CellSummary.ClientList.openCellSummary);
44325	        
44326	        _initCells(jtbl, false);
44327    	}
44328    	
44329    	_conRptCell_CL.openCellSummary = function() {
44330	    	var td = $(this);
44331	    	var htm = _getInfo(td);
44332	    	
44333	    	_openCellSummary2(td, htm);
44334	    }
44335	    
44336	    function _getInfo(td) {
44337	    	var htm = '';
44338	    	
44339	    	if (td.hasClass('be-phone')) {
44340	    		htm += _getPhoneColumn(td);
44341	    	} else if (td.hasClass('be-email')) {
44342	    		htm += _getEmailColumn(td);
44343	    	} else if (td.hasClass('last-visit')) {
44344	    		htm += _getVisitColumn(td, false);
44345	    	} else if (td.hasClass('next-visit')) {
44346	    		htm += _getVisitColumn(td, true);
44347	    	} else if (td.hasClass('visit-count')) {
44348	    		htm += _getVisitCountColumn(td);
44349	    	} else if (td.hasClass('product-count')) {
44350	    		htm += _getProductHistory(td);
44351	    	} else if (td.hasClass('product-first')) {
44352	    		htm += _getProductHistory(td);
44353	    	} else if (td.hasClass('product-last')) {
44354	    		htm += _getProductHistory(td);
44355	    	}
44356	    	
44357	    	return htm;
44358	    }
44359    	
44360    	function _getProductHistory(td) {
44361    		var htm = '';
44362    		
44363    		if (!UTIL.isEmpty(td.text())) {
44364    			var tr = td.closest('tr');
44365    			var htmFirst = '', htmLast = '', isMobile = GLO.Info.isMobile();
44366    			
44367    			var dtFirst = tr.find('.product-first').attr('dt'), dtLast = tr.find('.product-last').attr('dt');
44368				var tdCount = tr.find('.product-count');
44369				
44370				if (UTIL.isDate(dtFirst)) {
44371					var dtPretty = new Date(dtFirst).toGloDateString(true, true, isMobile, isMobile) + ' @ ' + new Date(dtFirst).toGloTime();
44372					htmFirst = '<div class="first-product"><b style="font-size: smaller;">First Product Purchase:</b> ' + dtPretty + '</div>';
44373				}
44374				
44375				if (UTIL.isDate(dtLast)) {
44376					var dtPretty = new Date(dtLast).toGloDateString(true, true, isMobile, isMobile) + ' @ ' + new Date(dtLast).toGloTime();
44377					htmLast = '<div class="first-product"><b style="font-size: smaller;">Last Product Purchase:</b> ' + dtPretty + '</div>';
44378				}
44379				
44380				htm += _getProductCountColumn(tdCount);
44381				htm += htmFirst + htmLast;
44382    		}
44383    		
44384    		return htm;
44385    	}
44386    	
44387    	function _getProductCountColumn(td) {
44388    		var msg = '', cntTotal = UTIL.coalesceInt(td.text(), 0);
44389    		var isMobile = GLO.Info.isMobile();
44390    		
44391    		var tr = td.closest('tr');
44392    		var cnt = UTIL.coalesceInt(tr.attr('products_in_range_sr'), 0);
44393    		
44394    		var jfilter = $('#be-filter-client-area');
44395    		var start = UTIL.fromSADate(jfilter.find('#filter-start').val()), end = UTIL.fromSADate(jfilter.find('#filter-end').val());
44396    		var jbrand = jfilter.find('#filter-brand > option:selected');
44397    		var jcategory = jfilter.find('#filter-category > option:selected');
44398    		
44399    		var plural = 's', brand = '', categoryValue = jcategory.val(), categoryText = $.trim(jcategory.text());
44400    		
44401    		if (cnt == 1) { plural = ''; }
44402    		if (!UTIL.isEmpty(jbrand.val())) { brand = ' ' + $.trim(jbrand.text()); }
44403    		
44404    		if (!UTIL.isEmpty(categoryValue)) {
44405    			if (parseInt(categoryValue) < 0) {
44406    				if (categoryValue == -1) {
44407    					categoryText = '';
44408    					msg = cnt + brand + ' product' + plural;
44409    				} else {
44410    					categoryText = ' when at least ' + Math.abs(categoryValue) + ' products purchased';
44411    					msg = cnt + brand + ' product' + plural + ' purchased' + categoryText;
44412    				}
44413    			} else {
44414    				categoryText = ' ' + categoryText;
44415    				msg = cnt + brand + categoryText + ' product' + plural;
44416    			}
44417    		} else {
44418    			categoryText = '';
44419    			msg = cnt + brand + ' product' + plural;
44420    		}
44421    		
44422    		if (UTIL.isDate(start) && UTIL.isDate(end)) {
44423    			msg += ' between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true);
44424    		} else if (UTIL.isDate(start)) {
44425    			msg += ' after ' + new Date(start).toGloDateString(true, true, isMobile, isMobile);
44426    		} else if (UTIL.isDate(end)) {
44427    			msg += ' before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile);
44428    		}
44429    		
44430    		if (cntTotal > cnt) {
44431    			if (cntTotal == 1) { plural = ''; } else { plural = 's'; }
44432    			var msgOverall = '<div style="margin-bottom: 8px; text-align: center;">Overall ' + cntTotal + brand + categoryText + ' product' + plural + ' sold</div>';
44433    		} else {
44434    			var msgOverall = '';
44435    		}
44436    		
44437    		msg = msgOverall + '<div class="product-message">' + msg + '</div>';
44438    		
44439    		var cid = tr.attr('client_id'), cname = tr.find('.be-client-name').find('>a').text();
44440			var fnString = 'ClientProfile.openProductHistoryByClient(this, ' + cid + ', \'' + UTIL.htmlEncode3(cname) + '\')';
44441			var viewLink = '<div class="view-product-history"><span class="btnAdd"><a onclick="' + fnString + '">View Product History</a></span></div>';
44442			
44443			return msg + viewLink
44444    	}
44445    	
44446    	function _getVisitCountColumn(td, isIgnoreVisitColumn) {
44447    		var cnt = UTIL.coalesceInt(td.text(), 0);
44448    		var tr = td.closest('tr');
44449    		
44450    		var jfilter = $('#be-filter-client-area');
44451    		var start = UTIL.fromSADate(jfilter.find('#filter-start').val()), end = UTIL.fromSADate(jfilter.find('#filter-end').val());
44452    		
44453    		var htm = _getVisitInfo(jfilter, tr, cnt, start, end);
44454    		
44455    		if (!isIgnoreVisitColumn) {
44456	    		var jlast = tr.find('.last-visit'), jnext = tr.find('.next-visit');
44457	    		htm += _getVisitColumn(jlast, false, true);
44458	    		htm += _getVisitColumn(jnext, true, true);
44459    		}
44460    		
44461    		htm += _getApptHistoryLink(tr, start, end);
44462    		
44463    		if (parseInt(tr.find('.product-count').text()) > 0) {
44464    			htm += '<hr/>' + _getProductHistory(td);
44465    		}
44466    		
44467    		htm += _getUnsubscribe(td, true, true);
44468    		htm += _getNotes(tr);
44469    		
44470    		return htm;
44471    	}
44472    	
44473    	function _getVisitInfo(jfilter, tr, bkgCount, start, end) {
44474    		var isMobile = GLO.Info.isMobile();
44475    		var jsvc = jfilter.find('#filter-service > option:selected');
44476    		var serviceMessage = '', signInOnlyMsg = '', serviceValue = jsvc.val(), serviceText = $.trim(jsvc.text());
44477    		var cnt = UTIL.coalesceInt(tr.attr('services_in_range_sr'), 0);
44478    		var siginOnlyCount = UTIL.coalesceInt(tr.attr('signin_only_count_sr'), 0);
44479    		
44480    		if (siginOnlyCount > 0) {
44481    			var ticketCount = UTIL.coalesceInt(tr.attr('past_appt_count_sr'), 0) + UTIL.coalesceInt(tr.attr('upcoming_appt_count_sr'), 0);
44482    			var signInExplainer = '<span class="narrow-text">(client signed-in, but no associated ticket)</span>';
44483    			
44484    			signInOnlyMsg = '<div class="signin-only-message">' + siginOnlyCount + ' sign-in only ' + signInExplainer + ' + ' + UTIL.pluralLabel(ticketCount, 'ticket') + '</div>';
44485    		}
44486    		
44487    		if (!UTIL.isEmpty(serviceValue)) {
44488    			if (parseInt(serviceValue) < 0) {
44489    				serviceMessage = UTIL.pluralLabel(cnt, 'service');				//serviceMessage = UTIL.pluralLabel(cnt, 'service') + ' with ' + serviceText;
44490    			} else {
44491    				serviceMessage = UTIL.pluralLabel(cnt, serviceText + ' service');
44492    			}
44493    		} else {
44494    			serviceMessage = UTIL.pluralLabel(cnt, 'service');
44495    		}
44496    		
44497    		if (UTIL.isDate(start) && UTIL.isSameDay(start, end)) {
44498    			serviceMessage += ' on ' + new Date(start).toGloDateString(true, true, true, true);
44499    		} else if (UTIL.isDate(start) && UTIL.isDate(end)) {
44500    			serviceMessage += ' between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true);
44501    		} else if (UTIL.isDate(start)) {
44502    			serviceMessage += ' after ' + new Date(start).toGloDateString(true, true, isMobile, isMobile);
44503    		} else if (UTIL.isDate(end)) {
44504    			serviceMessage += ' before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile);
44505    		}
44506    		
44507    		var msgFilter = '<div class="service-overall"> <b>' + UTIL.pluralLabel(bkgCount, 'visit') + '</b> <span class="narrow-text">(matching the client filter above)</span> </div>';
44508    		var overAll = _getAllTicketInfo(tr, bkgCount, cnt);
44509    		
44510    		return msgFilter + '<div class="service-message">' + serviceMessage + '</div>' + signInOnlyMsg + overAll;
44511    	}
44512    	
44513    	function _getAllTicketInfo(tr, bkgCount, inDateRangeCount) {
44514    		//if (bkgCount == inDateRangeCount) { return ''; }
44515    		
44516    		var pOnly = UTIL.coalesceInt(tr.attr('product_only_visit_count_sr'), 0);
44517    		var past = UTIL.coalesceInt(tr.attr('past_appt_count_sr'), 0);
44518    		var upcoming = UTIL.coalesceInt(tr.attr('upcoming_appt_count_sr'), 0);
44519    		
44520    		if (upcoming > 0 || past > 0) {
44521    			return '<div class="service-overall">' + UTIL.pluralLabel(past, 'ticket') + ' in the past, ' + UTIL.pluralLabel(upcoming, 'upcoming ticket') + '</div>';
44522    		}
44523    		
44524    		return '';
44525    	}
44526    	
44527    	function _getApptHistoryLink(tr, start, end) {
44528    		var startParam = null, endParam = null;
44529    		var cid = tr.attr('client_id'), cname = tr.find('.be-client-name').find('>a').text();
44530			
44531			if (UTIL.isDate(start)) {
44532				startParam = '\'' + new Date(start).toGloDate() + '\'';
44533			}
44534			
44535			if (UTIL.isDate(end)) {
44536				endParam = '\'' + new Date(end).toGloDate() + '\'';
44537			}
44538			
44539			var fnString = 'ClientProfile.openApptHistoryByClient(this, ' + cid + ', null, ' + startParam + ', ' + endParam + ')';
44540			
44541			return '<div class="view-product-history"><span class="btnAdd"><a onclick="' + fnString + '">View Appointment History</a></span></div>';
44542    	}
44543    	
44544    	function _getVisitColumn(td, isNext, isIgnoreCount) {
44545    		var htm = '', dt = td.attr('dt');
44546    		var tr = td.closest('tr');
44547    		var apptCount = UTIL.coalesceInt(tr.attr('past_appt_count_sr'), 0) + UTIL.coalesceInt(tr.attr('upcoming_appt_count_sr'), 0);
44548    		var siginOnlyCount = UTIL.coalesceInt(tr.attr('signin_only_count_sr'), 0);
44549    		
44550    		if (UTIL.isDate(dt)) {
44551    			var label = 'Last Visit', dt = new Date(dt), isMobile = GLO.Info.isMobile();
44552    			var dtService = td.attr('service_dt');		//only populated when 'dt' != service (so 'dt' is class or product purchase)
44553    			var visitLink = '', htmPre = '', cid = td.closest('tr').attr('client_id');
44554    			
44555    			if (isNext) {
44556    				label = 'Next Visit';
44557    				var pre = td.find('.is-prebooked').attr('title');
44558    				
44559    				if (!UTIL.isEmpty(pre)) {
44560    					htmPre = '<div class="next-visit-pre-booked">' + pre + '</div>';
44561    				}
44562    			}
44563    			
44564    			if (apptCount > 1 && !UTIL.isDate(dtService)) {
44565    				var visitLink = '<span class="btnAdd visit-link"><a onclick="GLO.Report.CellSummary.ClientList.viewAppt(this, ' + cid + ',\'' + dt.toGloDate(true) + '\')">View on Calendar</a></span>';
44566    			}
44567    			
44568    			var dtPretty = dt.toGloDateString(true, true, isMobile, isMobile) + ' @ ' + dt.toGloTime();
44569    			var htmLastVisit = '<b style="font-size: smaller;">' + label + ':</b> <span class="visit-date">' + dtPretty + '</span> ';
44570    			htm += '<div class="last-visit">' + htmLastVisit + visitLink + '</div>' + htmPre;
44571    			
44572    			if (!isIgnoreCount) {
44573    				var tdVisitCount = td.closest('tr').find('.visit-count');
44574    				htm += _getVisitCountColumn(tdVisitCount, true);
44575    			}
44576    		}
44577    		
44578    		return htm;
44579    	}
44580    	
44581    	function _getEmailColumn(td) {
44582    		var htm = '', emailShort = td.text();
44583    		var emailFull = UTIL.coalesce(td.attr('title'), emailShort);
44584    		
44585    		if (UTIL.Validate.email(emailFull)) {
44586	    		var emailLink = '<a href="mailto:' + emailFull + '"> <b style="font-size: 85%;">Email Now:</b> ' + emailFull + '</a>';
44587	    		htm += '<div class="email-link">' + emailLink + '</div>';
44588	    	}
44589	    	
44590	    	htm += _getUnsubscribe(td, true, false);
44591	    	return htm;
44592    	}
44593    	
44594    	function _getPhoneColumn(td) {
44595    		var htm = '', phone = td.text(), tr = td.closest('tr');
44596    		
44597    		if (!(GLO.Info.isIosApp && GLO.Info.isAndroid) && phone.length === 12) {
44598	    		var phoneLink = '<a href="tel:' + phone + '" style="letter-spacing: 1px; font-size: 16px;"> <b style="font-size: 85%;">Call Now:</b> ' + UTIL.formatPhone(phone) + '</a>';
44599	    		htm += '<div class="phone-link">' + phoneLink + '</div>';
44600	    	}
44601	    	
44602	    	htm += _getUnsubscribe(td, false, true);
44603	    	htm += _getNotes(tr);
44604	    	return htm;
44605    	}
44606    	
44607    	function _getNotes(tr) {
44608    		var htm = '', jicons = tr.find('.be-icons');
44609    		var staffNote = UTIL.cleanString(jicons.find('.be-staff-note > img').attr('title'));
44610			var forbidNote = UTIL.cleanString(jicons.find('.be-forbid > img').attr('title'));
44611			
44612			if (!UTIL.isEmpty(staffNote)) { htm += '<div class="staff-only-note"><b style="font-size: smaller;">Staff Only Note:</b> ' + staffNote + '</div>'; }
44613			if (!UTIL.isEmpty(forbidNote)) { htm += '<div class="forbid-note">' + forbidNote + '</div>'; }
44614			
44615			return htm;
44616    	}
44617    	
44618    	function _getUnsubscribe(td, isEmail, isText) {
44619    		var htm = '', jicons = td.closest('tr').find('.be-icons');
44620    		
44621    		if (isEmail) {
44622	    		var unsubscribeEmail = UTIL.cleanString(jicons.find('.be-unsubscribe-email').attr('title'));
44623		    	
44624		    	if (!UTIL.isEmpty(unsubscribeEmail)) {
44625		    		htm += '<div class="unsubscribe" style="color: orange;">' + unsubscribeEmail + '</div>';
44626		    	}
44627	    	}
44628	    	
44629	    	if (isText) {
44630	    		var unsubscribeText = UTIL.cleanString(jicons.find('.be-unsubscribe-text').attr('title'));
44631	    		
44632		    	if (!UTIL.isEmpty(unsubscribeText)) {
44633		    		htm += '<div class="unsubscribe">' + unsubscribeText + '</div>';
44634		    	}
44635	    	}
44636	    	
44637	    	return htm;
44638    	}
44639    	
44640    	_conRptCell_CL.viewAppt = function(btn, clientid, dt) {
44641    		var visitUri = 'provider/calendar#dt=' + dt + '&clientid=' + clientid;
44642    		
44643    		_conRptCell.gotoReport(visitUri, btn);
44644    	}
44645    	
44646    	return _conRptCell_CL;
44647    })();
44648    
44649    
44650    return _conRptCell;
44651})();
44652
44653
44654GLO.Message = (function() {
44655	function _conMsg() { }
44656	
44657	_conMsg.view = function(messageId, processingMessage) {
44658		var url = GLO.Link.WebsiteDomain + 'message/' + messageId + '?ispartial=1';
44659        
44660        if (processingMessage) {
44661        	var ojprocessing = GLO.Popup.Processing.open(processingMessage, 'Opening Message...');
44662        }
44663        
44664        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
44665            .success(function(data, textStatus, jqXHR) {
44666                if (ojprocessing) {
44667                	ojprocessing.close();
44668                }
44669                
44670                var jhtm = $(data);
44671                GLO.Mobile.formatExternalLinksForIos(jhtm);
44672                jhtm.modal();
44673                var jmodal = $('#simplemodal-container').addClass('view-message');
44674                
44675                if (!GLO.Info.isMobile()) {
44676                	var handle = '#msg-header';
44677                	jmodal.draggable({ "handle": handle }).find(handle).css({ "cursor": "move" });
44678		        }
44679		        
44680		        var width = jmodal.width() + 25;
44681		        jmodal.css({ "padding": 0 });
44682		        jmodal.find('.simplemodal-data').css({ "padding": 0 });
44683		        jmodal.find('#msg-header').css({ "font-size": "100%", "border-top-left-radius": "6px" });
44684		        jmodal.find('#msg-subject').css({ "margin-bottom": "8px" });
44685		        jmodal.find('.simplemodal-wrap').addClass('scrollable-for-mac').css({ "overflow": "auto" });	//jmodal.find('.simplemodal-wrap').css({ "overflow": "auto", "width": width });
44686		        
44687		        $.modal.update(null, width);
44688		        
44689		        setTimeout(function() {
44690		        	var jmodal = $('#simplemodal-container');
44691		        	var height = jmodal.find('.simplemodal-data').outerHeight();
44692		        	var newHeight = null;
44693		        	
44694		        	if (height < innerHeight && height > jmodal.height()) {
44695		        		newHeight = height;
44696		        	} else {
44697		        		newHeight = innerHeight * .8;
44698		        	}
44699		        	
44700		        	if (newHeight > 300) {
44701		        		jmodal.css({ "max-height": newHeight + 'px' });
44702		        		$.modal.update(newHeight, null);
44703		        	}
44704		        	
44705		        	width = parseInt(innerWidth - 40);
44706		        	
44707		        	if (width < 310) {
44708		        		width = 310;
44709		        	}
44710		        	
44711		        	if (jmodal.outerWidth() > width) {
44712		        		$.modal.update(newHeight, width);
44713		        	}
44714		        	
44715		        	//$(window).trigger('resize.simplemodal');
44716		        }, 200);
44717            })
44718            .error(function(jqXHR, textStatus, errorThrown) { });
44719	}
44720	
44721	_conMsg.viewCellSummary = function(element, event) {
44722		var jbtn = $(element);
44723		var msgid = jbtn.attr('message_id');
44724		
44725		_conMsg.view(msgid);
44726		GLO.Report.CellSummary.processingOpenPopup(jbtn);
44727	}
44728	
44729	return _conMsg;
44730})();
44731
44732
44733GLO.Message.Bulk = (function() {
44734	function _conBMsg() { }
44735	var _pageNumber, _pageCount, _isInitPage = true, _currentFilterAjax = null, _sortColumn = null, _sortDescending = null;
44736	var mmsImageUploadModal, mmsPreviewModal = null;
44737
44738	_conBMsg.initClientMarketingDashboard = function() {
44739		_loadMessageOverview();
44740	}
44741	
44742	function _loadMessageOverview() {
44743		var jcnt = $('#message-counts');
44744		var emailCount = UTIL.displayMoney(jcnt.attr('free_email_nr'), true, false, true);
44745		var paidCount = UTIL.coalesceInt(jcnt.attr('message_package_nr'));
44746		var textBlastCount = UTIL.coalesceInt(jcnt.attr('text_blast_nr'));
44747		
44748		if (paidCount > 0 && textBlastCount > 0) {
44749			var packageInfo = UTIL.displayMoney(paidCount, true, false, true) + ' normal paid messages';
44750			packageInfo += UTIL.displayMoney(textBlastCount, true, false, true) + ' text blast messages';
44751		} else if (paidCount > 0) {
44752			var packageInfo = UTIL.displayMoney(paidCount, true, false, true) + ' messages';
44753		} else if (textBlastCount > 0) {
44754			var packageInfo = UTIL.displayMoney(textBlastCount, true, false, true) + ' text blast messages';
44755		} else {
44756			var packageInfo = '';
44757		}
44758		
44759		var joverview = $('#marketing-overview');
44760		joverview.find('#free-email-count').text(emailCount);
44761		joverview.find('#message-package-count').text(packageInfo);
44762	}
44763	
44764	_conBMsg.initMarketingMessageHistory = function() {
44765		var jrpt = $('#message-blast-history table.tablesorter:visible');
44766		UI.initTableSorter(jrpt);
44767		GLO.Report.CellSummary.initReport(jrpt, false, true);
44768	}
44769	
44770	_conBMsg.init = function(fmtType) {
44771		GLO.Report.portalName = 'client-list';
44772		_initSaveButton();
44773		
44774		var jlanguage = $('#language-icon-container').remove();
44775		var helpIcon = '<span class="helpIcon2 sa-sprite" onclick="GLO.Message.Bulk.openHelp()"></span>';
44776		
44777		$('#bd').prepend('<h1 id="client-list-header">' + UTIL.cleanString(jlanguage.html()) + '<b>' + SA.Resource.ClientList + helpIcon + '</b></h1>');
44778		
44779		_initSavedFilter();
44780		_initClientFilter();
44781		_initClientFilterNarrowScreen();
44782		_initClientFilterData();
44783		
44784		_initMessageArea(fmtType);
44785		
44786		var isMessage = _initExistingMessage();
44787		var jExisting = $('#bulk-email-container #bulk-sent-client-list');
44788		
44789		_initNonAdmin();
44790		_initForMobile();
44791		_isInitPage = false;
44792		
44793		if (jExisting.length > 0) {							//= is existing bulk message, not client list report (ie has bulk_id in query string).
44794			UI.initTableSorter(jExisting);
44795			
44796			if ($('#bulk-email-container.accept-text-only').length > 0) {
44797				$('#bmsg-include-client-username').addClass('hide');
44798			}
44799		}
44800		
44801		/* if (GLO.Provider.isInCanada()) {
44802			$('#be-message-body-text #Text_vc').attr('maxlength', 136);
44803		} else {
44804			$('#be-message-body-text #Text_vc').attr('maxlength', 160);
44805		} */
44806		
44807		_initAutoSearch(isMessage);
44808		GLO.Report.enableFullPageCheck();
44809	}
44810	
44811	function _initSavedFilter() {
44812		var jfilter = $('#be-filter-client-area');
44813		var query = jfilter.find('#ticket-type-filter').attr('saved_query_vc');
44814		var bulkId = $('#Message_Bulk_id').val();
44815		
44816		if (!UTIL.isEmpty(bulkId)) {
44817			if (!UTIL.isEmpty(query)) {
44818				if (query.indexOf('id=' + bulkId) === -1) {
44819					query = query + '&id=' + bulkId;			 //UTIL.coalesceString(location.search, '').replace('?', '');
44820				}
44821				
44822				GLO.Report.TicketHistory.changeUrl(query, 'Saved Client List');
44823				
44824				if (jfilter.hasClass('is-sent')) {
44825					jfilter.find('input, select').prop('disabled', true);
44826					jfilter.find('.ui-icon-circle-close').remove();
44827					jfilter.removeClass('hide');
44828				}
44829			}
44830		}
44831	}
44832	
44833	function _initAutoSearch(isMessage) {
44834		var jfilter = $('#be-filter-client-area');
44835		var isAutoSearch = jfilter.length && !jfilter.hasClass('is-sent');
44836		//var isAutoSearch = (!isMessage && $('#be-client-list').find('tbody > tr').length === 0);
44837		
44838		if (isAutoSearch) {
44839			setTimeout(function() {
44840				$('#be-filter-client-area').find('#btnFilter > a').click();
44841				//_initClientListHelp();
44842			}, 40);
44843		}
44844	}
44845	
44846	function _initClientListHelp() {
44847		var maxStep = 6, stepNumber = parseInt(GLO.Uri.url('helpstep'));
44848		
44849		//if (GLO.Info.roleType < 210) {  maxStep = 4; }
44850		
44851		/* if (!UTIL.isNumber(stepNumber) || stepNumber > maxStep) {
44852			stepNumber = UTIL.randomNumber(1, maxStep)();
44853		} */
44854		
44855		_conBMsg.openHelp(stepNumber);
44856		
44857		var btnClose = $('.pop-help-post.glopop').find('.btnClose');
44858		GLO.UI.Form.beginProcessing(btnClose);
44859	}
44860	
44861	_conBMsg.openHelp = function(stepNumber) {
44862		SA.Help.openReportHelp('#client-list-help', stepNumber, 'info/ClientListHelp');
44863	}
44864	
44865	_conBMsg.openHelpEmailDeliverability = function() {
44866		var msg1 = '<p>When email messages are sent to a large number of people, email companies sometimes start filtering messages</p>';
44867		var msg2 = '<p>To improve your messages deliverability we do several things including</p>';
44868		var newCustomers = '<p class="narrow-text">
44868New ' + GLO.Info.getScheduleAnyoneHtm() + ' customers or high risk customers might have lower limits, ' + acctReview + '</p>';
44869		var acctReview = 'if you receive a warning that you have a low limit per day or week feel free to contact us: account reviews typically increase limits to the normal settings';
44870		
44871		var li1 = '<li>Limit the number of messages that can be sent to the same email</li>';
44872		var li2 = '<li>For each message we generate a deliverability score of 0-100, the higher the score the more likely the recepient will receive the message</li>';
44873		var li3 = '<li>Work with email deliverability engines to improve successful delivery</li>';
44874		
44875		var list = '<ul>' + li1 + li2 + li3 + '</ul>';
44876		var htm = '<div id="pop-help-email-deliverability">' + msg1 + msg2 + list + '</div>';
44877		var jpop = GLO.Popup.Custom.openSimple(htm, 'Email Message Blast Deliverability Best Practices');
44878		GLO.Popup.Custom.singleButton(jpop);
44879	}
44880	_conBMsg.openHelpTextDeliverability = function() {
44881		var isApproveMore = UTIL.parseBool($('#bulk-email-container').attr('allow_more_messages_fl'));
44882		
44883		var msg1 = '<p>When text messages are sent to a large number of people, phone companies often start filtering the messages by blocking the messages completely or sending them to spam folders</p>';
44884		var msg2 = '<p>To improve your messages deliverability we do several things including</p>';
44885		
44886		if (isApproveMore) {
44887			var acctReview = '', newCustomers = '', clientLimit = '5,000';
44888		} else {
44889			var acctReview = 'if you receive a warning that you have a lower limit feel free to contact us: account reviews typically increase limits to the normal settings';
44890			var newCustomers = '<p class="narrow-text">New ' + GLO.Info.getScheduleAnyoneHtm() + ' customers or high risk customers might have lower limits, ' + acctReview + '</p>';
44891			var clientLimit = '1,000';
44892		}
44893		
44894		var optOut = '<ul style="margin-bottom: 0;"><li>This lets the phone company and clients know that clients who do not want the messages can easily opt-out</li>'
44895				+ '<li>Of course, always do everything possible to not send message to clients who do not want it</li></ul>';
44896		
44897		var li1 = '<li>Before sending the message, we give you a deliverability score to help you check if any words or phrases in your text message are red flags to phone companies</li>';
44898		var li2 = '<li>At the end of every message <b class="narrow-text" style="color: deeppink;">Reply STOP 2 opt out</b> is automatically added' + optOut + '</li>';
44899		var li3 = '<li>Limit the number of messages that can be sent to the same phone number</li>';
44900		var li4 = '<li>Limit the number of clients that can receive the same message to ' + clientLimit + ' clients' + newCustomers + '</li>';
44901		var li5 = '<li>Work with the best text message delivery companies to improve successful delivery</li>';
44902		var li6 = '<li>For each message we generate a deliverability score of 0-100, the higher the score the more likely the recepient will receive the message</li>';
44903		
44904		var list = '<ul>' + li1 + li2 + li3 + li4 + li5 + li6 + '</ul>';
44905		var htm = '<div id="pop-help-text-deliverability">' + msg1 + msg2 + list + '</div>';
44906		var jpop = GLO.Popup.Custom.openSimple(htm, 'Text Message Blast Deliverability Best Practices');
44907		GLO.Popup.Custom.singleButton(jpop);
44908	}
44909	
44910	_conBMsg.openHelpMMSPricing = function() {
44911		var isApproveMore = UTIL.parseBool($('#bulk-email-container').attr('allow_more_messages_fl'));
44912		var msg0 = '<p>MMS (Multimedia Messaging Service) is the standard protocol used to send longer text messages that may contain multimedia content like images. </p>';
44913		var msg0Note ='<div style="padding: 20px;background-color:#cce5ff;color: black; border: solid #000;border-width: 0 0 0 3px;margin-right:8px;text-align:left;">MMS messages are charged per message part, while SMS messages are charged per message. Understanding what defines an MMS part will inform your understanding of how you will be billed and will help prevent accidental overages.</div><br/>';
44914		var msg1 = '<p>MMS messages are charged per message segment. The character limit for a single MMS segment is 160 characters (GSM-7 encoding) or 70 characters (UCS-2 encoding) based on encoding type. While SMS messages can be joined together, messages longer than 160 characters are split by carriers prior to them being sent.</p>';
44915		var msg1img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/mms-parts-pic.jpg" style="min-height: 250px; width: 90%; max-width: 800px; margin-bottom: 10px;"></div>';
44916		var msg2 = '<p>The system will display the number of characters, number of segments and price just below the message box, so you can be aware of how many segments are being utilized and how it will impact your MMS blast pricing.</p>';
44917		var msg2img = '<div><img src="' + GLO.Data.cdnDirectory + 'image/help/mms-indicators.jpg" style="min-height: 220px; width: 90%; max-width: 500px; margin-bottom: 10px;"></div>';
44918		var msg3 = '<p>The character encoding of your message determines the number of characters allowed per segment:</p>';
44919		var li1Enc = '<li><b class="narrow-text">GSM-7 encoding:</b> Supports standard Latin characters and some special characters, allowing up to 160 characters per segment.</li>';
44920		var li2Enc = '<li><b class="narrow-text">UCS-2 enconding:</b> Used for messages containing non-Latin characters or certain symbols <b>like emojis</b>, limiting each segment to 70 characters.</li>';
44921		var listEnc = '<ul>' + li1Enc + li2Enc + '</ul>';
44922		
44923		var msg4 = '<p>Best Practices:</p>';
44924		var li1BestPrac = '<li><b class="narrow-text">Keep Messages Concise:</b> Aim to stay within 1-2 MMS parts to optimize costs and delivery efficie
44924ncy.</li>';
44925		var li2BestPrac = '<li><b class="narrow-text">Be Mindful of Encoding:</b> Be mindful of using special characters or emojis since they will trigger UCS-2 encoding and result in higher cost.</li>';
44926		var li3BestPrac = '<li><b class="narrow-text">Utilize MMS Effectively:</b> Use Images with MMS but ensure file sizes are within supported limits (less than 1MB) to prevent delivery issues.</li>';
44927		var listBestPrac = '<ul>' + li1BestPrac + li2BestPrac + li3BestPrac  + '</ul>';
44928		
44929		var htm = '<div id="pop-help-text-deliverability">' + msg0 + msg0Note + msg1 + msg1img + msg2 + msg2img + msg3 + listEnc + msg4 + listBestPrac + '</div>';
44930		var jpop = GLO.Popup.Custom.openSimple(htm, 'MMS Pricing & Deliverability Best Practices');
44931		GLO.Popup.Custom.singleButton(jpop);
44932	}
44933
44934	function _initForMobile() {
44935		if (innerWidth < 500) {
44936			$('#filter-not-seen-since').attr('placeholder', 'Not Seen Since');
44937		}
44938	}
44939	
44940	function _initNonAdmin() {
44941		GLO.Info.init();
44942		
44943		if (GLO.Info.roleType < 210) {
44944			$('#filter-service').find('option[value="-1"]').remove();
44945			_initClientList();
44946		}
44947	}
44948	
44949	function _initExistingMessage() {
44950		var j = $('#bulk-email-container');
44951		var mbid = j.find('#Message_Bulk_id').val();
44952		//var sentDate = j.find('#bulk-email-sent-date').attr('value');
44953		
44954		if (!_isEditableMsg()) {								// (!UTIL.isEmpty(sentDate)) {
44955			j.find('input').prop('disabled', true);
44956		}
44957		
44958		if (!UTIL.isEmpty(mbid)) {
44959			return true;
44960		} else {
44961			return false;
44962		}
44963	}
44964	
44965	function _initMessageArea(fmtType) {
44966		var j = $('#be-top');
44967		
44968		if (j.length === 0) {
44969			$('#be-client-list').removeClass('hide');
44970			return;
44971		}
44972		
44973		var jfmt = $('#be-message-format .mobile-radio-button')
44974		var openMessage = (UTIL.parseBool(GLO.Uri.query('openMessage')) || UTIL.parseBool(GLO.Uri.query('openEmail')) || $('#Message_Bulk_id').val() > 0);
44975		var msgBody = j.find('#email-body-container .sa-text-editor')[0].innerHTML;
44976		
44977		if (!openMessage && (msgBody.length > 8 || !UTIL.isEmpty(j.find('#Message_Bulk_id').val()))) {
44978			if (_getRemainingMessages(j) > 0) {
44979				openMessage = true;
44980			}
44981		}
44982		
44983		if (openMessage && !$('#be-create-email-header').is(':visible')) {
44984			$('#be-create-email-header').click();
44985		}
44986		
44987		if (_isEditableMsg()) {
44988			jfmt.find('li').click(GLO.Message.Bulk.changeFormatType);
44989			jfmt.find('li[value="' + fmtType + '"]').click();
44990		} else {
44991			jfmt.find('li[value="' + fmtType + '"]').addClass('selected');
44992			_changeFormatType(fmtType);
44993			_initClientList(true);
44994			
44995			if (fmtType == 1) {
44996				$('.sa-text-editor-menu').addClass('hide');
44997				$('.sa-text-editor').attr('contenteditable', 'false');
44998			}
44999		}
45000		
45001		_conBMsg.monitorWidth();
45002		setInterval(GLO.Message.Bulk.monitorWidth, 4900);
45003	}
45004	
45005	function _isEditableMsg() {
45006		return $('#bulk-email-sent-date').length === 0 && $('#bulk-email-schedule-date').length == 0 && $('#bulk-email-in-progress').length == 0;
45007	}
45008	
45009	_conBMsg.monitorWidth = function() {
45010		//var widthDoc = $('#doc3').width();
45011		var j = $('#bulk-email-container');
45012		var jmsg = j.find('.sa-text-editor');
45013		
45014		var widthMsg = jmsg.width();
45015		var widthLabel = j.find('.be-message-body').outerWidth();
45016		var widthBE = j.find('#be-top').width();
45017		
45018		if (widthMsg > widthBE - widthLabel - 10) {
45019			var mw = widthBE - widthLabel - 20 + 'px';
45020			jmsg.css({ "max-width": mw });
45021		} else if (widthBE > widthMsg) {
45022			var mw = widthBE - widthLabel - 20 + 'px';
45023			jmsg.css({ "max-width": mw });
45024		}
45025	}
45026	
45027	function _initStaffDropDown(j) {
45028		var jstaff = j.find('#filter-staff').html(UserPortal.getStaffDropDown().html());		//var slist = '<option value="">(all staff)</option>' + UserPortal.getStaffDropDown().html();
45029		jstaff.find('option[value=""]').remove();
45030		
45031		var ddInactive = j.find('#InactiveStaffList').find('option');
45032		
45033		if (ddInactive.length > 0) {
45034			var htmInactive = '<optgroup label="Inactive Staff">';
45035			
45036			for (var i = ddInactive.length - 1; i >= 0; i--) {
45037				htmInactive += ddInactive.eq(i).outerHTML();
45038			}
45039			
45040			jstaff.html('<optgroup label="Active Staff">' + jstaff.html() + '</optgroup>');
45041			jstaff.prepend(htmInactive + '</optgroup>');
45042		}
45043		
45044		j.find('#InactiveStaffList').remove();
45045		jstaff.prepend('<option value="" style="text-align: center;" selected="selected"> ( All Staff ) </option>');
45046	}
45047	
45048	function _initClientFilter() {
45049		var j = $('#ticket-type-filter');
45050		var yearRange = GLO.UI.getYearRange(true);					//'2012:' + (new Date().getFullYear() + 2);
45051		
45052		_initStaffDropDown(j);
45053		j.find('#filter-brand').find('option:first').text('( ' + SA.Resource.AllBrands + ' )');
45054		j.find('#filter-category').find('option:first').text('( ' + SA.Resource.AllCategories + ' )');
45055		j.find('#filter-category').find('option:first').after('<option value="-1">At Least 1 Product Purchase</option>');
45056		
45057		j.find('#filter-start').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(1400), showCurrentAtPos: 1, changeYear: true, yearRange: yearRange });
45058		j.find('#filter-end').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(), changeYear: true, yearRange: yearRange });
45059		j.find('#filter-not-seen-since').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(), changeYear: true, yearRange: yearRange });
45060		
45061		var jclientRefer = j.find('#Referred_By_Client_id');
45062		
45063		if (jclientRefer.length) {
45064			UI.initAutoComplete(jclientRefer, GLO.Link.Object.Provider.ClientSearch);
45065		}
45066		
45067		_initNeverHad(j);
45068		
45069		if (j.find('#btnFilter').length === 0) {
45070			j.find('input, select').prop('disabled', true);
45071		}
45072	}
45073	
45074	function _initNeverHad(j) {
45075		var noServiceTitle = 'Ignore clients that have had an appointment with this service';
45076		var noProductTitle = 'Ignore clients who have bought these products';
45077		var noService = UTIL.coalesce(GLO.Uri.url('noappt'), GLO.Uri.url('noclass'), GLO.Uri.url('noapptever'), GLO.Uri.url('noclassever'));
45078		
45079		var jNeverHadService = '<select id="filter-never-had-service" title="' + noServiceTitle + '">' + j.find('#filter-service').html() + '</select>';
45080		var jNeverHadProduct = '<select id="filter-never-had-product" title="' + noProductTitle + '">'
45081								+ '<option value=""></option>'
45082								+ '<option id="never-had-any-product" value="-1">Never Purchased Any Product</option>'
45083								+ '<optgroup id="filter-never-had-brand" label="Never Purchased Product with Brand">' + j.find('#filter-brand').html() + '</optgroup>'
45084								+ '<optgroup id="filter-never-had-category" label="Never Purchased Product in Category">' + j.find('#filter-category').html() + '</optgroup>'
45085							+ '</select>';
45086		
45087		j.find('#filter-never-had-service').replaceWith(jNeverHadService);
45088		j.find('#filter-never-had-product').replaceWith(jNeverHadProduct);
45089		
45090		if (noService == -2) {
45091			j.find('#filter-never-had-service').find('option:first').after('<option value="-2"> At Least 1 Class</option>');
45092		}
45093		
45094		j.find('#filter-never-had-service').find('option:first').html('');
45095		j.find('#filter-never-had-service').find('option[value="1"]').attr('id', 'filter-never-any-service').html('Never Had Any Service');
45096		
45097		j.find('#filter-never-had-product').find('#filter-never-had-brand > option:first').remove();
45098		j.find('#filter-never-had-product').find('#filter-never-had-category > option:first').remove();
45099	}
45100	function _initClientFilterNarrowScreen() {			//= some fields just too confusing on small UI
45101		if (innerWidth >= 400) { return; }
45102		
45103		var j = $('#be-filter-client-area');
45104		
45105		j.find('li.bday-filter-container').remove();
45106		j.find('li.filter-never-had-container').remove();
45107	}
45108	function _initClientFilterData() {
45109		var j = $('#ticket-type-filter');
45110		
45111		j.find('#filter-first-name').val(UTIL.cleanString(GLO.Uri.url('fname')));
45112		j.find('#filter-last-name').val(UTIL.cleanString(GLO.Uri.url('lname')));
45113		
45114		_initClientFilterDataElement(j, '#filter-staff', 'original_staff_id', null, 'staff');
45115		_initClientFilterDataElement(j, '#filter-service', 'original_service_id', 'original_service_group_id', 'service');
45116		_initClientFilterDataElement(j, '#filter-brand', 'original_vendor_id', 'original_pline_id', 'brand');
45117		_initClientFilterDataElement(j, '#filter-category', 'original_category_id', 'original_category_type_id', 'category');
45118		
45119		_initClientFilterDataElement(j, '#filter-start', 'original_dt', null, 'start');
45120		_initClientFilterDataElement(j, '#filter-end', 'original_dt', null, 'end');
45121		_initClientFilterDataElement(j, '#filter-not-seen-since', 'original_dt', null, 'notsince');
45122		
45123		var noService = UTIL.coalesce(GLO.Uri.url('noappt'), GLO.Uri.url('noclass'), GLO.Uri.url('noapptever'), GLO.Uri.url('noclassever'));
45124		var noProduct = UTIL.coalesce(GLO.Uri.url('noproduct'), GLO.Uri.url('noproductever'));
45125		
45126		if (noService) { j.find('#filter-never-had-service').val(noService); }
45127		if (noProduct) { j.find('#filter-never-had-product').val(noProduct); }
45128		
45129		_initClientFilterBirthday(j);
45130		_initClientFilterTag(j);
45131		_initClientFilterRefer(j);
45132		_initClientFilterVisitCount(j);
45133		
45134		j.find('#Zip_vc').val(GLO.Uri.url('zip'));
45135		
45136		_initMinServiceAndProduct(j);
45137		_getProfileCreateQueryString(j, true);
45138		_initDefaultFilter(j);
45139	}
45140	function _initClientFilterVisitCount(j) {
45141		if (UTIL.parseBool(GLO.Uri.url('lastwithstaff')) && j.find('#Last_Visit_With_Staff_fl:visible').length) {
45142			j.find('#Last_Visit_With_Staff_fl').prop('checked', true);
45143		}
45144		
45145		var wasNewClient = GLO.Uri.url('wasnewclient');
45146		var min = GLO.Uri.url('minvisit'), max = GLO.Uri.url('maxvisit'), exact = GLO.Uri.url('exactvisit');
45147		var jtype = j.find('#filter-visit-count-type'), jamount = j.find('#filter-visit-count');
45148		
45149		if (UTIL.parseBool(wasNewClient)) {
45150			j.find('#Was_New_Client_fl').prop('checked', true);
45151		}
45152		
45153		if (UTIL.isNumber(min)) {
45154			j.find('#Min_Visit_sr').val(min);
45155			jamount.val(min);
45156			jtype.find('option[value="-1"]').prop('selected', true);
45157		}
45158		
45159		if (UTIL.isNumber(max)) {
45160			j.find('#Max_Visit_sr').val(max);
45161			jamount.val(max);
45162			jtype.find('option[value="1"]').prop('selected', true);
45163		}
45164		
45165		if (UTIL.isNumber(exact)) {
45166			jamount.val(exact);
45167			jtype.find('option[value="0"]').prop('selected', true);
45168		}
45169	}
45170	function _initClientFilterRefer(j) {
45171		j.find('#Provider_Referral_id').val(GLO.Uri.url('prefer'));
45172		
45173		var clientReferId = GLO.Uri.url('crefer');
45174		
45175		if (UTIL.isNumber(clientReferId)) {
45176			var jreferClient = j.find('#Referred_By_Client_id').attr('autoid', clientReferId);
45177			_conBMsg.getClientNameForField(clientReferId, jreferClient);
45178		}
45179	}
45180	function _initClientFilterTag(j) {
45181		var tagType = GLO.Uri.url('tagtype'), tagRelate = UTIL.coalesce(GLO.Uri.url('tagrelationship'), 'both'), tagNote = UTIL.cleanString(GLO.Uri.url('tagnote'));
45182		
45183		if (!UTIL.isEmpty(tagType)) {
45184			j.find('#Client_Tag_Type_id').val(tagType).change();
45185			j.find('#Client_Tag_Relationship_cd').val(tagRelate);
45186		}
45187		
45188		j.find('#Tag_Note_vc').val(tagNote);
45189	}
45190	function _initClientFilterBirthday(j) {
45191		j.find('#bday-start-month').val(GLO.Uri.url('bmonth1'));
45192		j.find('#bday-start-day').val(GLO.Uri.url('bday1'));
45193		j.find('#bday-end-month').val(GLO.Uri.url('bmonth2'));
45194		j.find('#bday-end-day').val(GLO.Uri.url('bday2'));
45195	}
45196	
45197	_conBMsg.getClientNameForField = function(cid, jclient) {
45198		var url = GLO.Link.Object.Provider.Ajax + 'ClientQuick?id=' + cid;
45199		
45200		$.ajax({ type: "GET", url: url, "cache": false })
45201            .success( function(data, textStatus, jqXHR) {
45202                var jdata = $(data);
45203                var cname = jdata.attr('name');
45204                
45205                if (!UTIL.isEmpty(cname)) {
45206                	jclient.val(cname);
45207                }
45208            })
45209            .error( function(jqXHR, textStatus, errorThrown) { 
45210                //GLO.UI.Form.resetProcessing();
45211            });
45212	}
45213	
45214	function _initDefaultFilter(j) {
45215		var staffCount = j.find('#filter-staff').find('option').length;
45216		
45217		if (UTIL.coalesceInt(staffCount) < 5) { return; }
45218		if (UTIL.parseBool(GLO.Uri.url('allclients'))) { return; }
45219		
45220		var arrQS = window.location.search.substring(1).split('&');
45221		var len = arrQS.length - 1;
45222		
45223		if (arrQS.has('help')) { --len; }
45224		if (arrQS.has('highlight')) { --len; }
45225		if (arrQS.has('open')) { --len; }
45226		
45227		if (arrQS.has('helloback')) { --len; }
45228		if (arrQS.has('openback')) { --len; }
45229		if (arrQS.has('pageback')) { --len; }
45230		
45231		//if (arrQS.has('openEmail')) { --len; }
45232		//if (arrQS.has('format')) { --len; }
45233		
45234		var quality = _filterSettingQuality(arrQS);
45235		
45236		if (len < 1 && quality < 2) {
45237			if (staffCount > 9 && quality == 0) {
45238				var today = new Date();
45239				var start = new Date(today.setMonth(today.getMonth() - 1)).toGloDate();
45240				var end = new Date(today.setMonth(today.getMonth() + 1)).toGloDate();
45241				
45242				j.find('#filter-start').val(start);
45243				j.find('#filter-end').val(end);
45244			}
45245			
45246			j.find('#filter-service').val(-1);
45247		}
45248	}
45249	
45250	function _filterSettingQuality(arrQS) {
45251		if (arrQS.length > 0 && arrQS[0].split('=').length > 1) {
45252			var key = arrQS[0].split('=')[0].toLowerCase();
45253			
45254			if (key === 'staff' || key === 'crefer') {
45255				return 2;
45256			} else if (key === 'service' || key === 'brand' || key === 'category' || key === 'prefer' || key === 'minloyalty'
45257						|| key === 'filter-first-name' || key === 'filter-last-name' || key === 'bday1' || key === 'zip' || key === 'tagrelationship' || key === 'tagtype') {
45258				return 1;
45259			}
45260		}
45261		
45262		return 0;
45263	}
45264	
45265	function _initMinServiceAndProduct(j) {
45266		var jsvc = j.find('#filter-service');
45267		var jcat = j.find('#filter-category');
45268		var minsvc = UTIL.coalesceInt(jsvc.attr('min_service_sr'), GLO.Uri.url('minservice'));
45269		var minproduct = UTIL.coalesceInt(jcat.attr('min_product_sr'), GLO.Uri.url('minproduct'));
45270		
45271		if (minsvc > 0) {
45272			var jopt2 = jsvc.find('option').eq(1);
45273			
45274			if (minsvc > 1) {
45275				jopt2.after('<option value="' + (-minsvc) + '">At Least ' + minsvc + ' Services</option>');
45276				jsvc.find('option').eq(2).prop('selected', true)
45277			} else {
45278				jopt2.prop('selected', true);
45279			}
45280		}
45281		
45282		if (minproduct > 0) {
45283			var jopt2 = jcat.find('option').eq(1);
45284			
45285			if (minproduct > 1) {
45286				jopt2.after('<option value="' + (-minproduct) + '">At Least ' + minproduct + ' Product Purchases</option>');
45287				jcat.find('option').eq(2).prop('selected', true);
45288			} else {
45289				jopt2.prop('selected', true);
45290			}
45291		}
45292	}
45293	
45294	function _initClientFilterDataElement(j, selector, attribute1, attribute2, queryKey) {
45295		var val, jelement = j.find(selector);
45296		
45297		if (!UTIL.isEmpty(attribute1)) {
45298			val = jelement.attr(attribute1);
45299			jelement.removeAttr(attribute1);
45300		}
45301		
45302		if (UTIL.isEmpty(val) && !UTIL.isEmpty(attribute2)) {
45303			val = jelement.attr(attribute2);
45304			jelement.removeAttr(attribute2);
45305		}
45306		
45307		if (UTIL.isEmpty(val) && !UTIL.isEmpty(queryKey)) {
45308			val = GLO.Uri.url(queryKey);
45309		}
45310		
45311		if (!UTIL.isEmpty(val)) {
45312			if (attribute1 === 'original_dt') {
45313				val = new Date(val).toSADate(true);
45314				jelement.val(val);
45315			} else {
45316				jelement.val(val);
45317			}
45318		}
45319	}
45320	
45321	function _initClientList(isLoading) {
45322		_pageNumber = 1;
45323		_pageCount = Math.ceil(_getActiveRows().length / 100);
45324		
45325		if (isLoading || _isInitPage) {
45326			var jtbl = $('#be-client-list');
45327			var sortArray = null;
45328			
45329			if (_findSortColumn()) {
45330				sortArray = [_sortColumn, _sortDescending];
45331			}
45332			
45333			UI.initTableSorter(jtbl, sortArray, true);					//jtbl.bind("sortStart",function() { $('#be-client-list tr.hide').removeClass('hide'); });
45334			
45335		    jtbl.bind("sortEnd",function(event) {
45336		    	GLO.Message.Bulk.gotoPage(_pageNumber);
45337		    });
45338		}
45339		
45340		return _setPage(true);
45341	}
45342	
45343	function _findSortColumn() {
45344		if (!UTIL.isNumber(_sortColumn) && !UTIL.isEmpty(_sortColumn)) {
45345			var sortColumn = String(_sortColumn).toLowerCase();
45346			var jhead = $('#be-client-list').find('thead > tr');
45347			
45348			if (sortColumn == 'client') {
45349				_sortColumn = jhead.find('.be-client-name').index();
45350			} else if (sortColumn == 'icon') {
45351				_sortColumn = jhead.find('.be-icons').index();
45352			} else if (sortColumn == 'phone') {
45353				_sortColumn = jhead.find('.be-phone-column').index();
45354			} else if (sortColumn == 'email') {
45355				_sortColumn = jhead.find('.be-email-column').index();
45356			} else {
45357				_sortColumn = jhead.find('.' + sortColumn).index();
45358			}
45359		}
45360		
45361		if (UTIL.isNumber(_sortColumn) && _sortColumn > 0) {
45362			_sortColumn = parseInt(_sortColumn);
45363			return true;
45364		} else {
45365			_sortColumn = _sortDescending = null;
45366			return false;
45367		}
45368	}
45369	
45370	function _displayRemainingMessages(j, fmt) {
45371		var jremaining = j.find('#be-remaining-messages');
45372		var jtotal = j.find('#be-total-monthly-messages');
45373		var jbonus = j.find('#be-bonus-messages');
45374		var bonusCount = UTIL.coalesceInt(jbonus.attr('bonus_count_sr'), 0);
45375		
45376		if (fmt == 3) {
45377			var available = jremaining.attr('text_nr'), max = jtotal.attr('text_nr');
45378			jbonus.text(UTIL.coalesceInt(bonusCount/3));
45379		} else {
45380			var available = jremaining.attr('email_nr'), max = jtotal.attr('email_nr');
45381			jbonus.text(bonusCount);
45382		}
45383		
45384		jremaining.text(available);
45385		jtotal.text(max);
45386	}
45387	function _getRemainingMessages(jcontainer) {
45388		var jPayAsUse = jcontainer.find('#bmsg-per-message');
45389		var jremaining = jcontainer.find('#be-remaining-messages');
45390		var isText = (jcontainer.find('#Message_Format_cd').find('li.selected').attr('value') == 3);
45391		
45392		if (jPayAsUse.length) {
45393			var jcontainer = $('#bulk-email-container');
45394			var isMax = UTIL.parseBool(jcontainer.attr('allow_more_messages_fl'));
45395			var maxAllowedText = UTIL.coalesceInt(jcontainer.attr('max_text_allowed'));
45396			
45397			if (isMax) {
45398				if (isText) {
45399					if (maxAllowedText > 0) {
45400						return maxAllowedText;
45401					} else {
45402						return 5000;
45403					}
45404				} else {
45405					return 15000;
45406				}
45407			} else {
45408				if (isText) {
45409					return 1000;
45410				} else {
45411					return 5000;
45412				}
45413			}
45414		} else if (isText) {
45415			var cnt = jremaining.attr('text_nr');
45416		} else {
45417			var cnt = jremaining.attr('email_nr');
45418		}
45419		
45420		return UTIL.coalesceInt(cnt, 0);
45421	}
45422	
45423	function _getActiveRows(forceEmailOnly, forceTextOnly) {
45424		var j = $('#bulk-email-container');
45425		var jtbl = j.find('#be-client-list > tbody');
45426		
45427		if (forceEmailOnly || j.hasClass('accept-email-only')) {
45428			return jtbl.find('tr.accept-email');
45429		} else if (forceTextOnly || (j.hasClass('accept-text-only'))) {				// && GLO.Data.provider.textPackage < 10
45430			return jtbl.find('tr.accept-text');
45431		} else {
45432			return jtbl.find('tr');
45433		}
45434	}
45435	
45436	function _displayMoreInfoPopup(actionType, reason2) {
45437		if (actionType === 'email-blast' || actionType === 'email-followup') {
45438			var h1 = SA.Resource.CustomerMarketing;
45439			var msg = SA.Resource.MarketingHelp + '<br/><br/>' + SA.Resource.MarketingHelp2;
45440		} else {												//if (actionType === 'mobile-app') {
45441			var h1 = GLO.Data.provider.name + ' iPhone App';
45442			var msg = '<div style="text-align: left;">'
45443						+ '<div style="">Want your business to have it\'s own iPhone / iPad app where customers can view your services, book appointments, etc?</div><br/>'
45444						+ '<div style="text-align: center;">We can help!</div><br/>'
45445						+ '<div style=" margin-bottom: 10px;">Contact us to get started creating your very own iPhone app your customers can use</div>'
45446						+ '<div style="">If you have any special requests you can enter them below</div>';
45447					+ '</div>';
45448		}
45449		
45450		var msg = $('<div id="pop-request-more-info" style="padding-left: 6px; padding-right: 2px;"> <h1 action_type_vc="' + actionType + '" class="friendly-msg2">' + h1 + '</h1>'
45451                    + '<div style="max-width: 500px; letter-spacing: 1px; line-height: 180%;">' + msg + '</div>'
45452                    + '<div> <textarea id="More_Info_vc" maxlength="2000" placeholder="' + SA.Resource.SpecialRequests + '"></textarea> </div>'
45453                + '</div>');
45454        
45455        var jpop = new GLO.Popup.Custom(msg, function() {
45456        		GLO.Message.Bulk.sendPleaseContact(actionType, false);
45457        	}).getPopup().addClass('no-persist');
45458        
45459        jpop.find('.btnSave').css({ "float": "right", "margin-left": "0", "text-align": "center" }).find('> a').text('Ok');
45460        jpop.find('.btnCancel').css({ "width": "80px" }).find('> a').css({ "letter-spacing": "2px" }).click(function() {
45461    		GLO.Message.Bulk.sendPleaseContact(actionType, true, reason2);
45462    	});
45463	}
45464	
45465	_conBMsg.sendPleaseContact = function(actionType, isIgnore, note) {
45466		var jpop = $('#pop-request-more-info').closest('.glopop');
45467		var note2 = jpop.find('#More_Info_vc').val();
45468		
45469		if (!UTIL.isEmpty(note) && !UTIL.isEmpty(note2)) { note = note2 + ': ' + note; }
45470		
45471		note = UTIL.htmlEncode(note, note2);
45472		
45473		var url = GLO.Link.WebsiteDomain + "log/NotifySA";
45474        var jd = { "isIgnore": UTIL.parseBool(isIgnore), "action_type_vc": actionType, "note_vc": note };
45475        
45476        GLO.Popup.close(jpop);
45477        
45478        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
45479            .success(function (data, textStatus, jqXHR) {
45480                
45481            })
45482            .error(function (jqXHR, textStatus, errorThrown) {
45483                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
45484            })
45485	}
45486	
45487	_conBMsg.gotoUpgrade = function(btn, reason, reason2, helloback) {
45488		if (GLO.Info.isIosApp) {
45489			_displayMoreInfoPopup(reason, reason2);
45490			return;
45491		}
45492		
45493		var j = $('#be-top');
45494		var btnSave = j.find('#be-message-body3 #btnSaveForLater > a');
45495		var jbody = j.find('#email-body-container .sa-text-editor');
45496		var body = null, timeoutDelay = 600;
45497		
45498		if (jbody.length > 0) {
45499			body = jbody[0].innerHTML;
45500		}
45501		
45502		if (!UI.borderIsTransparent(btnSave) && body.length > 20) {
45503			var jsubject = j.find('#Subject_vc');
45504			
45505			if (UTIL.isEmpty(jsubject.val())) {
45506				jsubject.val('Subject');
45507			}
45508			
45509			btnSave.click();
45510			timeoutDelay = 1200;
45511		}
45512		
45513		if (btn) {
45514			btn = $(btn).parent();
45515			GLO.UI.Form.beginProcessing(btn);
45516		}
45517		
45518		setTimeout(function() {
45519			var url = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=' + UTIL.cleanString(reason);
45520			
45521			if (helloback) { url += '&helloback=' + helloback; }
45522			
45523			document.location = url;
45524		}, 600);
45525	}
45526	
45527	_conBMsg.removeBulk = function(element) {
45528		var btn = $(element).parent();
45529		var tr = btn.closest('tr').addClass('prep-remove');
45530		
45531		var msg = $('<div> <h1 class="friendly-msg2">' + SA.Resource.DeleteMessage + '</h1> <div class="friendly-msg2">' + SA.Resource.DeleteMessageConfirm + '</div> </div>');
45532		
45533		var oj = new GLO.Popup.Confirm(msg, GLO.Message.Bulk.removeBulkConfirmed, function() {
45534				tr.removeClass('prep-remove');
45535				GLO.Popup.close();
45536			});
45537    	
45538    	var jpop = oj.getPopup();
45539    	var jbtn = jpop.find('.pop-buttons');
45540	}
45541	
45542	_conBMsg.removeBulkConfirmed = function() {
45543		var tr = $('tr.prep-remove');
45544		var btn = tr.find('#btnTrashBin > a');
45545		var id = tr.attr('message_bulk_id');
45546		var uri = GLO.Link.WebsiteDomain + 'message/BulkRemove?id=' + id;
45547		
45548		GLO.UI.Form.beginProcessing(btn);
45549		
45550        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "id": id } })
45551            .success(function(data, textStatus, jqXHR) {
45552                tr.remove();
45553                GLO.UI.Form.resetProcessing(btn);
45554            })
45555            .error(function(jqXHR, textStatus, errorThrown) {
45556                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
45557                tr.removeClass('prep-remove');
45558            });
45559	}
45560	
45561	function _setPage(isInit) {
45562		var tbl = $('#be-client-list');
45563		var rows = _getActiveRows();				//tbl.find('tbody > tr');
45564		var clientCount = rows.length;
45565		var isEmailOnly = $('#Include_Email_Only_fl').prop('checked');
45566		var isTextOnly = false;			//		$('#Include_Text_Only_fl').prop('checked');
45567		
45568		if (rows.length > 150) {
45569			for (var i = _pageNumber * 100; i < rows.length; i++) {
45570				rows.eq(i).addClass('hide');
45571				//if (isEmailOnly && _hasEmail(tr)) { ++clientCount; }
45572			}
45573			
45574			if (_pageNumber > 1) {
45575				for (var i = 0; i < _pageNumber * 100; i++) {
45576					rows.eq(i).addClass('hide');
45577					//if (isEmailOnly && _hasEmail(tr)) { ++clientCount; }
45578				}
45579			}
45580			
45581			for (var i = (_pageNumber -1) * 100; i < _pageNumber * 100; i++) {
45582				rows.eq(i).removeClass('hide');
45583				//if (isEmailOnly && _hasEmail(tr)) { ++clientCount; }
45584			}
45585			
45586			_setPageControl(tbl, rows.length);
45587			//if (!isEmailOnly) { clientCount = rows.length; }
45588		} else {
45589			$('#sa-page-control').remove();
45590			
45591			/*
45592			if (isInit && isEmailOnly) {
45593				for (var i = 0; i < rows.length; i++) {
45594					if (isEmailOnly && _hasEmail(rows.eq(i))) { ++clientCount; }
45595				}
45596			} else {
45597				clientCount = rows.length;
45598			}
45599			*/
45600		}
45601		
45602		if (isInit || rows.length > 150) {
45603			var msg = clientCount + ' ' + SA.Resource.Clients.toLowerCase();
45604			
45605			if (clientCount === 0) {
45606				clientCount = $('#bulk-sent-client-list').find('tbody tr').length;
45607				
45608				if (clientCount > 0) {
45609					msg = '<i style="letter-spacing: 0;">Sent to ' + UTIL.numberWithCommas(clientCount) + ' ' + SA.Resource.Clients + '</i>';
45610				}
45611			}
45612			
45613			if (!GLO.Info.isMobile()) {
45614				if (isEmailOnly) {
45615					msg += ' ' + SA.Resource.with_email;
45616				} else if (isTextOnly) {
45617					msg += ' ' + SA.Resource.with_text;
45618				}
45619			}
45620			
45621			$('#be-filter-client-header').find('.quieter').html(msg);
45622		}
45623		
45624		tbl.removeClass('hide');
45625		return clientCount;
45626	}
45627	
45628	function _hasEmail(tr) {
45629		if (tr.hasClass('accept-email')) {					// if (!UTIL.isEmpty(tr.find('.be-email').text())) {
45630			return true;
45631		} else {
45632			return false;
45633		}
45634	}
45635	
45636	function _setPageControl(tbl, rowCount) {
45637		//var prev = '<i class="fa fa-chevron-circle-left" onclick="GLO.Message.Bulk.prevPage()"></i>';
45638		//var next = '<i class="fa fa-chevron-circle-right" onclick="GLO.Message.Bulk.nextPage()"></i>';
45639		
45640		if (_pageNumber < 2) {
45641			var prev = '<i class="fa fa-arrow-circle-left hide" onclick="GLO.Message.Bulk.prevPage()"></i>';
45642		} else {
45643			var prev = '<i class="fa fa-arrow-circle-left" onclick="GLO.Message.Bulk.prevPage()"></i>';
45644		}
45645		
45646		if (_pageNumber >= _pageCount) {
45647			var next = '<i class="fa fa-arrow-circle-right hide" onclick="GLO.Message.Bulk.nextPage()"></i>';
45648		} else {
45649			var next = '<i class="fa fa-arrow-circle-right" onclick="GLO.Message.Bulk.nextPage()"></i>';
45650		}
45651		
45652		var cntItem = '<span id="sa-page-control-client-count" style="position: absolute; left: 8px; bottom: 0; margin: 4px;">' + rowCount + ' ' + SA.Resource.Clients.toLowerCase() + '</span>';
45653		var htm = '<div id="sa-page-control">' + cntItem + '<div id="sa-page-control-center">' + prev + '<span>page ' + _pageNumber + ' of ' + _pageCount + '</span>' + next + '</div> </div>';
45654		
45655		if ($('#sa-page-control').length > 0) {
45656			$('#sa-page-control').html($(htm).html());
45657		} else {
45658			tbl.after(htm);
45659		}
45660	}
45661	
45662	_conBMsg.prevPage = function() {
45663		if (_pageNumber > 1) {
45664			_conBMsg.gotoPage(_pageNumber - 1);
45665		}
45666	}
45667	
45668	_conBMsg.nextPage = function() {
45669		if (_pageNumber < _pageCount) {
45670			_conBMsg.gotoPage(_pageNumber + 1);
45671		}
45672	}
45673	
45674	_conBMsg.gotoPage = function(pageNumber) {
45675		_pageNumber = pageNumber;
45676		_setPage();
45677	}
45678	
45679	_conBMsg.clearDate = function(dateString) {
45680		var j = $('#ticket-type-filter');
45681		
45682		if (dateString === 'start') {
45683			j.find('#filter-start').val('');
45684		} else if (dateString === 'end') {
45685			j.find('#filter-end').val('');
45686		} else if (dateString === 'bday-start') {
45687			j.find('#bday-start').val('');
45688		} else if (dateString === 'bday-end') {
45689			j.find('#bday-end').val('');
45690		} else if (dateString === 'not-seen') {
45691			j.find('#filter-not-seen-since').val('');
45692		} else {
45693			j.find('#' + dateString).val('');
45694		}
45695	}
45696	
45697	_conBMsg.changeFormatType = function() {
45698		UI.changeMobileSelect.call(this);
45699		
45700		var fmtType = $(this).attr('value');
45701		_changeFormatType(fmtType);
45702	}
45703	
45704	function _changeFormatType(fmtType) {
45705		var btns = $('#be-message-body3');
45706		var isCreateMessageOpen = $('#be-top').is(':visible');
45707		_conBMsg.destroyMMSIndicators();
45708		
45709		if (fmtType == 1) {
45710			var jc = $('#bulk-email-container').removeClass('accept-text-only').removeClass('accept-mms-only');
45711			
45712			if (isCreateMessageOpen) { jc.addClass('accept-email-only'); }
45713			
45714			var trHide = $('#bmsg-include-only-text').addClass('hide');
45715			var trShow = $('#bmsg-include-only-email').removeClass('hide');
45716			
45717			$('#be-message-body-text, #be-message-body-text-info').addClass('hide');
45718			$("#be-message-body-text-info").css("margin-top", "");
45719			$('#be-message-body-mms').addClass('hide');
45720			$('#be-message-body-email').removeClass('hide');
45721			
45722			$('#be-message-body-email-info').removeClass('hide');
45723			$('#bmsg-include-client-username').removeClass('hide');
45724			
45725			btns.find('#btnSendSample').addClass('hide');
45726			btns.find('#btnPreview').removeClass('hide');
45727			btns.find('#btnMMSPreview').addClass('hide');
45728			$('#mms-pricing-help').addClass('hide');
45729
45730		} else if (fmtType == 3) { //sms
45731			var jc = $('#bulk-email-container').removeClass('accept-email-only').removeClass('accept-mms-only');
45732			
45733			if (isCreateMessageOpen || $('#Message_Bulk_id').val() > 0) {
45734				jc.addClass('accept-text-only');
45735			}
45736			
45737			var trHide = $('#bmsg-include-only-email').addClass('hide');
45738			var trShow = $('#bmsg-include-only-text').removeClass('hide').prop('checked', false);
45739			
45740			//if (GLO.Data.provider.textPackage > 9) { trShow.prop('checked', false); }
45741			
45742			$('#bmsg-include-client-username').addClass('hide');
45743			$('#be-message-body-text, #be-message-body-text-info').removeClass('hide');
45744			$("#be-message-body-text-info").css("margin-top", "");
45745			$('#be-message-body-email-info').addClass('hide');
45746			$('#be-message-body-email').addClass('hide');
45747			$('#be-message-body-mms').addClass('hide');
45748			
45749			btns.find('#btnPreview').addClass('hide');
45750			btns.find('#btnSendSample').removeClass('hide');
45751			btns.find('#btnMMSPreview').addClass('hide');
45752			$('#mms-pricing-help').addClass('hide');
45753			
45754		} else { //mms
45755			var jc = $('#bulk-email-container').removeClass('accept-email-only').removeClass('accept-text-only');
45756			
45757			if (isCreateMessageOpen || $('#Message_Bulk_id').val() > 0) {
45758				jc.addClass('accept-mms-only');
45759			}
45760			
45761			var trHide = $('#bmsg-include-only-email').addClass('hide');
45762			var trShow = $('#bmsg-include-only-text').removeClass('hide').prop('checked', false);
45763			
45764			//if (GLO.Data.provider.textPackage > 9) { trShow.prop('checked', false); }
45765			
45766			$('#bmsg-include-client-username').addClass('hide');
45767			$('#be-message-body-mms, #be-message-body-text-info').removeClass('hide');
45768			$('#be-message-body-email-info').addClass('hide');
45769			$('#be-message-body-email').addClass('hide');
45770			$('#be-message-body-text').addClass('hide');
45771			$("#be-message-body-text-info").css("margin-top", "70px");
45772			
45773			btns.find('#btnPreview').addClass('hide');
45774			btns.find('#btnSendSample').removeClass('hide');
45775			btns.find('#btnMMSPreview').removeClass('hide');
45776			$('#mms-pricing-help').removeClass('hide');
45777
45778
45779			_conBMsg.initMMSIndicators();
45780			$('#mms_text_vc').keyup();
45781		}
45782		
45783		_displayRemainingMessages(jc, fmtType);
45784		trHide.find(':checkbox').prop('checked', false);
45785		
45786		if (isCreateMessageOpen) {
45787			trShow.find(':checkbox:visible').prop('checked', true);
45788		}
45789		
45790		_conBMsg.onlyClientsWithEmail();
45791	}
45792	
45793	_conBMsg.toggleFilterArea = function() {
45794		var h2 = $('#be-filter-client-header');
45795		var h2click = $('#be-click-to-filter-client');
45796		var j = $('#be-filter-client-area');
45797		
45798		if (j.hasClass('hide')) {
45799			h2click.addClass('hide');
45800			h2.removeClass('hide');					//h2.find('.fa-plus-circle').removeClass('fa-plus-circle').addClass('fa-minus-circle');
45801			
45802			j.removeClass('hide');
45803		} else {
45804			h2.addClass('hide');					//h2.find('.fa-minus-circle').removeClass('fa-minus-circle').addClass('fa-plus-circle');
45805			h2click.removeClass('hide');
45806			
45807			$('#ui-datepicker-div').css('display', 'none');
45808			j.addClass('hide');
45809		}
45810	}
45811	
45812	_conBMsg.toggleMessageArea = function() {
45813		var h2 = $('#be-create-email-header');
45814		var j = $('#be-top')
45815		var h2click = $('#be-click-to-write-email');
45816		
45817		if (j.hasClass('hide')) {
45818			h2.removeClass('hide');					//h2.find('.fa-plus-circle').removeClass('fa-plus-circle').addClass('fa-minus-circle');
45819			j.removeClass('hide');
45820			h2click.addClass('hide');
45821		} else {
45822			h2.addClass('hide');					//h2.find('.fa-minus-circle').removeClass('fa-minus-circle').addClass('fa-plus-circle');
45823			j.addClass('hide');
45824			h2click.removeClass('hide');
45825		}
45826	}
45827	
45828	_conBMsg.onlyClientsWithEmail = function() {
45829		var i=0, clientCount = 0, trs = $('#be-client-list').find('tbody > tr');
45830		var isEmailOnly = $('#Include_Email_Only_fl:visible').prop('checked');
45831		
45832		if (isEmailOnly) {
45833			$('#bulk-email-container').addClass('accept-email-only');
45834			
45835			for (; i < trs.length; i++) {
45836				if (trs.eq(i).find('.be-email').text() === '') {
45837					trs.eq(i).addClass('hideX');
45838				} else {
45839					trs.eq(i).removeClass('hideX');
45840					++clientCount;
45841				}
45842			}
45843			
45844			/*
45845			var jEmailHeader = $('#be-client-list .be-email-column');
45846			
45847			if (!jEmailHeader.hasClass('headerSortUp')) {
45848				jEmailHeader.click();
45849				
45850				if (trs.length > 2 && !jEmailHeader.hasClass('headerSortDown')) {
45851					var ojProcessing = new GLO.Popup.Processing('Loading Only Clients with Email Addresses...');
45852					
45853					setTimeout(function() {
45854						ojProcessing.close();
45855						$('#be-client-list .be-email-column').click();
45856					}, 1500);
45857				}
45858			}
45859			*/
45860		} else {
45861			$('#bulk-email-container').removeClass('accept-email-only');
45862			
45863			for (; i < trs.length; i++) {
45864				trs.eq(i).removeClass('hideX');
45865			}
45866			
45867			clientCount = i;
45868		}
45869		
45870		var msg = clientCount + ' ' + SA.Resource.Clients.toLowerCase();
45871		if (isEmailOnly && !GLO.Info.isMobile()) { msg += ' with email'; }
45872		
45873		$('#be-filter-client-header').find('.quieter').text(clientCount + ' ' + SA.Resource.Clients.toLowerCase());
45874		_initClientList(false);
45875	}
45876	
45877	/* _conBMsg.onlyClientsWithText = function() {
45878		var trs = $('#be-client-list').find('tbody > tr');
45879		
45880		if ($('#Include_Text_Only_fl').prop('checked')) {
45881			$('#bulk-email-container').addClass('accept-text-only');
45882			
45883			for (var i=0; i < trs.length; i++) {
45884				if (trs.eq(i).hasClass('accept-text').length === 0) {
45885					trs.eq(i).addClass('hideX');
45886				} else {
45887					trs.eq(i).removeClass('hideX');
45888				}
45889			}
45890		} else {
45891			$('#bulk-email-container').removeClass('accept-text-only');
45892			
45893			for (var i=0; i < trs.length; i++) {
45894				trs.eq(i).removeClass('hideX');
45895			}
45896		}
45897		
45898		_initClientList(false);				//_conBMsg.gotoPage(_pageNumber);
45899	} */
45900	
45901	/* _conBMsg.changeUrl = function(qs) {
45902		if (window.history.pushState) {
45903    		var url = window.location.origin + window.location.pathname + '?' + qs;
45904		    
45905		    window.history.pushState({ "pageTitle": "Client List" } , "", url);
45906    	}
45907	} */
45908	
45909	_conBMsg.changeEndDate = function(element) {
45910		var jfilter = $('#ticket-type-filter');
45911		var dtEnd = element.value;
45912		var jNotSince = jfilter.find('#filter-not-seen-since');
45913		var dtNotSince = jNotSince.val();
45914		
45915		if (UTIL.isDate(dtEnd) && UTIL.isDate(dtNotSince)) {
45916			if (new Date(dtEnd) > new Date(dtNotSince)) {
45917				var newNotSince = new Date(dtEnd).toGloDate();
45918				jNotSince.val(newNotSince).focus();
45919				UI.highlight(jNotSince, 1200, 6400, false);
45920			}
45921		}
45922	}
45923	function _filterIsValid(start, end, notSince) {
45924		var jfilter = $('#ticket-type-filter');
45925		
45926		if (UTIL.isDate(start) && !UTIL.isDate(end)) {
45927			end = new Date().toGloDate();
45928			jfilter.find('#filter-end').val(end);
45929		}
45930		
45931		if (new Date(start) > new Date(end)) {
45932			var msg = '<h1 class="friendly-quick-msg">' + SA.Resource.InvalidDates + '</h1> <div class="friendly-quick-msg">' + SA.Resource.StartDateWarning + '</div>';
45933			new GLO.Popup.Warning(msg, function() { $('#ticket-type-filter').find('#filter-not-since').focus(); });
45934			return false;
45935		} else if (UTIL.isDate(notSince) && new Date(end) > new Date(notSince)) {
45936			if (new Date(notSince) > new Date(start)) {
45937				end = new Date(notSince).toGloDate();
45938				var jend = jfilter.find('#filter-end');
45939				
45940				jend.val(end);
45941				UI.highlight(jend, 1200, 6400, false);
45942			} else {
45943				var msg = '<h1 class="friendly-quick-msg">' + SA.Resource.InvalidDates + '</h1> <div class="friendly-quick-msg">' + SA.Resource.NotSeenSinceWarning + '</div>';
45944				new GLO.Popup.Warning(msg, function() { $('#ticket-type-filter').find('#filter-end').focus(); });
45945				return false;
45946			}
45947		}
45948		
45949		return true;
45950	}
45951	
45952	function _getStaticQueryString() {
45953		var qs = '';
45954		
45955		var help = GLO.Uri.query('help'), highlight = GLO.Uri.query('highlight'), open = GLO.Uri.query('open'), helpstep = GLO.Uri.query('helpstep');
45956		var helloback = GLO.Uri.query('helloback'), openback = GLO.Uri.query('openback'), pageback = GLO.Uri.query('pageback');
45957		var openMessage = GLO.Uri.query('openMessage');			//, format = GLO.Uri.query('format');
45958		
45959		if (help) { qs += '&help=' + help; }
45960		if (highlight) { qs += '&highlight=' + highlight; }
45961		if (open) { qs += '&open=' + open; }
45962		if (helpstep) { qs += '&helpstep=' + helpstep; }
45963		
45964		if (helloback) { qs += '&helloback=' + helloback; }
45965		if (openback) { qs += '&openback=' + openback; }
45966		if (pageback) { qs += '&pageback=' + pageback; }
45967		
45968		if (openMessage) { qs += '&openMessage=' + openMessage; }
45969		
45970		return qs;
45971	}
45972	
45973	function _getQueryString(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct, isLastVisitWithStaff, fname, lname) {
45974		var qs = '';
45975		
45976		if (!UTIL.isEmpty(start)) {
45977			if (qs !== '') { qs += '&'; }
45978			
45979			qs += 'start=' + start
45980		}
45981		
45982		if (!UTIL.isEmpty(end)) {
45983			if (qs !== '') { qs += '&'; }
45984			
45985			qs += 'end=' + end
45986		}
45987		
45988		if (!UTIL.isEmpty(notSince)) {
45989			if (qs !== '') { qs += '&'; }
45990			
45991			qs += 'notsince=' + notSince
45992		}
45993		
45994		if (!UTIL.isEmpty(sid)) {
45995			if (qs !== '') { qs += '&'; }
45996			
45997			qs += 'staff=' + sid
45998		}
45999		
46000		if (!UTIL.isEmpty(svc)) {
46001			if (qs !== '') { qs += '&'; }
46002			
46003			qs += 'service=' + svc
46004		}
46005		
46006		if (!UTIL.isEmpty(brand)) {
46007			if (qs !== '') { qs += '&'; }
46008			
46009			qs += 'brand=' + brand
46010		}
46011		
46012		if (!UTIL.isEmpty(category)) {
46013			if (qs !== '') { qs += '&'; }
46014			
46015			qs += 'category=' + category;
46016		}
46017		
46018		var bulkId = UTIL.coalesceInt(GLO.Uri.query('id'), GLO.Uri.query('bulk_id'));
46019		
46020		if (!UTIL.isEmpty(bulkId)) {
46021			if (qs !== '') { qs += '&'; }
46022			
46023			qs += 'id=' + bulkId;
46024		}
46025		
46026		if (UTIL.parseBool(isLastVisitWithStaff)) {
46027			if (qs !== '') { qs += '&'; }
46028			
46029			qs += 'lastwithstaff=1';
46030		}
46031		
46032		qs = _getQueryStringKeyValue(qs, 'noappt', noAppt);
46033		qs = _getQueryStringKeyValue(qs, 'noclass', noClass);
46034		qs = _getQueryStringKeyValue(qs, 'noproduct', noProduct);
46035		
46036		qs = _getQueryStringKeyValue(qs, 'noapptever', noApptEver)
46037		qs = _getQueryStringKeyValue(qs, 'noclassever', noApptEver);
46038		qs = _getQueryStringKeyValue(qs, 'noproductever', noProductEver);
46039		qs = _getQueryStringKeyValue(qs, 'minservice', minService);
46040		qs = _getQueryStringKeyValue(qs, 'minproduct', minProduct);
46041		
46042		qs = _getQueryStringKeyValue(qs, 'fname', fname);
46043		qs = _getQueryStringKeyValue(qs, 'lname', lname);
46044		
46045		return qs;
46046	}
46047	
46048	function _getQueryStringKeyValue(qs, key, value) {
46049		if (!UTIL.isEmpty(value)) {
46050			if (qs !== '') { qs += '&'; }
46051			
46052			qs += key + '=' + value;
46053		}
46054		
46055		return qs;
46056	}
46057	
46058	function _displaySearchSummary(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct
46059									, providerRefId, clientRefId, fname, lname, zip) {
46060		var jfilter = $('#be-filter-client-area');
46061		var msg = _getSearchSummary_Appointment(jfilter, start, end, sid, svc, minService);
46062		msg += _getSearchSummary_Product(jfilter, start, end, brand, category, minProduct);
46063		msg += _getSearchSummary_Bday(jfilter);
46064		msg += _getSearchSummary_Tag(jfilter);
46065		
46066		msg += _getSearchSummary_Profile(jfilter, fname, lname, zip);		//name, date created, zip
46067		msg += _getSearchSummary_Loyalty(jfilter);
46068		msg += _getSearchSummary_Refer(jfilter, providerRefId, clientRefId);
46069		
46070		msg += _getSearchSummary_NotSeenSince(jfilter, notSince);
46071		msg += _getSearchSummary_NoAppointment(jfilter, noAppt, noClass, noApptEver);
46072		msg += _getSearchSummary_NoProduct(jfilter, noProduct, noProductEver);
46073		
46074		msg += _getEmailOrTextRestriction();
46075		
46076		//msg += _staticSearchSummary();
46077		return _openSearchSummary(msg);
46078	}
46079	
46080	function _staticSearchSummary() {
46081		var arrow = '<b class="more-info-arrow">&#10140;</b>';
46082		
46083		return '<div id="search-summary-more-info">' + '<h5>More Information</h5>'
46084					+ '<p><span onclick="GLO.Message.Bulk.openHelp()">Tips on managing your client list and sending your clients marketing messages' + arrow + '</span></p>'
46085					+ '<p><span onclick="GLO.Message.Marketing.openHelp()">
46085Details of Emails & Texts ' + GLO.Info.getScheduleAnyoneHtm() + ' Sends' + arrow + '</span></p>'
46086				+ '</div>';
46087	}
46088	
46089	function _getEmailOrTextRestriction() {
46090		var msg = '', jmsg = $('#be-top');
46091		var fmt = jmsg.find('#Message_Format_cd').find('li.selected').attr('value');
46092		
46093		if (fmt == 3) {
46094			if (jmsg.find('#Include_Email_Only_fl').prop('checked')) {
46095				msg = 'Have an email address';
46096			}
46097		//} else {
46098		//	if (jmsg.find('#Include_Text_Only_fl').prop('checked')) {
46099		//		msg = 'Have opted-in to text messages';
46100		//	}
46101		}
46102		
46103		return _getSearchSummaryRow(msg);
46104	}
46105	function _getSearchSummary_Bday(jfilter) {
46106		var mo1 = UTIL.coalesceInt(jfilter.find('#bday-start-month').val(), 0);
46107		var day1 = UTIL.coalesceInt(jfilter.find('#bday-start-day').val(), 1);
46108		var mo2 = UTIL.coalesceInt(jfilter.find('#bday-end-month').val(), 0);
46109		var day2 = UTIL.coalesceInt(jfilter.find('#bday-end-day').val(), 1);
46110		
46111		if (mo1 === 0 || mo2 === 0 || mo1 > mo2) {
46112			return '';
46113		} else {
46114			var d1 = new Date(new Date().setMonth(mo1 - 1)).getMonthString(true) + ' ' + day1;
46115			var d2 = new Date(new Date().setMonth(mo2 - 1)).getMonthString(true) + ' ' + day2;
46116			
46117			var msg = 'Birthday between ' + d1 + ' - ' + d2;
46118			return _getSearchSummaryRow(msg);
46119		}
46120	}
46121	function _getSearchSummary_Tag(jfilter) {
46122		var tagType = jfilter.find('#Client_Tag_Type_id option:selected').text();
46123		var jTagRelate = jfilter.find('#Client_Tag_Relationship_cd option:selected');
46124		var tagNote = jfilter.find('#Tag_Note_vc').val();
46125		var msg = '';
46126		
46127		if (!UTIL.isEmpty(tagType)) {
46128			tagType = '<b>' + tagType + '</b>';
46129			
46130			if (!UTIL.isEmpty(jTagRelate.val()) && jTagRelate.val() != 'both') {
46131				tagType += ' <small>(' + jTagRelate.text() + ')</small>';
46132			}
46133			
46134			if (!UTIL.isEmpty(tagNote)) {
46135				tagType += ' <small> and the tag note contains <i>"' + tagNote + '"</i></small>';
46136			}
46137			
46138			msg = 'Client has the tag: ' + tagType;
46139		} else if (!UTIL.isEmpty(tagNote)) {
46140			msg = 'Client has any tag where the tag note contains: <i>"' + tagNote + '"</i>';
46141		}
46142		
46143		return _getSearchSummaryRow(msg);
46144	}
46145	function _getSearchSummary_Profile(jfilter, fname, lname, zip) {
46146		var htm = '', msg = '';
46147		var dt1 = jfilter.find('#profile-create-start').val();
46148		var dt2 = jfilter.find('#profile-create-end').val();
46149		
46150		if (UTIL.isDate(dt1) && UTIL.isDate(dt2)) {
46151			msg = 'Client profiles created between ' + dt1 + ' and ' + dt2;
46152		} else if (UTIL.isDate(dt1)) {
46153			msg = 'Client profiles created after ' + dt1;
46154		} else if (UTIL.isDate(dt2)) {
46155			msg = 'Client profiles created before ' + dt2;
46156		}
46157		
46158		if (!UTIL.isEmpty(fname)) {
46159			htm += _getSearchSummaryRow('First name starts with ' + fname);
46160		}
46161		
46162		if (!UTIL.isEmpty(fname)) {
46163			htm += _getSearchSummaryRow('Last name starts with ' + fname);
46164		}
46165		
46166		if (!UTIL.isEmpty(zip)) {
46167			htm += _getSearchSummaryRow('' + jfilter.find('#Zip_vc').attr('placeholder') + ' is ' + zip);
46168		}
46169		
46170		return htm + _getSearchSummaryRow(msg);
46171	}
46172	function _getSearchSummary_Loyalty(jfilter) {
46173		var msg = '', min = jfilter.find('#Loyalty_Min_sr').val(), max = jfilter.find('#Loyalty_Max_sr').val();
46174		
46175		if (parseInt(min) > 0 && parseInt(max) >= 0) {
46176			msg = 'Loyalty point balance between ' + min + ' - ' + max;
46177		} else if (parseInt(min) > 0) {
46178			msg = 'More than ' + min + ' loyalty points';
46179		} else if (parseInt(max) > 0) {
46180			msg = 'Less than ' + max + ' loyalty points';
46181		} else if (parseInt(max) == 0) {
46182			msg = 'Zero loyalty points';
46183		}
46184		
46185		return _getSearchSummaryRow(msg);
46186	}
46187	function _getSearchSummary_Refer(jfilter, providerRefId, clientRefId) {
46188		var msg = '';
46189		
46190		if (providerRefId) {
46191			msg = 'Referred by ' + jfilter.find('#Provider_Referral_id option:selected').text();
46192		}
46193		
46194		//if (clientRefId) { msg = 'Clients referred by ' + ???; }
46195		
46196		return _getSearchSummaryRow(msg);
46197	}
46198	function _getSearchSummary_Appointment(jfilter, start, end, sid, svc, minService) {
46199		var msg = '', appt = ' appointment ', isMobile = GLO.Info.isMobile();
46200		
46201		if (!UTIL.isEmpty(svc)) {
46202			msg += jfilter.find('#filter-service :selected').text() + appt;
46203			appt = ' ';
46204		}
46205		
46206		if (!UTIL.isEmpty(sid)) {
46207			msg += appt + 'with ' + jfilter.find('#filter-staff :selected').text();
46208			appt = ' ';
46209		}
46210		
46211		if (UTIL.isDate(start) && UTIL.isDate(end)) {
46212			msg += appt + 'between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true);
46213		} else if (UTIL.isDate(start)) {
46214			msg += appt + 'since ' + new Date(start).toGloDateString(true, true, isMobile, isMobile)
46215		} else if (UTIL.isDate(end)) {
46216			msg += appt + 'before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile);
46217		} else if (minService > 0 && UTIL.isEmpty(msg)) {
46218			msg = 'At Least ' + UTIL.pluralLabel(minService, 'Service');
46219			return _getSearchSummaryRow(msg);
46220		}
46221		
46222		return _getSearchSummaryRow(msg);
46223	}
46224	
46225	function _getSearchSummary_NotSeenSince(jfilter, notSince) {
46226		var msg = '', dtPretty = new Date(notSince).toGloDateString(true, true);
46227		
46228		if (UTIL.isDate(notSince)) {
46229			if (GLO.Info.providerPackage === 1) {
46230				msg = 'Have not visited since ' + dtPretty;
46231			} else {
46232				msg = 'Have not had appointment or product purchase since ' + dtPretty;
46233			}
46234		}
46235		
46236		return _getSearchSummaryRow(msg, true);
46237	}
46238	
46239	function _getText(jfilter, isNeverHad, isService) {
46240		if (isNeverHad && isService) {
46241			var j = jfilter.find('#filter-never-had-service option:selected');
46242		} else if (isNeverHad) {
46243			var j = jfilter.find('#filter-never-had-product option:selected');
46244		}
46245		
46246		if (UTIL.coalesceInt(j.val(), 0) < 0) {
46247			var text = ' any';
46248		} else {
46249			var text = ' a ' + $.trim(j.text());
46250		}
46251		
46252		return text;
46253	}
46254	
46255	function _getSearchSummary_NoAppointment(jfilter, noAppt, noClass, noApptEver) {
46256		var msg = '';
46257		var serviceText = _getText(jfilter, true, true);
46258		
46259		if (!UTIL.isEmpty(noAppt)) {
46260			 msg = 'Have never had' + serviceText + ' appointment';
46261		} else if (!UTIL.isEmpty(noClass)) {
46262			msg = 'Have never had' + serviceText + ' class reservation';
46263		} else if (!UTIL.isEmpty(noApptEver)) {
46264			msg = 'Have never had an appointment';
46265		}
46266		
46267		return _getSearchSummaryRow(msg, true);
46268	}
46269	
46270	function _getSearchSummary_Product(jfilter, start, end, brand, category, minProduct) {
46271		var msg = '', product = ' product ', isMobile = GLO.Info.isMobile();
46272		
46273		if (UTIL.isEmpty(brand) && UTIL.isEmpty(category)) {
46274			if (minProduct > 0) {
46275				var msg = 'At Least ' + UTIL.pluralLabel(minProduct, 'Product Purchase');
46276				return _getSearchSummaryRow(msg);
46277			} else {
46278				return '';
46279			}
46280		}
46281		
46282		if (!UTIL.isEmpty(brand)) {
46283			msg += jfilter.find('#filter-brand :selected').text() + product;
46284			product = ' ';
46285		}
46286		
46287		if (!UTIL.isEmpty(category)) {
46288			msg += jfilter.find('#filter-brand :selected').text() + product;
46289			product = ' ';
46290		}
46291		
46292		if (UTIL.isDate(start) && UTIL.isDate(end)) {
46293			msg += product + 'between ' + new Date(start).toGloDateString(true, true, true, true) + ' - ' + new Date(end).toGloDateString(true, true, true, true);
46294		} else if (UTIL.isDate(start)) {
46295			msg += product + 'since ' + new Date(start).toGloDateString(true, true, isMobile, isMobile)
46296		} else if (UTIL.isDate(end)) {
46297			msg += product + 'before ' + new Date(end).toGloDateString(true, true, isMobile, isMobile);
46298		}
46299		
46300		return _getSearchSummaryRow(msg);
46301	}
46302	
46303	function _getSearchSummary_NoProduct(jfilter, noProduct, noProductEver) {
46304		var msg = '';
46305		
46306		if (!UTIL.isEmpty(noProduct)) {
46307			var productText = _getText(jfilter, true, false);
46308			msg = 'Have never purchased ' + productText + ' product';
46309		} else if (!UTIL.isEmpty(noProductEver)) {
46310			msg = 'Have never purchased a product';
46311		}
46312		
46313		return _getSearchSummaryRow(msg, true);
46314	}
46315	
46316	function _getSearchSummaryRow(msg, isNever) {
46317		if (msg !== '') {
46318			msg = $.trim(msg);
46319			msg = msg.substring(0,1).toUpperCase() + msg.substring(1);
46320			
46321			if (isNever) {
46322				return '<li class="search-summary-not-since">' + msg + '</li>';
46323			} else {
46324				return '<li>' + msg + '</li>';
46325			}
46326		}
46327		
46328		return msg;
46329	}
46330	
46331	function _openSearchSummary(msg) {
46332		var isAddAllButton = false;
46333		
46334		if (msg !== '') {
46335			var action = '<h6 id="search-summary-label"><b id="search-summary-action">Finding</b> Clients With<b id="search-summary-dots">...</b></h6>';
46336			msg = action + '<ul>' + msg + '</ul>';
46337			isAddAllButton = true;
46338		} else {
46339			msg = '<h6 id="search-summary-label"><b id="search-summary-action">Retrieving</b> <b>All Clients</b><b id="search-summary-dots">...</b></h6>';
46340		}
46341		
46342		var cssThrobber = 'height: 40px; width: 40px; margin: 0; margin-top: 12px;';
46343		var throbber = '<div id="search-summary-throbber">' + GLO.Report.Template2.getBlueThrobber(cssThrobber) + '</div>';
46344		
46345		var htm = '<div id="search-summary">' + msg + throbber + '</div>';
46346		var h1 = UTIL.coalesce(GLO.Uri.query('label'), 'Searching Client List');
46347		var ojpop = GLO.Popup.Custom.open(htm, h1);
46348		var jpop = ojpop.getPopup().addClass('no-persist').css({ "padding-bottom": 0 });
46349		GLO.Popup.Custom.singleButton(jpop);
46350		
46351		var marginBottom = 100;
46352		
46353		if (innerWidth < 550) { marginBottom = 120; }
46354		
46355		var moreInfo = _staticSearchSummary();
46356		var jbtns = jpop.find('.pop-buttons-parent').css({ "position": "relative", "margin-bottom": marginBottom + "px" });
46357		jbtns.find('.btnSA').css({ "z-index": "100" });
46358		jbtns.after(moreInfo);
46359		
46360		if (innerWidth > 620) {
46361			jpop.css({ "min-width": "600px" });
46362		} else if (innerWidth > 520) {
46363			jpop.css({ "min-width": "500px" });
46364		}
46365		
46366		if (isAddAllButton) {
46367			jbtns.find('.pop-buttons').append('<span id="search-summary-all-button" class="btnAdd"><a onclick="GLO.Message.Bulk.filterAllClients()">Display<br/>All Clients</a></span>');
46368		}
46369		
46370		jbtns.find('.pop-buttons').prepend('<span id="search-cancel-button" class="btnAdd"><a onclick="GLO.Message.Bulk.cancelSearch()">Cancel<br/>Search</a></span>');
46371		ojpop.realign();
46372		return ojpop;
46373	}
46374	
46375	_conBMsg.changeTag = function(ddTagType) {
46376		ddTagType = $(ddTagType);
46377		var jtagName = ddTagType.find('option:selected');
46378		var tagName = jtagName.text();
46379		var relationship = jtagName.attr('relationship_name_vc');
46380		var jtag = ddTagType.closest('#tag-filter-container');
46381		var htmRelateOptions = ''; 			//var jTagRelationship = jtag.find('#tag-relationship-container');
46382		
46383		if (!UTIL.isEmpty(relationship)) {
46384			jtag.addClass('has-relationship');
46385			//jTagRelationship.removeClass('hide').find('label').html('<small>include</small>' + relationship);
46386			
46387			htmRelateOptions += '<option value="both">include both: ' + tagName + ' and ' + relationship + '</option>';
46388			htmRelateOptions += '<option value="onlytag">only: ' + tagName + '</option>';
46389			htmRelateOptions += '<option value="onlyrelate">only: ' + relationship + '</option>';
46390		} else {
46391			//jTagRelationship.addClass('hide');
46392			jtag.removeClass('has-relationship');
46393		}
46394		
46395		jtag.find('#Client_Tag_Relationship_cd').html(htmRelateOptions);
46396	}
46397	
46398	_conBMsg.cancelSearch = function(isSearchAll) {
46399		GLO.Popup.close( $('#search-summary').closest('.glopop') );
46400		UTIL.abortAjaxRequest(_currentFilterAjax, true, !isSearchAll);
46401	}
46402	_conBMsg.filterAllClients = function() {
46403		_conBMsg.cancelSearch(true);
46404		$('#ticket-type-filter').find('input,select').val('');
46405		GLO.Message.Bulk.filter();
46406	}
46407	
46408	_conBMsg.getTagQueryString = function(jfilter) {
46409		if (GLO.Info.providerPackage != 2 && GLO.Info.providerPackage != 10 && GLO.Info.providerPackage != 20) { return ''; }
46410		
46411		var qs = '';
46412		var tagTypeId = jfilter.find('#Client_Tag_Type_id').val();
46413		var tagRelationship = jfilter.find('#Client_Tag_Relationship_cd:visible').val();
46414		var tagNote = jfilter.find('#Tag_Note_vc:visible').val();
46415		
46416		if (!UTIL.isEmpty(tagTypeId)) {
46417			qs += '&tagtype=' + tagTypeId;
46418			
46419			if (tagRelationship) {
46420				qs += '&tagrelationship=' + tagRelationship;
46421			}
46422		}
46423		
46424		if (!UTIL.isEmpty(tagNote)) {
46425			qs += '&tagnote=' + tagNote;
46426		}
46427		
46428		return qs;
46429	}
46430	function _getProfileCreateQueryString(jfilter, isInit) {
46431		var dt1 = jfilter.find('#profile-create-start').val();
46432		var dt2 = jfilter.find('#profile-create-end').val();
46433		
46434		if (isInit) {
46435			dt1 = UTIL.coalesceDate(dt1, GLO.Uri.query('profile-create1'));
46436			dt2 = UTIL.coalesceDate(dt2, GLO.Uri.query('profile-create2'));
46437		}
46438		
46439		if (!UTIL.isEmpty(dt1) || !UTIL.isEmpty(dt2)) {
46440			var yearRange = GLO.UI.getYearRange(true);					//'2012:' + (new Date().getFullYear());
46441			
46442			jfilter.find('.profile-create-container').removeClass('hideX');
46443			jfilter.find('#profile-create-start').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(1400), showCurrentAtPos: 1, changeYear: true, yearRange: yearRange });
46444			jfilter.find('#profile-create-end').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek, dateFormat: "M d, yy", numberOfMonths: UI.getDatepickerMonths(), changeYear: true, yearRange: yearRange });
46445			
46446			return '&profile-create1=' + dt1 + '&profile-create2=' + dt2;
46447		}
46448		
46449		return '';
46450	}
46451	function _getVisitCountQueryString(jfilter) {
46452		var jmin = jfilter.find('#Min_Visit_sr'), jmax = jfilter.find('#Max_Visit_sr');
46453		var exact, min, max, qs = '';
46454		
46455		if (jmin.length || jmax.length) {
46456			min = jmin.val();
46457			max = jmax.val();
46458		} else {
46459			var countType = jfilter.find('#filter-visit-count-type').val();
46460			var countAmount = jfilter.find('#filter-visit-count').val();
46461			
46462			if (countType == 1) {
46463				max = countAmount;
46464			} else if (countType == -1) {
46465				min = countAmount;
46466			} else if (countType == 0) {
46467				exact = countAmount;
46468			}
46469		}
46470		
46471		if (!UTIL.isEmpty(min)) {
46472			qs += '&minvisit=' + min;
46473		}
46474		if (!UTIL.isEmpty(max)) {
46475			qs += '&maxvisit=' + max;
46476		}
46477		if (!UTIL.isEmpty(exact)) {
46478			qs += '&exactvisit=' + exact;
46479		}
46480		
46481		return qs;
46482	}
46483	function _getLoyaltyQueryString(jfilter, isInit) {
46484		var jmin = jfilter.find('#Loyalty_Min_sr'), jmax = jfilter.find('#Loyalty_Max_sr');
46485		var min = jmin.val(), max = jmax.val();
46486		
46487		var qs = '';
46488		
46489		if (jmin.length && parseInt(min) >= 0) {
46490			qs += '&minloyalty=' + min;
46491		}
46492		
46493		if (jmax.length && parseInt(max) >= 0) {
46494			qs += '&maxloyalty=' + max;
46495		}
46496		
46497		return qs
46498	}
46499	function _getProfileReferAndZip(jfilter, providerRefId, clientRefId, zip) {
46500		var qs = '';
46501		
46502		if (!UTIL.isEmpty(providerRefId)) {
46503			qs += '&prefer=' + providerRefId;
46504		}
46505		
46506		if (!UTIL.isEmpty(clientRefId)) {
46507			qs += '&crefer=' + clientRefId;
46508		}
46509		
46510		if (!UTIL.isEmpty(zip)) {
46511			qs += '&zip=' + zip;
46512		}
46513		
46514		return qs
46515	}
46516	function _getBdayQueryString(jfilter) {
46517		var mo1 = jfilter.find('#bday-start-month').val();
46518		var day1 = jfilter.find('#bday-start-day').val();
46519		
46520		var mo2 = jfilter.find('#bday-end-month').val();
46521		var day2 = jfilter.find('#bday-end-day').val();
46522		
46523		var bdayStart = UTIL.birthDay(mo1, day1, false);
46524		var bdayEnd = UTIL.birthDay(mo2, day2, true);
46525		
46526		if (bdayStart === 0 || bdayEnd === 0 || bdayStart > bdayEnd) {
46527			return '';
46528		} else {
46529			return '&bmonth1=' + mo1 + '&bday1=' + day1 + '&bmonth2=' + mo2 + '&bday2=' + day2 + '&b1=' + bdayStart + '&b2=' + bdayEnd;
46530		}
46531	}
46532	_conBMsg.changeBirthdayStart = function(element) {
46533		var j = $('.bday-filter-container');
46534		var jday1 = j.find('#bday-start-day');
46535		var jmo2 = j.find('#bday-end-month');
46536		var jday2 = j.find('#bday-end-day');
46537		
46538		var day1 = UTIL.coalesceInt(jday1.val(), 0);
46539		var mo2 = UTIL.coalesceInt(jmo2.val(), 0);
46540		var day2 = UTIL.coalesceInt(jday2.val(), 0);
46541		
46542		if (UTIL.isEmpty(element.value)) {
46543			jday1.val('');
46544			jmo2.val('');
46545			jday2.val('');
46546		} else if (mo2 === 0 || element.value > mo2) {
46547			jmo2.val(element.value);
46548			
46549			if (day1 === 0) {
46550				jday1.val(1);
46551			}
46552			
46553			if (day2 === 0 || (day1 == 1 && day2 > 27)) {
46554				var lastDay = UTIL.lastDayOfMonth(element.value - 1);
46555				jday2.val(lastDay);
46556			}
46557		}
46558	}
46559	
46560	_conBMsg.openHelpWasNewClient = function(element) {
46561		var arrow = '<span class="arrow-right" style="color: inherit;">&#10140;
46561</span>';
46562		var msg1 = '<p style="line-height: 1.4; letter-spacing: 0; font-weight: bold; font-size: larger;">Identify which clients had their first visit</p>';
46563		var msg2 = '<p style="line-height: 1.4;">Then you can send a message to these clients to convert new customers to regular clients</p>';
46564		
46565		var li1 = '<li class="pop-help-note" style="color: green;">';
46566		var note1 = li1 + 'a 1st time client is only 30-40% likely to return for a second visit</p>';
46567		var note2 = li1 + 'after a clients second visit they are 50-70% likely to return for a third visit</p>';
46568		var note3 = li1 + 'After a client\'s third visit they are very likely to become regular clients</p>';
46569		
46570		var noteMsgCss = 'margin: 0; margin-top: 32px; padding-top: 8px; border-top: 1px solid green; font-weight: bold; color: green;'
46571		var noteMsg = '<p style="' + noteMsgCss + '">Convert New Clients ' + arrow + ' Regular Clients</p>';
46572		var noteList = noteMsg + '<ul class="pop-help-note-list">' + note1 + note2 + note3 + '</ul>';
46573		
46574		var htm = '<div id="pop-help-was-new-client">' + msg1 + msg2 + noteList + _getProviderParentHelp() + '</div>';
46575		GLO.Popup.Info.open(htm, '1st Visit During Date Range');
46576	}
46577	function _getProviderParentHelp() {
46578		if (GLO.Data.provider.relationship > 0 || GLO.Data.provider.reportParentId > 0) {
46579			var bWasNewClient = '<b class="narrow-text" title="Was a New Client">1st Visit During Date Range</b>';
46580			var msgCss = 'margin-bottom: 2px; line-height: 1.2; text-align: left; letter-spacing: 0; font-family: arial; font-stretch: condensed; font-size: 120%; font-weight: bold; color: purple;';
46581			var msg = '<p style="' + msgCss + '">When set these fields, filters across all your locations</p>';
46582			
46583			var li1 = '<li class="pop-help-note" style="color: purple;">';
46584			var list1 = li1 + bWasNewClient + ' only clients who were <i class="narrow-text">New client</i> during the given date range <span class="narrow-text">(never been to any location)</span></li>';
46585			var list2 = li1 + '<b class="narrow-text">Not-Seen-Since</b> date range <span class="narrow-text">(at any location)</span> </li>';
46586			
46587			return '<div id="provider-parent-help">' + msg + '<ul class="pop-help-note-list">' + list1 + list2 + '</ul></div>';
46588		} else {
46589			return '';
46590		}
46591	}
46592	_conBMsg.openHelpWithStaff = function(element) {
46593		var name = UTIL.maxString($('#ticket-type-filter #filter-staff').find(':selected').text(), 12, true);
46594		var msg = '<div id="pop-help-filter-with-staff">' + UTIL.replaceAll($(element).attr('title'), 'staff', name) + '</div>';
46595		
46596		GLO.Popup.Info.open(msg, 'Filter Information');
46597	}
46598	
46599	function _toggleStaffLastVisit(jfilter, sid) {
46600		var jwith = jfilter.find('#filter-last-visit-with-staff');
46601		
46602		if (UTIL.isNumber(sid)) {
46603			var name = UTIL.maxString(jfilter.find('#filter-staff').find(':selected').text(), 12, true);
46604			
46605			if (jwith.hasClass('hide')) {
46606				jwith.removeClass('hide').find('span i').text(name);
46607			} else {
46608				return jwith.find('#Last_Visit_With_Staff_fl').prop('checked');
46609			}
46610		} else {
46611			jwith.addClass('hide');
46612		}
46613		
46614		return false;
46615	}
46616	
46617	_conBMsg.changeNotSeenSince = function() {
46618		var jfilter = $('#ticket-type-filter');
46619		var start = UTIL.fromSADate(jfilter.find('#filter-start').val(), true, true);
46620		var end = UTIL.fromSADate(jfilter.find('#filter-end').val(), true, true);
46621		var notSince = jfilter.find('#filter-not-seen-since').val();
46622		
46623		if (UTIL.isDate(notSince)) {
46624			notSince = new Date(UTIL.fromSADate(notSince, true, true));
46625			var newEnd = notSince.addDays(-1).toGloDate();
46626			
46627			if (new Date(start) > notSince) {
46628				var jsvc = jfilter.find('#filter-service');
46629				var dayDiff = UTIL.dayDiff(new Date(end), new Date(start));
46630				var newStart = new Date(new Date(newEnd).addDays(dayDiff)).toGloDate();
46631				
46632				jfilter.find('#filter-start').val(newStart);
46633				jfilter.find('#filter-end').val(newEnd);
46634				
46635				if (UTIL.isEmpty(jsvc.val())) {
46636					jsvc.val(-1);
46637				}
46638			} else if (new Date(end) > notSince) {
46639				var jsvc = jfilter.find('#filter-service');
46640				jfilter.find('#filter-end').val(newEnd);
46641				
46642				if (UTIL.isEmpty(jsvc.val())) {
46643					jsvc.val(-1);
46644				}
46645			} else if (UTIL.isEmpty(start) && UTIL.isEmpty(end) && document.location.search.split('&').length < 3) {
46646				var days = UTIL.dayDiff(notSince, new Date()) + 1;
46647				var dtStart = new Date(notSince).addDays(-days * 2);
46648				
46649				jfilter.find('#filter-start').val(dtStart.toGloDate());
46650				jfilter.find('#filter-end').val(notSince.toGloDate());
46651			}
46652		}
46653		
46654		GLO.Message.Bulk.filter();
46655	}
46656	
46657	_conBMsg.filter = function(isExport) {
46658		var jfilter = $('#ticket-type-filter');
46659    	var sid = jfilter.find('#filter-staff').val();					//var sfilter = GLO.Uri.query('sfilter');
46660    	var isLastVisitWithStaff = _toggleStaffLastVisit(jfilter, sid);
46661    	var fname = jfilter.find('#filter-first-name').val(), lname = jfilter.find('#filter-last-name').val();
46662    	
46663    	var start = jfilter.find('#filter-start').val();
46664    	if (!UTIL.isEmpty(start)) { start = UTIL.fromSADate(start, true, true); }
46665    	
46666    	var end = jfilter.find('#filter-end').val();
46667    	if (!UTIL.isEmpty(end)) { end = UTIL.fromSADate(end, true, true); }
46668    	
46669    	var notSince = jfilter.find('#filter-not-seen-since').val();
46670    	if (!UTIL.isEmpty(notSince)) { notSince = UTIL.fromSADate(notSince, true, true); }
46671    	
46672    	var svc = jfilter.find('#filter-service').val();
46673    	var brand = jfilter.find('#filter-brand').val();
46674    	var category = jfilter.find('#filter-category').val();
46675    	
46676    	var noProduct = jfilter.find('#filter-never-had-product').val();
46677    	
46678    	var noAppt = null, noClass = null, noApptEver = null, noProductEver = null;
46679    	var jNoService = jfilter.find('#filter-never-had-service').find('option:selected');
46680    	
46681    	if (noProduct == -1) {
46682    		noProductEver = 1, noProduct = null;
46683    	}
46684    	
46685    	if (jNoService.attr('id') === 'filter-never-any-service') {
46686    		noApptEver = 1;
46687    	} else if (UTIL.parseBool(jNoService.attr('has_class_fl'))) {
46688    		noClass = UTIL.cleanString(jNoService.attr('value'));
46689    	} else {
46690    		noAppt = UTIL.cleanString(jNoService.attr('value'));
46691    	}
46692    	
46693    	var minService = null, minProduct = null, jd = {};
46694    	var providerRefId = jfilter.find('#Provider_Referral_id').val(), clientRefId = jfilter.find('#Referred_By_Client_id').attr('autoid');
46695    	var zip = jfilter.find('#Zip_vc').val();
46696    	
46697    	if (svc < 0) {
46698    		minService = -svc, svc = null;
46699    	}
46700    	
46701    	if (category < 0) {
46702    		minProduct = -category, category = null;
46703    	}
46704    	
46705    	if (UTIL.isDate(start) && !UTIL.isDate(end)) {
46706        	end = new Date().toGloDate();
46707        	jfilter.find('#filter-end').val(new Date().toGloDateString(false, true, true, false));
46708        } else if (!UTIL.isDate(start) && UTIL.isDate(end)) {
46709        	//start = '';
46710        }
46711        
46712        if (!_filterIsValid(start, end, notSince)) {
46713        	return;
46714        } else if (!GLO.Report.hasReportPassword(jd)) {
46715	    	return;
46716	    }
46717    	
46718    	var end = jfilter.find('#filter-end').val();			//= filterIsValid might change end date value
46719    	if (!UTIL.isEmpty(end)) { end = UTIL.fromSADate(end, true, true); }
46720    	
46721    	var fmt = $('#be-message-format #Message_Format_cd').find('li.selected').attr('value');
46722    	
46723    	if (fmt == 3) {
46724    		$('#Include_Email_Only_fl').prop('checked', false).change();
46725    	}
46726    	
46727    	var ojpop = _displaySearchSummary(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct
46728    									, providerRefId, clientRefId, fname, lname, zip);
46729    	_setSort();
46730    	
46731    	var qs = _getQueryString(start, end, notSince, sid, svc, brand, category, noAppt, noClass, noProduct, noApptEver, noProductEver, minService, minProduct, isLastVisitWithStaff, fname, lname);
46732    	qs += _conBMsg.getTagQueryString(jfilter);
46733    	qs += _getBdayQueryString(jfilter);
46734    	qs += _getProfileCreateQueryString(jfilter);
46735    	qs += _getProfileReferAndZip(jfilter, providerRefId, clientRefId, zip);
46736    	qs += _getLoyaltyQueryString(jfilter);
46737    	qs += _getVisitCountQueryString(jfilter);
46738    	
46739    	if (jfilter.find('#Was_New_Client_fl').prop('checked')) {
46740    		qs += '&wasnewclient=1';
46741    	}
46742    	
46743    	if (qs && qs.length > 0 && qs.substring(0,1) === '&') {
46744    		qs = qs.substring(1);
46745    	}
46746    	
46747    	var url = GLO.Link.WebsiteDomain + 'message/FilterClientList?' + qs;
46748    	
46749    	if (isExport) {
46750    		_exportClientList(jfilter, url);
46751    		return;
46752    	}
46753    	
46754    	var qs2 = _getStaticQueryString();
46755    	var jbtn = jfilter.find('.btnSearch');
46756    	GLO.UI.Form.beginProcessing(jbtn);
46757        
46758        setTimeout(function() { GLO.Report.TicketHistory.changeUrl(qs + qs2, 'Client List'); }, 50);
46759        
46760        _currentFilterAjax = $.ajax({ type: "POST", url: url, "cache": false, "data": jd })
46761            .success(function(data, textStatus, jqXHR) {
46762                GLO.UI.Form.resetProcessing();
46763                var jcontainer = $('#client-list-container');
46764                
46765                if (!UTIL.isEmpty(data) && $(data).attr('id') == 'client-list-container') {
46766                	jcontainer.replaceWith(data);
46767                    var clientsFound = _initClientList(true);
46768                } else {
46769                    jcontainer.html(data);
46770                    var clientsFound = 0;
46771                    GLO.Popup.Info(SA.Resource.NoResultsFound);
46772                }
46773                
46774                _clientListLoadComplete(ojpop, clientsFound);
46775            })
46776            .error(function(jqXHR, textStatus, errorThrown) {
46777                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
46778                GLO.UI.Form.resetProcessing();
46779            });
46780	}
46781	
46782	function _exportClientList(jfilter, url) {
46783		var btnExport = jfilter.find('.btnExportToExcel');
46784    	GLO.UI.Form.beginProcessing(btnExport);
46785    	
46786    	window.setTimeout(function() {
46787    		GLO.UI.Form.resetProcessing(btnExport);
46788    	}, 14500);
46789    	
46790    	url += '&ExportToExcel=1';
46791    	var childWindow = UI.openChildWindow(url, '', true);
46792	}
46793	
46794	function _initUrlClientList() {
46795		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
46796		
46797		if (!UTIL.isEmpty(highlight)) {
46798			var jhighlight = $('#' + highlight + ', .' + highlight);
46799			
46800			if (jhighlight.length > 0) {
46801				GLO.Popup.closeIfExist($('#search-summary').closest('.glopop'));
46802				UI.highlight(jhighlight, 800, 6400, true);
46803			}
46804			
46805			var qs = document.location.search;
46806			
46807			if (qs.length) {
46808				qs = qs.replace('highlight=' + highlight, '');
46809				qs = qs.replace('&&', '');
46810				
46811				if (qs.substring(0,1) === '?') {
46812					qs = qs.substring(1);
46813				}
46814				
46815				setTimeout(function() {
46816					GLO.Report.TicketHistory.changeUrl(qs, 'Client List');
46817				}, 50);
46818			}
46819		}
46820	}
46821	function _clientListLoadComplete(ojpop, clientsFound) {
46822		$('#search-summary').find('#search-summary-action').text('Loading');
46823		
46824		setTimeout(function() {
46825			$('#search-summary').find('#search-summary-dots').remove();
46826			GLO.Report.CellSummary.ClientList.init();
46827		}, 1200);
46828		
46829		setTimeout(function() {
46830			$('#search-summary').find('#search-summary-throbber').remove();
46831			$('#search-summary').find('#search-summary-label').html('Clients Loaded');
46832			_clientListLoadCompleteBigResult(ojpop, clientsFound);
46833		}, 2400);
46834		
46835		$('#be-client-list').on('click.open-tag', '.client-tag', GLO.Message.Bulk.openTag);
46836		//$('#be-client-list').find('.client-tag').attr('onclick', 'GLO.Message.Bulk.openTag(this)');
46837		
46838		_initUrlClientList();
46839	}
46840	function _clientListLoadCompleteBigResult(ojpop, clientsFound) {
46841		if (clientsFound < 2000) {
46842			return;
46843		} else if (clientsFound > 4500) {
46844			var msg = '<p>When search returns more than 5,000 clients, then only returns clients that have</p>';
46845			var li1 = '<li>first name</li>';
46846			var li2 = '<li>at least one of the following: Last Name, Mobile Phone, or Email</li>';
46847			var li3 = '<li>if all filter fields are empty then client must have Mobile Phone or Email</li>';
46848			var htm = msg + '<ul>' + li1 + li2 + li3 + '</ul>';
46849		} else if (clientsFound > 1800) {
46850			var htm = '<p>When search returns more than 2,000 clients, then only returns clients that have: phone, email, or have visited at least 1 time</p>';
46851		}
46852		
46853		$('#search-summary').append('<div id="client-search-big-result">' + htm + '</div>');
46854		ojpop.realign(); ojpop.realign();
46855	}
46856	
46857	_conBMsg.openTag = function(element) {
46858		var jtag = $(this);
46859    	var tr = jtag.closest('tr');
46860    	var thisClientId = tr.attr('client_id'), thisClientName = tr.find('.be-client-name').find('a').text();
46861    	
46862    	GLO.ClientProfile.Tag.openTagFromReport(jtag, thisClientId, thisClientName);
46863	}
46864	
46865	function _setSort() {
46866		_sortColumn = GLO.Uri.query('sort');
46867		_sortDescending = UTIL.coalesceInt(GLO.Uri.query('descending'), 0);
46868	}
46869	
46870	function _initSaveButton() {
46871		var j = $('#bulk-email-container');
46872		var jBtnSave = j.find('#btnSaveForLater').find('a');
46873		
46874		j.find('textarea, .sa-text-editor').on('keyup', function() { jBtnSave.css({ "border": "3px solid Red" }); });
46875		j.find('input:not(#Include_Text_Only_fl, #Include_Email_Only_fl), select, textarea, .sa-text-editor').on('change', function() { jBtnSave.css({ "border": "3px solid Red" }); });
46876	}
46877	
46878	_conBMsg.imageUploadComplete = function(jupload, fileName, imgId, imgSize) {
46879		var jbanner = $('#pop-preview-message').find('.banner, .custom-banner').find('img');
46880		jbanner.attr('src', GLO.Data.cdnDirectory + 'upload-folder/' + fileName);		//this does NOT refresh image so have to do replaceWith
46881		jbanner.replaceWith(jbanner.outerHTML());
46882	}
46883	
46884	_conBMsg.checkAll = function(element) {
46885		if (element.checked) {
46886			var context = '#be-client-list > tbody';
46887			
46888			var btnAll = '<span id="btnAll" class="btnAdd"><a>All Clients Below</a></span>';
46889			var btnThisPage = '<span id="btnThisPage" class="btnAdd"><a>Clients on This Page</a></span>';
46890			var btnCustomNumber = '<span id="btnCustomNumber" class="btnAdd"><a>Select Number of Clients</a></span>';
46891			
46892			var msg = '<p style="padding: 2px 8px; text-align: center;">Which Clients do you want to select?</p>';
46893			var htmBtns = '<div>' + btnAll + btnThisPage + btnCustomNumber + '</div>';
46894			var htm = '<div id="pop-select-rows">' + msg + htmBtns + '</div>';
46895			
46896			var fnCancel = function() {
46897				element.checked = false;			//$('#be-client-list').find('th.be-checkbox > input:checkbox').prop('checked', false);
46898				GLO.Popup.closeIfExist( $('#pop-select-rows').closest('.glopop') );
46899			};
46900			
46901			var jpop = GLO.Popup.Custom.openSimple(htm, 'Select which Clients?', null, fnCancel);
46902			var jbtns = jpop.find('.pop-buttons').css({ "text-align": "center" });
46903			
46904			jpop.find('#btnAll > a').click(function() { GLO.Message.Bulk.checkAllRows(element, context); });
46905			jpop.find('#btnThisPage > a').click(function() { GLO.Message.Bulk.checkThisPage(element, context); });
46906			jpop.find('#btnCustomNumber > a').click(function() { GLO.Message.Bulk.checkCustomAmount(element, context); });
46907			
46908			jbtns.find('.btnSave').remove();
46909			jbtns.find('.btnCancel').css({ "float": "none", "position": "relative", "font-size": "18px", "font-weight": "bold" });
46910		} else {
46911			_conBMsg.checkAll2(element, '#be-client-list > tbody');
46912		}
46913	}
46914	_conBMsg.checkAllRows = function(element, context) {
46915		_conBMsg.checkAll2(element, context);
46916	}
46917	_conBMsg.checkThisPage = function(element, context) {
46918		_conBMsg.checkAll2(element, context, null, true);
46919	}
46920	_conBMsg.checkCustomAmount = function(element, context) {
46921		var msg = '<p style="padding: 2px 8px; text-align: center;">How many clients do you want to select?</p>';
46922		var input = '<div> <input id="Row_Count_sr" type="number" style="width: 120px; letter-spacing: 1px; font-size: 20px; font-weight: bold;"/> </div>';
46923		var htm = '<div id="pop-select-rows-custom">' + msg + input + '</div>';
46924		
46925		var fn = function() {
46926			var numberToSelect = $('#pop-select-rows-custom').closest('.glopop').find('#Row_Count_sr').val();
46927			_conBMsg.checkAll2(element, context, numberToSelect);
46928		}
46929		
46930		var jpop = GLO.Popup.Custom.openSimple(htm, 'Select How Many Rows');
46931		GLO.Popup.Custom.singleButton(jpop, 'Select Rows').click(fn);
46932	}
46933	_conBMsg.checkAll2 = function(parentCheckBox, context, numberToSelect, isVisibleOnly) {
46934        GLO.Popup.closeIfExist( $('#pop-select-rows-custom').closest('.glopop') );
46935        GLO.Popup.closeIfExist( $('#pop-select-rows').closest('.glopop') );
46936        
46937        if (isVisibleOnly || numberToSelect > 0) {
46938        	var chk = $(context + ' input:checkbox:visible');
46939        } else {
46940        	var chk = $(context + ' input:checkbox');
46941        }
46942        
46943        var count = 0;
46944        var jcheckbox = $(parentCheckBox);
46945        var isChecked = jcheckbox.prop('checked');
46946        
46947        chk.each(function() {
46948            ++count;
46949            
46950            if (isChecked) {
46951            	if (!$(this).closest('tr').hasClass('hideX')) {
46952                	$(this).prop('checked', true);
46953                }
46954            } else {
46955                $(this).prop('checked', false);
46956            }
46957            
46958            if (numberToSelect > 0 && numberToSelect == count) {
46959            	isChecked = false;
46960            }
46961        });
46962        
46963        //setTimeout(function() { jcheckbox.prop('checked', isChecked); }, 200);			//= for some reason the 'all' checkbox doesn't stay checked.
46964    }
46965	
46966	function _getCxml(j, encode, fmt) {
46967		var forceEmailOnly = (fmt == 1), forceTextOnly = (fmt == 3 || fmt == 6);					// && GLO.Data.provider.textPackage < 10
46968		var tr, trs = _getActiveRows(forceEmailOnly, forceTextOnly);									//j.find('#be-client-list > tbody > tr');
46969		var jemail, email, cxml = '';
46970		var providerDD = j.find('#be-mobile-provider-dd');
46971		//var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value');
46972		
46973		for (var i=0; i < trs.length; i++) {
46974			if (trs.eq(i).not('.hideX').find(':checkbox').prop('checked')) {
46975				if (fmt == 3 || fmt == 6) {
46976					jemail = trs.eq(i).find('.be-phone');
46977					email = UTIL.replaceAll(UTIL.replaceAll(UTIL.replaceAll(UTIL.replaceAll(jemail.text(), '-', ''), '(', ''), ')', ''), ' ', '');
46978					//var postfix = providerDD.find('option[value="' + jemail.attr('mobile_provider_cd') + '"]').attr('email_postfix_vc');
46979					
46980					if (!UTIL.isEmpty(email)) {					// && !UTIL.isEmpty(postfix)
46981						email = email;							// + postfix
46982					} else if (!email || email.length != 10) {	// || GLO.Data.provider.textPackage < 10
46983						email = null;
46984					}
46985				} else {
46986					jemail = trs.eq(i).find('.be-email');
46987					email = UTIL.coalesce(jemail.attr('title'), jemail.text());
46988				}
46989				
46990				if (!UTIL.isEmpty(email)) {
46991					cxml += '<tr client_id="' + trs.eq(i).attr('client_id') + '" email_vc="' + email + '"/>';
46992				}
46993			}
46994		}
46995		
46996		if (cxml === '') {
46997			return '';
46998		} else {
46999			if (encode) {
47000				return UTIL.htmlEncode('<table>' + cxml + '</table>');
47001			} else {
47002				return '<table>' + cxml + '</table>';
47003			}
47004		}
47005	}
47006	
47007	function _hasRemainingMessages(j, clientCount) {
47008		var remaining = _getRemainingMessages(j);
47009		
47010		if (remaining < clientCount) {
47011			var h1 = '<h1>' + SA.Resource.NotEnoughMessages + '</h1>';
47012			var msg = '<div style="line-height: 180%;">You are about to send ' + clientCount + ' messages but only have ' + remaining + ' remaining this month</div>';
47013			
47014			if (remaining == 0) {
47015				msg += '<div style="padding-top: 20px; padding-bottom: 20px; text-align: center;">'
47016							+ '<span class="btnAdd btnUpgrade"> <a onclick="GLO.Message.Bulk.gotoUpgrade(this, \'email-blast\')">Upgrade to Send more Email and Texts</a> </span>'
47017						+ '</div>';
47018			} else {
47019				msg += '<div style="padding-top: 20px;">Do you want to:<ul style="margin: 0; text-align: center;">'
47020							+ '<li><a onclick="GLO.Message.Bulk.sendAllRemaining()">Send message to first ' + remaining + ' clients</a></li>'
47021							+ '<li><a onclick="GLO.Message.Bulk.closeNotEnough()">Select specific clients below to send message</a></li>'
47022							+ '<li> <span class="btnAdd btnUpgrade" style="margin-top: 8px;"> <a onclick="GLO.Message.Bulk.gotoUpgrade(this, \'email-blast\')">Upgrade to Send more Email and Texts</a> </span> </li>'
47023						+ '</ul> </div>';
47024			}
47025			
47026			var css = 'padding: 0 8px; letter-spacing: 1px;';
47027			var jmsg = $('<div id="pop-bulk-not-enough" style="' + css + '">' + h1 + msg + '</div>');
47028			
47029			var jpop = new GLO.Popup.Custom(jmsg).getPopup().addClass('no-persist');
47030			var jbtns = jpop.find('.pop-buttons').css({ "width": "300px" });
47031			
47032			jbtns.find('.btnSave').remove();
47033			jbtns.find('.btnCancel').css( { "float": "none", "width": "60px", "margin": "inherit", "letter-spacing": "1px" }).find('a').text(SA.Resource.Close);
47034			
47035			return false;
47036		} else {
47037			return true;
47038		}
47039	}
47040	
47041	_conBMsg.closeNotEnough = function() {
47042		GLO.Popup.close( $('#pop-bulk-not-enough').closest('.glopop') );
47043	}
47044	
47045	_conBMsg.gotoHistory = function(btn, helloback) {
47046		btn = $(btn).parent();
47047		GLO.UI.Form.beginProcessing(btn);
47048		
47049		setTimeout(function() {
47050			var url = GLO.Link.WebsiteDomain + 'message/MarketingHistory?';
47051			
47052			if (helloback) { url += 'helloback=' + helloback; }
47053			
47054			document.location = url;
47055		}, 600);
47056	}
47057	
47058	_conBMsg.gotoChangePlan = function(btn, helloback) {
47059		btn = $(btn).parent();
47060		GLO.UI.Form.beginProcessing(btn);
47061		
47062		setTimeout(function() {
47063			var url = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&highlight=message-plan';
47064			
47065			if (helloback) { url += '&helloback=' + helloback; }
47066			
47067			document.location = url;
47068		}, 600);
47069	}
47070	
47071	_conBMsg.gotoClientList = function(btn, isNewMsg, helloback) {
47072		var url = GLO.Link.WebsiteDomain + '/message/ClientList?';
47073		
47074		if (SA.Menu.isRequirePIN(url, btn)) {
47075    		return false;
47076    	}
47077    	
47078		btn = $(btn).parent();
47079		GLO.UI.Form.beginProcessing(btn);
47080		
47081		setTimeout(function() {
47082			if (isNewMsg) { url += 'openMessage=1&summaryonly=1'; }
47083			if (helloback) { url += '&helloback=' + helloback; }
47084			
47085			document.location = url;
47086		}, 600);
47087	}
47088	
47089	function _blindSend(j, fmt, fmtType) {
47090		var remaining = _getRemainingMessages(j);
47091		var jsummary = j.find('#client-list-summary');
47092		
47093		if (fmt == 3) {
47094			var fmtString = SA.Resource.Text, clientCount = UTIL.coalesceInt(jsummary.attr('client_text_count_nr'), 0);
47095		} else {
47096			var fmtString = SA.Resource.Email, clientCount = UTIL.coalesceInt(jsummary.attr('client_email_count_nr'), 0);
47097		}
47098		
47099		if (remaining == 0) {
47100			var msg = '<div>' + SA.Resource.You_have_no_remaining_messages_this_month + '</div><div>' + SA.Resource.UpgradeYourPlan + '</div>';
47101        	var fn = function() {
47102	        		document.location = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&highlight=message-package';
47103	        	};
47104        	
47105        	GLO.Popup.Confirm.open(msg, SA.Resource.CannotSendMessage, fn);
47106		} else {
47107			if (clientCount > remaining) {
47108				var msg = '<div class="main-prompt-message">You have ' + remaining + ' remaining messages this month</div>'
47109							+ '<div style="margin-top: 20px;">' + SA.Resource.Send + ' ' + fmtString + ' ' + SA.Resource.to_text + ' ' + remaining + ' ' + SA.Resource.of_the + ' ' + clientCount + ' ' + SA.Resource.clients_that_accept + ' ' + fmtString + 's?</div>'
47110						+ '</div>';
47111			} else if (clientCount == 0 && remaining > 0) {
47112				var msg = '<div class="main-prompt-message">' + SA.Resource.Send + ' ' + fmtString + ' ' + SA.Resource.to_text + ' all ' + SA.Resource.Clients + ' (up to ' + remaining + ' clients)?</div>';
47113			} else {
47114				var msg = '<div class="main-prompt-message">' + SA.Resource.Send + ' ' + fmtString + ' ' + SA.Resource.to_text + ' ' + clientCount + ' ' + SA.Resource.Clients + '?</div>';
47115			}
47116			
47117			_openConfirmBlastPopup(clientCount, fmt, msg, SA.Resource.ConfirmSend, GLO.Message.Bulk.sendBlind);
47118		}
47119	}
47120	
47121	_conBMsg.sendAllRemaining = function() {
47122		var j = $('#bulk-email-container');
47123		var remaining = _getRemainingMessages(j);
47124		var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value');
47125		var clientList = $(_getCxml(j, false, fmt)).find('tr');
47126		var cid, tbody = j.find('#be-client-list > tbody');
47127		
47128		for (var i = remaining; i < clientList.length; i++) {
47129			cid = clientList.eq(i).attr('client_id');
47130			tbody.find('tr[client_id="' + cid + '"]').find(':checkbox').prop('checked', false);
47131		}
47132		
47133		GLO.Popup.close( $('#pop-bulk-not-enough').closest('.glopop') );
47134		_conBMsg.sendAll();
47135	}
47136	
47137	function _canSendBulkMessages() {
47138		if (GLO.Provider.isPaidAccount()) {
47139			return true;
47140		}
47141		
47142		if (GLO.Data.provider.signupDetail > 499) {
47143			var upgradeLabel = 'Update Credit Card';
47144		} else {
47145			var upgradeLabel = 'Upgrade Now';
47146		}
47147		
47148		var upgradeButton = '<span style="position: absolute; left: 4px; bottom: 12px; min-height: 20px;" class="btnAdd">
47148<a onclick="GLO.Uri.gotoUri(\'/provider/profile/6\')">' + upgradeLabel + '</a></span>';
47149		var pb = '<span id="btnPreview" class="btnAdd"> <a onclick="GLO.Message.Bulk.closeAndpreview()">Preview button</a> </span>';
47150		var btnSendSample = $('#pop-preview-message-buttons #btnSendSample:visible');
47151		
47152		if (btnSendSample.length === 1) { pb = btnSendSample.outerHTML(); }
47153		
47154		var h1 = '<h1 class="friendly-msg2">Paid Package Required to Send Marketing Message</h1>';
47155		var msg1 = '<div>You must have an active paying account to send marketing messages</div>';
47156		var msg2 = '<div style="margin-top: 12px;">You can use the ' + pb + ' to send yourself a sample message</div>';
47157		var htm = '<div id="pop-paid-plan-required">' + h1 + '<div class="friendly-msg2" style="margin-bottom: 40px; text-align: left;">' + msg1 + msg2 + '</div></div>';
47158		
47159		var jpop = new GLO.Popup.Info(htm).getPopup();
47160		var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
47161		
47162		jbtns.find('.btnOk').css({ "padding-top": "7px" }).find('>a').text('Close').css({ "padding-top": "4px", "padding-bottom": "3px" });
47163		jbtns.prepend(upgradeButton);
47164		
47165		return false;
47166	}
47167	
47168	_conBMsg.closeAndpreview = function() {
47169		GLO.Popup.close($('#pop-paid-plan-required').closest('.glopop'));
47170		GLO.Message.Bulk.preview();
47171	}
47172	
47173	function _textBlastDisclaimer(isSimpleOnly) {
47174		var msg1 = 'Response rates to encourage existing clients to come back or visit for a specific reason are often positive';
47175		var msg1b = ' - make sure your text messages are appropriate, relevant, and compelling for the recipients';
47176		
47177		if (!isSimpleOnly) {
47178			var msg2 = 'Response rates for unsolicited SMS text message campaigns will almost always be low, and therefore the return on your investment will be poor';
47179			var msg3 = 'It is usually a bad idea to send text messages to people who are not already clients and it could be illegal to send unsolicited messages in the United States ';
47180			var msg3b = '<small>(based on the Telephone Consumer Protection Act)</small> and Canada <small>(see Canada\'s Anti-Spam Legislation)</small>';
47181			var msg4 = 'When customers receive a text blast message they can reply to the text with: STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, or QUIT and they will no longer receive text messages';
47182			
47183			var htm = '<p>' + msg1 + msg1b + '</p><p>' + msg2 + '</p><p>' + msg3 + msg3b + '</p><p>' + msg4 + '</p>';
47184		} else {
47185			var htm = '<p>' + msg1 + msg1b + '</p>';
47186		}
47187		
47188		htm += '<p>Text messages can only be scheduled between 9am - 8pm <small>(any messages not sent before 9pm will be sent the next morning starting at 9am)</small></p>';
47189		return '<div id="pop-text-blast-disclaimer">' + htm + '</div>';
47190	}
47191	
47192	_conBMsg.sendAll = function() {
47193		if (!_canSendBulkMessages()) { return false; }
47194		
47195		var j = $('#bulk-email-container');
47196		var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value');
47197		//var clientCount = $('#be-client-list').find('>tbody :checked').length;						//input:checkbox:checked
47198		var clientCount = $(_getCxml(j, false, fmt)).find('tr').length;
47199		
47200		if (fmt == 3) { //sms
47201			var fmtType = 'a text', fmtClass = 'accept-text';
47202		} else if (fmt == 6) { //mms
47203			var fmtType = 'a MMS', fmtClass = 'accept-text';
47204		} else {
47205			var fmtType = 'an email', fmtClass = 'accept-email';			//.be-email
47206		}
47207		
47208		if (clientCount === 0) {
47209			if (j.find('#be-client-list').length === 0) {
47210				_blindSend(j, fmt);
47211				return;
47212			}
47213			
47214			var tr = $('#be-client-list').find('>tbody .' + fmtClass);
47215			clientCount = tr.length;
47216			
47217			for (var i=0; i < clientCount; i++) {
47218				tr.eq(i).find(':checkbox').prop('checked', true);
47219			}
47220		}
47221		
47222		if (!_hasRemainingMessages(j, clientCount)) { return; }
47223		
47224		var h1 = 'Confirm Send ' + fmtType + ' to ' + clientCount + ' Clients?';
47225		var msg = '<div style="margin-bottom: 16px; padding-top: 8px;">Confirm Send ' + fmtType + ' Blast to ' + clientCount + ' Clients?</div>';
47226		
47227		_openConfirmBlastPopup(clientCount, fmt, msg, h1, GLO.Message.Bulk.sendAllConfirmed);
47228		_conBMsg.getScore();
47229	}
47230	
47231	function _previewBeforeSending(fmt, isSaving) {
47232		if (fmt == 3) {
47233			var msg1 = 'Please Review Message before Sending';
47234		} else {
47235			var msg1 = 'Please Preview Message before sending';
47236		}
47237		
47238		var msg2 = '<p>We suggest sending yourself a sample before sending message blast</p>';
47239		var htmPleasePreview = '<div id="pop-processing-please-preview"><p>' + msg1 + '</p><p>' + msg2 + '</p></div>';
47240		var fnFocus = function() {
47241			GLO.Popup.closeIfExist( $('#bulk-deliverability-score').closest('.glopop') );
47242			
47243			var btnRow = $('#be-message-body3');
47244			UI.highlight(btnRow, 1200, 16400, true);
47245		};
47246		
47247		if (isSaving) {
47248			var h1 = 'Saving Message...';
47249			var ojpop = GLO.Popup.Processing.open(htmPleasePreview, h1, fnFocus);
47250		} else {
47251			var h1 = 'Send Yourself a Sample?';
47252			var ojpop = GLO.Popup.Info.open(htmPleasePreview, h1, fnFocus);
47253		}
47254		
47255		return ojpop;
47256	}
47257	
47258	function _openConfirmBlastPopup(clientCount, fmt, msg, h1, fn) {
47259		var j = $('#bulk-email-container');
47260		var mbid = j.find('#Message_Bulk_id').val();
47261		
47262		if (fmt == 3 || fmt == 6) {
47263			var disclaimer = _textBlastDisclaimer();
47264			var fnMoreInfo = 'GLO.Message.Marketing.openHelp(15)';
47265			msg += _htmPreviewTextBlast(fmt);
47266		} else {
47267			var disclaimer = '';
47268			var fnMoreInfo = 'GLO.Message.Marketing.openHelp(14)';
47269		}
47270		
47271		if (UTIL.isEmpty(mbid)) {
47272			_previewBeforeSending(fmt, true);
47273			_conBMsg.save(false, false, true);
47274			return;
47275		} else if (clientCount > 500) {
47276			disclaimer += '<p style="margin-top: 16px;">The first 100 messages are sent when scheduled, then the next 100 messages are sent every 5 minutes</p>';
47277			disclaimer += '<p style="margin-top: 16px;">It might take a few minutes to prepare and schedule all of these messages</p>';
47278		}
47279		
47280		var htmSchedule = _getScheduleBlastHtm();
47281		var htm = '<div>' + msg + htmSchedule + disclaimer + '</div>';
47282		
47283		var ojpop = GLO.Popup.Confirm.open(htm, h1, fn);
47284		var jpop = ojpop.getPopup().css({ "background-color": "#eee" }).attr('id', 'pop-confirm-send-blast');
47285		var infoCSS = 'position: absolute; right: 8px; margin-top: -36px; z-index: 99;'
47286		var helpMoreInfo = '<span class="helpIcon2 sa-sprite" onclick="' + fnMoreInfo + '" title="Client Marketing Blats" style="' + infoCSS + '"></span>';
47287		
47288		var jbtns = jpop.find('.pop-buttons-parent').append(helpMoreInfo).find('.pop-buttons').css({ "width": "inherit", "max-width": "98%" });
47289		
47290		if (innerWidth >= 480) {
47291			var cssNo = { "width": "120px", "margin-left": "12px", "margin-top": "-6px", "padding": "4px 12px 2px", "border-radius": "12px", "border": "1px outset black", "background-color": "white" };
47292			jbtns.find('.btnNo').css(cssNo).find('>a').text('No, Not Yet').css({ "letter-spacing": "1px", "font-size": "18px", "border-bottom": 0 });
47293			jbtns.find('.btnYes').addClass('btnSave').css({ "width": "180px", "margin-right": "48px" }).find('>a').text('Yes, Send Messages').css({ "padding": "6px 12px 4px" });
47294		} else {
47295			var cssNo = { "width": "60px", "margin-left": "12px", "margin-top": "-8px", "padding": "4px 12px 2px", "border-radius": "12px", "border": "1px outset black", "background-color": "white" };
47296			jbtns.find('.btnNo').css(cssNo).find('>a').css({ "letter-spacing": "1px", "font-size": "18px", "border-bottom": 0 });
47297			jbtns.find('.btnYes').addClass('btnSave').css({ "width": "80px", "margin-right": "48px" }).find('>a').css({ "padding": "2px 20px 1px", "font-size": "18px" });
47298		}
47299		
47300		_initPopupConfirmSend(jpop, fmt);
47301		
47302		if (jpop.height() > innerHeight - 100) {
47303			ojpop.addScrollBar();
47304		}
47305	}
47306	
47307	function _htmPreviewTextBlast(fmt) {
47308		var jtop = $('#be-top');
47309		var msg = '';
47310		if (fmt == 3) {
47311			msg = jtop.find('#be-message-body-text #Text_vc').val();
47312			
47313			if (msg.length < 140) {
47314				msg += ' ';
47315			}
47316		}
47317
47318		if (fmt == 6) {
47319			msg = jtop.find('#be-message-body-mms #mms_text_vc').val();
47320
47321			if (msg.length > 1500) {
47322				msg += msg.substring(0,1500);
47323			}
47324		}
47325
47326		return '<div id="be-preview-text-message">' + msg + ' ' + jtop.find('#be-message-text-post').text() + '</div>';
47327	}
47328	
47329	function _initPopupConfirmSend(jpop, fmt) {
47330		var day = new Date();
47331		var tm = day.toGloTime(true);
47332		
47333		if (fmt === 3 || fmt === 6) {
47334			var todayAtEightPM  = new Date();
47335			todayAtEightPM.setHours(20);
47336			todayAtEightPM.setMinutes(0);
47337			
47338			var tomorrowAtNineAM  = new Date();
47339			tomorrowAtNineAM.setDate(tomorrowAtNineAM.getDate() + 1);
47340			tomorrowAtNineAM.setHours(9);
47341			tomorrowAtNineAM.setMinutes(0);
47342			
47343			if (day > todayAtEightPM) {
47344				day = new Date(day.setDate(day.getDate() + 1));
47345				tm = ' 9:00 AM';
47346			} else if (day < tomorrowAtNineAM) {
47347				tm = ' 9:00 AM';
47348			}
47349		}
47350		
47351		jpop.find("#Blast_d").datepicker({ "minDate": day }).val(day.toGloDate());
47352		
47353		var oTime = UI.timeMask('#Blast_tm');
47354		UI.setTimeMaskValue(jpop.find('#Blast_tm'), tm);
47355		
47356		setTimeout(function() {
47357			jpop.find(':focus').blur();
47358		}, 100);
47359	}
47360	
47361	function _getScheduleBlastHtm() {
47362		var css = '<style> .ui-datepicker { z-index: 9999 !important; } </style>';
47363		var label = '<label for="">Send at</label>';
47364		var htmDate = '<input type="text" id="Blast_d" name="Blast_d" pattern="[0-9]*" onclick="GLO.UI.displayDatePicker(this)"/>'
47365		
47366        if (GLO.Info.isIPhone || GLO.Info.isAndroid) {
47367            var htmTime = '<input type="time" id="Blast_tm" name="Blast_tm"/>';
47368        } else {
47369            var htmTime = '<input type="text" id="Blast_tm" name="Blast_tm"/>';
47370        }
47371		
47372		return '<div>' + label + htmDate + htmTime + css + '</div>';
47373	}
47374	
47375	_conBMsg.canSendSample = function(messageFormat) {
47376		if (messageFormat == 3 || messageFormat == 6) {
47377			if (GLO.Staff.hasText(GLO.Info.StaffId)) {
47378				return true;
47379			}
47380		} else if (GLO.Staff.hasEmail(GLO.Info.StaffId)) {
47381			return true;
47382		}
47383		
47384		return false;
47385	}
47386	
47387	_conBMsg.sendAllConfirmed = function() {
47388		_conBMsg.save(false, true);
47389	}
47390	
47391	_conBMsg.sendSample = function() {
47392		var fmt = $('#bulk-email-container').find('#Message_Format_cd').find('li.selected').attr('value');
47393		
47394		if (_conBMsg.canSendSample(fmt)) {
47395			_conBMsg.save(true);
47396		}
47397	}
47398	
47399	_conBMsg.preview = function() {
47400		_conBMsg.save(false, false, true);
47401	}
47402	
47403	_conBMsg.sendBlind = function() {
47404		_conBMsg.save(false, false, false, true);
47405	}
47406	
47407	_conBMsg.getScore = function() {
47408		var j = $('#bulk-email-container');
47409		var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value');
47410		var cxml = _getCxml(j, false, 3);
47411		
47412		if (!UTIL.isEmpty(cxml)) {
47413			var messageCount = $(cxml).find('tr').length;
47414		} else {
47415			 var messageCount = _getActiveRows(false, true).length;
47416		}
47417		
47418		var uri = GLO.Link.WebsiteDomain + 'message/BulkScore?count=' + messageCount + '&format=' + fmt;
47419		
47420		if (fmt == 3) {
47421			var body = UTIL.htmlEncode(j.find('#Text_vc').val());
47422		} else if (fmt == 6) {
47423			var body = UTIL.htmlEncode(j.find('#mms_text_vc').val());
47424		} else {
47425			var body = UTIL.htmlEncode(DOMPurify.sanitize(j.find('.sa-editor .sa-text-editor')[0].innerHTML));
47426		}
47427		
47428        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "body": body } })
47429            .success(function(data, textStatus, jqXHR) {
47430                var jd = $(data);
47431                GLO.Popup.closeIfExist($('#pop-bulk-deliverability-score').closest('.glopop'));
47432				
47433                if (jd.attr('id') === 'bulk-deliverability-score') {
47434	                var ojpop = new GLO.Popup.Custom(jd);
47435					var jpop = ojpop.getPopup().addClass('no-persist').attr('id', 'pop-bulk-deliverability-score');
47436					GLO.Popup.Custom.singleButton(jpop, 'Close');
47437					
47438					ojpop.realign(); ojpop.realign();
47439					
47440					var score = jd.find('h2 b').text();
47441					
47442					if (score < 65) {
47443						GLO.Popup.closeIfExist($('#pop-confirm-send-blast.glopop'));
47444					}
47445				}
47446            })
47447            .error(function(jqXHR, textStatus, errorThrown) {
47448                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
47449            });
47450	}
47451	
47452	function _allowSendBlast(jd) {
47453		var jwrite = $('#be-write-email-container');
47454		
47455		if (jwrite.attr('provider_var') == 'MembershipSalons' && !UTIL.parseBool(jwrite.attr('provider_allow_blast_fl'))) {
47456			var pass = $('#pop-confirm-var-pass #VAR_Password_vc').val();
47457			
47458			if (!UTIL.isEmpty(pass)) {
47459				jd.pass = pass;
47460				GLO.Popup.close($('#pop-confirm-var-pass'));
47461			} else {
47462				var htm = '<div><label for="VAR_Password_vc">Enter Password to Send Message Blast</label><input type="password" id="VAR_Password_vc"/></div>';
47463				var ojpop = GLO.Popup.Confirm.open(htm, 'Enter Password to Send Messages', GLO.Message.Bulk.sendQuick);
47464				ojpop.getPopup().attr('id', 'pop-confirm-var-pass');
47465                
47466                ojpop.realign();
47467                return false;
47468			}
47469		}
47470		
47471		return true;
47472	}
47473	
47474	_conBMsg.sendQuick = function() {
47475		var id = GLO.Uri.query('id');
47476		_sendAll(id);
47477	}
47478	
47479	function _sendAll(id, clientCount) {
47480		var uri = GLO.Link.WebsiteDomain + 'message/BulkSend?id=' + id;
47481		var j = $('#bulk-email-container');
47482		var jd = { "id": id };
47483		var locationId = j.find('#usepid').val();
47484		
47485		if (!UTIL.isEmpty(locationId)) {
47486			uri += '&usepid=' + locationId;
47487		}
47488		
47489		if (!_allowSendBlast(jd)) {
47490			return;
47491		}
47492		
47493		if (clientCount == 0 || UTIL.coalesceInt(clientCount, 999) > 100) {
47494			var small = '<i class="narrow-text">(if there are more than 100 clients being sent this message)</i>';
47495			var msg1 = '<p style="margin-top: 16px; line-height: 1.5;">The first 100 messages are sent when scheduled, then the next 100 messages are sent every 5 minutes ' + small + '</p>';
47496			var msg2 = '<p style="margin-top: 16px; line-height: 1.5;">It might take a few minutes to prepare and schedule all of these messages</p>';
47497		} else {
47498			var msg1 = '<p>';
47499			var msg2 = '<p style="margin-top: 16px; line-height: 1.5;">We are preparing and scheduling each of these messages</p>';
47500		}
47501		
47502		var htm = '<div id="pop-processing-message-blast">' + msg1 + msg2 + '</div>';
47503		
47504		GLO.UI.Form.beginProcessing(j.find('#btnSendAll'));
47505		var jprocessing = GLO.Popup.Processing.open(htm, 'Preparing & Scheduling Messages');
47506		
47507        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
47508            .success(function(data, textStatus, jqXHR) {
47509                GLO.UI.Form.resetProcessing();
47510                var warning = UTIL.coalesceInt($(data).attr('warning_cd'));
47511                
47512                if (warning > 399) {
47513                	var msg = '<div id="pop-warn-message-blast-disabled" style="margin-bottom: 12px;">' + $(data).outerHTML() + '</div>';
47514                	GLO.Popup.Warning.open(msg, 'Message Blast Disabled');
47515                } else if (warning > 199) {
47516                	var msg = '<div id="pop-confirm-message-blast-upgrade" style="margin-bottom: 12px;">' + $(data).outerHTML() + '</div>';
47517                	new GLO.Popup.Confirm(msg, function() {
47518                		document.location = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&highlight=message-package';
47519                	});
47520                } else if (warning > 0) {
47521                	var msg = '<div id="pop-warn-message-blast" style="margin-bottom: 12px;">' + $(data).outerHTML() + '</div>';
47522                	new GLO.Popup.Warning(msg);
47523                } else {
47524                	var msg = '<div style="margin-top: 4px; margin-bottom: 2px; letter-spacing: 1px; font-size: 140%;">Messages Sent</div>';
47525                	new GLO.Popup.Success(msg);
47526                	document.location = GLO.Link.WebsiteDomain + 'message/ClientList?bulk_id=' + id;
47527                }
47528                
47529                jprocessing.close();
47530            })
47531            .error(function(jqXHR, textStatus, errorThrown) {
47532                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
47533            });
47534	}
47535	
47536	function _setBlindCount(j, fmt) {
47537		var jsummary = j.find('#client-list-summary');
47538    	var remaining = _getRemainingMessages(j);
47539    	
47540    	if (fmt == 3) {
47541    		var cnt = UTIL.coalesceInt(jsummary.attr('client_text_count_nr'), 0);
47542    	} else {
47543    		var cnt = UTIL.coalesceInt(jsummary.attr('client_email_count_nr'), 0);
47544    	}
47545    	
47546    	if (cnt > remaining) {
47547    		return remaining;
47548    	} else {
47549    		return cnt;
47550    	}
47551	}
47552	
47553	function _getScheduleDate() {
47554		var jpop = $('#pop-confirm-send-blast').closest('.glopop');
47555		var day = jpop.find('#Blast_d').val();
47556		var tm = jpop.find('#Blast_tm').val();
47557		
47558		if (UTIL.isDate(day + ' ' + $.trim(tm))) {
47559			var dt = new Date(day + ' ' + $.trim(tm));
47560			return dt.toGloDate() + ' ' + dt.toGloTime();
47561		} else if (UTIL.isDate(day)) {
47562			return new Date(day).toGloDate();
47563		} else {
47564			return '';
47565		}
47566	}
47567	
47568	function _isValidSend(subject, body, fmt) {
47569		var css = 'letter-spacing: 1px; font-size: larger;';
47570		
47571		if (UTIL.isEmpty(subject) && fmt == 1) {
47572            var msg = '<h1 style="margin-bottom: 0; color: White; ' + css + '">' + SA.Resource.NoSubject + '</h1><div style="' + css + '">' + SA.Resource.PleaseIncludeSubject + '</div>';
47573            
47574            new GLO.Popup.Warning(msg, function() {
47575            	$('#bulk-email-container #Subject_vc').focus();
47576            });
47577            return false;
47578        } else if (UTIL.isEmpty(body)) {
47579        	var msg = '<h1 style="margin-bottom: 0; color: White; ' + css + '">' + SA.Resource.NoMessage + '</h1><div style="' + css + '">' + SA.Resource.Please_include_a_message + '</div>';
47580        	
47581        	new GLO.Popup.Warning(msg, function() { $('#email-body-container .sa-text-editor').focus(); });
47582            return false;
47583        }
47584        
47585        return true;
47586	}
47587	
47588	_conBMsg.save = function(sendSample, sendAll, displayPreview, sendBlind) {
47589		var j = $('#bulk-email-container');
47590		var jpopPreview = $('#pop-preview-message').closest('.glopop');
47591		var mbid = j.find('#Message_Bulk_id').val();
47592		var fmt = j.find('#Message_Format_cd').find('li.selected').attr('value');
47593		var mmsAttachmentName = '';
47594		var smsSegments = 1;
47595		var mmsPrice = 0.035;
47596		var locationId = j.find('#usepid').val();
47597		
47598		if (fmt == 1) {
47599			var subject = j.find('#Subject_vc').val();
47600			var body = j.find('#email-body-container .sa-text-editor')[0].innerHTML;			//j.find('#Body_vc').val();
47601			body = UTIL.htmlEncode(DOMPurify.sanitize(body));
47602			var up = j.find('#Include_Username_Password_fl').prop('checked');
47603		} else if (fmt == 6) { //mms
47604			var subject =  null, up = null;
47605			var body = UTIL.htmlEncode(j.find('#mms_text_vc').val());
47606			mmsAttachmentName = j.find('#mms-uploaded-file-name').text();
47607			var resultTuple = GLO.Message.Bulk.calcMmsPartsAndPrice(body);
47608			smsSegments = resultTuple.item1;
47609			mmsPrice = resultTuple.item2;
47610		} 
47611		else { //sms
47612			var subject =  null, up = null;
47613			var body = UTIL.htmlEncode(j.find('#Text_vc').val());
47614		}
47615		
47616		if (!_isValidSend(subject, body, fmt)) {
47617			return;
47618		/* } else if (sendAll && UTIL.isEmpty(mbid)) {
47619			sendAll = false;
47620			displayPreview = true;
47621			//jpopProcessing = GLO.Popup.Processing.open('Please Preview Message before sending', 'Saving Message...').getPopup();
47622		*/
47623		}
47624        
47625        var isDisplayEmailPreview = (displayPreview && fmt == 1);
47626        var cxml = _getCxml(j, true, fmt);
47627        var clientCount = $(_getCxml(j, false, fmt)).find('tr').length
47628        var dtSchedule = _getScheduleDate();
47629        var jd = { "Message_Bulk_id": mbid, "subject": subject, "body": body, "Include_Username_Password_fl": up, "Message_Format_cd": fmt
47630        			, "Send_Sample_fl": UTIL.parseBool(sendSample), "Preview_fl": isDisplayEmailPreview, "Send_Blind_fl": sendBlind, "schedule_dt": dtSchedule, 
47631					"client_xml": cxml, "mms_image_filename_vc": mmsAttachmentName, "sms_segments": smsSegments, "mms_price": mmsPrice };
47632        
47633        if (!_isValidScheduleDate(dtSchedule, fmt)) { return false; }
47634        
47635        if (UTIL.parseBool(sendBlind)) { jd.Send_Blind_Count_nr = _setBlindCount(j, fmt); }
47636        
47637        var uri = GLO.Link.WebsiteDomain + 'message/ClientList';
47638		GLO.UI.Form.beginProcessing(j.find('.btnSave'));
47639		
47640		if (!UTIL.isEmpty(locationId)) {
47641			uri += '?usepid=' + locationId;
47642		}
47643
47644		if (sendSample) {
47645			GLO.UI.Form.beginProcessing(jpopPreview.find('#btnSendSample'));
47646		} else {
47647			GLO.UI.Form.beginProcessing(jpopPreview.find('#btnSendAll'));
47648		}
47649		
47650		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
47651            .success(function(data, textStatus, jqXHR) {
47652                GLO.UI.Form.resetProcessing();
47653                GLO.Popup.closeIfExist(jpopPreview);
47654                
47655                _initSaveButton();
47656                
47657                var j = $('#bulk-email-container #btnSaveForLater').find('a').css({ "border-color": "transparent" });
47658                var jdata = $(data);
47659                
47660                if (UTIL.isEmpty(mbid)) {
47661					if (jdata.length > 3) {
47662						mbid = jdata.eq(3).attr('message_bulk_id')
47663					} else {
47664						mbid = jdata.attr('message_bulk_id');
47665					}
47666					
47667					var jmbid = $('#bulk-email-container #Message_Bulk_id').val(mbid);
47668				}
47669				
47670				if (sendAll || sendBlind) {
47671					_sendAll(mbid, clientCount);
47672				} else if (sendSample) {
47673					var success_htm = '<div class="friendly-msg4"><h1 class="friendly-msg4">Changes Saved</h1><div class="friendly-msg4" style="margin-bottom: 20px; font-size: large;">Sample Sent to You</div></div>';
47674					new GLO.Popup.Info(success_htm);
47675					
47676					_conBMsg.getScore();
47677				} else if (displayPreview) {
47678					if (isDisplayEmailPreview) {
47679						_displayPreview(data);
47680						_conBMsg.getScore();
47681					}
47682					
47683					if (GLO.Popup.closeIfExist($('#pop-processing-please-preview').closest('.glopop'))) {
47684						_previewBeforeSending(fmt, false);
47685					}
47686				} else {
47687					var success_htm = '<div class="friendly-msg4"><h1 class="friendly-msg4">Changes Saved</h1><div class="friendly-msg4" style="margin-bottom: 20px; font-size: large;">Changes Saved</div></div>';
47688					new GLO.Popup.Info(success_htm);
47689					_conBMsg.getScore();
47690				}
47691				
47692				if (UTIL.isEmpty(GLO.Uri.query('id'))) {
47693					//GLO.Uri.query('id', mbid);			//window.history.pushState('Client Marketing', 'Client Marketing', '/message/ClientList?id=' + mbid);
47694					var newUrl = GLO.Uri.addQueryKeyAndValue(location.href, 'id=' + mbid);
47695					window.history.pushState('Message Blast', 'Client Marketing', newUrl);
47696				}
47697            })
47698            .error(function(jqXHR, textStatus, errorThrown) {
47699                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
47700            });
47701	}
47702	
47703	function _isValidScheduleDate(dtSchedule, fmt) {
47704		if (fmt == 3) {
47705			var day = new Date(dtSchedule);
47706			
47707			var dayAtEightPM  = new Date(day);
47708			dayAtEightPM.setHours(20);
47709			dayAtEightPM.setMinutes(0);
47710			
47711			var dayAtNineAM  = new Date(day);
47712			dayAtNineAM.setDate(dayAtNineAM.getDate());
47713			dayAtNineAM.setHours(9);
47714			dayAtNineAM.setMinutes(0);
47715			
47716			var fn = function() { $('#pop-confirm-send-blast #Blast_tm').focus(); }
47717			
47718			if (day > dayAtEightPM) {
47719				var msg = 'Cannot Send Texts After 8 PM';
47720				GLO.Popup.Warning.open(msg, 'Invalid Time', fn);
47721				return false;
47722			} else if (day < dayAtNineAM) {
47723				var msg = 'Cannot Send Texts Before 9 AM';
47724				GLO.Popup.Warning.open(msg, 'Invalid Time', fn);
47725				return false;
47726			}
47727		}
47728		
47729		return true;
47730	}
47731	
47732	function _displayPreview(data) {
47733		if (GLO.Info.isMobile() || innerWidth < 500) {
47734			var style = '', btnSample = 'Send Sample', btnSendAll = 'Send', h1Text = 'Preview';
47735			var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;';
47736		} else {
47737			var btnSample = 'Send Sample (to me)', btnSendAll = 'Send Message', h1Text = 'Email Preview';
47738			var style = '';				//' style="width: ' + parseInt(innerWidth * .9) + 'px;"'
47739			var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;';
47740		}
47741		
47742		var htmlButtons = '<div id="pop-preview-message-buttons">'
47743							+ '<span id="btnSendSample" class="btnSendSample btnAdd"> <a onclick="GLO.Message.Bulk.sendSample()">' + btnSample + '</a> </span>'
47744							+ '<span class="btnOk btn">
47744<a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>'
47745							+ '<span id="btnSendAll" class="btnAdd btnAction1"> <a onclick="GLO.Message.Bulk.sendAll()">' + btnSendAll + '</a> </span>'
47746						+ '</div';
47747		
47748		var uploadHtm = $('#be-message-widgets .sa-upload').outerHTML();
47749		
47750		var h1 = '<h1 style="position: relative; margin-bottom: 0;">'
47751					+ uploadHtm 		//+ '<span id="btnChangeImage" class="btnAdd"> <a onclick="GLO.Message.Bulk.changeImage()">Change Image</a> </span>'
47752					+ '<span style="' + h1style + '">' + h1Text + '</span>'
47753				+ '</h1>';
47754		
47755		var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>');
47756		GLO.Mobile.formatExternalLinksForIos(jhtm);
47757		
47758		var ojpop = new GLO.Popup.Custom(jhtm);
47759		var jpop = ojpop.getPopup().addClass('no-persist').css({ "top": "10px" });
47760		
47761		jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons);
47762		jpop.find('.msg').css({ "max-width": "900px" });
47763		
47764		var h1 = jpop.find('h1');
47765		h1.find('form').css({ "float": "left" });
47766		h1.find('input');
47767		
47768		SA.Uploader.init(jpop, GLO.Message.Bulk.imageUploadComplete);
47769		
47770		if (!GLO.Info.isMobile()) {
47771			var jscroll = jpop.find('.msg');
47772			var width = jscroll.width() + 12;
47773			
47774			if (width < 500 && innerWidth >= 500) {
47775				width = 500;
47776			}
47777			
47778			jscroll.width(width);
47779		}
47780		
47781		setTimeout(ojpop.realign, 800);		//= displays scroll bar on popup after email image has loaded. //toDo: run on-image-load (not setTimeout).
47782	}
47783
47784	_conBMsg.initMMSIndicators = function() {
47785		//character count display for mms content
47786		$('#mms_text_vc').keyup(function() {
47787    
47788	        var characterCount = $('#mms_text_vc').val().length,
47789		        current = $('#mms-current'),
47790		        maximum = $('#mms-maximum'),
47791		        theCount = $('#mms-char-count');
47792    
47793	        current.text(characterCount);
47794  
47795			//800 characters mms limit, warn after 600 chars
47796	        if (characterCount >= 600) {
47797		        maximum.css('color', '#8f0001');
47798		        current.css('color', '#8f0001');
47799		        theCount.css('font-weight','bold');
47800	        } else {
47801		        current.css('color', '#666');
47802		        maximum.css('color','#666');
47803		        theCount.css('font-weight','bold');
47804	        }
47805
47806			GLO.Message.Bulk.replaceMmsWithGsmEquivalent();
47807			GLO.Message.Bulk.displayMmsPartsAndPrice();
47808        });
47809	}
47810
47811	_conBMsg.destroyMMSIndicators = function() {
47812
47813		$('#mms_text_vc').unbind();
47814	}
47815
47816	_conBMsg.launchMMSPreview = function(event) {
47817
47818		//validate if message is present
47819		var fmt = $('#Message_Format_cd').find('li.selected').attr('value');
47820		var subject =  null, up = null;
47821		var body = UTIL.htmlEncode($('#mms_text_vc').val());
47822		if (!_isValidSend(subject, body, fmt)) {
47823			return;
47824		}
47825
47826		mmsPreviewModal = $('#mms-preview-iphone-container').modal();
47827		// var jModal = $('#simplemodal-container #mms-preview-iphone-container');
47828		var h = $(window).height() * 0.8;
47829        var w = $(window).width() * 0.8;
47830        
47831        $.modal.update(h,w);
47832        $(window).resize(); 
47833		$('.modalCloseImg').css("margin-top","20px");
47834		$('.modalCloseImg').css("margin-right","20px");
47835		$('.modalCloseImg').on("click",function() { GLO.Message.Bulk.closeMMSImageUpload(); });
47836		
47837		//set the preview image
47838		var img_path = $('#mms-image-path').val();
47839		if (img_path) {
47840			$('#mms-preview-image').removeClass('hide');
47841			//assign image path to mms preview image
47842			document.querySelector('#mms-preview-image').src = img_path;
47843		}
47844		else {
47845			$('#mms-preview-image').addClass('hide');
47846		}
47847		//set the preview message
47848		var message = $('#mms_text_vc').val();
47849		//get message text from text area
47850		$('#mms-preview-message').text(message);
47851
47852		if (GLO.Info.isMobile()) {
47853			$('#simplemodal-container').draggable({disable:true});
47854		}
47855		$('#simplemodal-container').css("overflow-y","auto");
47856	
47857		// GLO.Mobile.formatExternalLinksForIos(jhtm);
47858	}
47859
47860	
47861	_conBMsg.deleteClients = function() {
47862		var j = $('#be-client-list');
47863		var cnt = j.find('input:checkbox:checked').length;
47864		
47865		if (cnt === 0) {
47866			var fn = null, h1 = 'No Client Selected';
47867			var msg = 'To delete clients please first check the box to the left of the client\'s name';
47868		} else {
47869			var h1 = 'Confirm Delete';
47870			var msg = 'Delete ' + UTIL.makePlural(cnt, 'Client') + '?';
47871			var fn = GLO.Message.Bulk.deleteClientsConfirmed;
47872		}
47873		
47874		GLO.Popup.Confirm.open(msg, h1, fn);
47875	}
47876	
47877	_conBMsg.deleteClientsConfirmed = function() {
47878		var j = $('#be-client-list');
47879		var uri = GLO.Link.WebsiteDomain + 'message/ClientDelete';
47880		var cnt = 0, xml = '<table>', trs = j.find('tbody tr');
47881		
47882		for (var i=0; i < trs.length; i++) {
47883			if (trs.eq(i).find('input:checkbox').prop('checked')) {
47884				xml += '<tr client_id="' + trs.eq(i).attr('client_id') + '"/>';
47885			}
47886		}
47887		
47888		var jd = { "client_xml": UTIL.htmlEncode(xml + '</table>') };
47889		GLO.UI.Form.beginProcessing(j.find('.btnDelete'));
47890		
47891        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
47892            .success(function(data, textStatus, jqXHR) {
47893                var msg = UTIL.pluralLabel(cnt, 'Client') + ' Deleted';
47894                
47895                GLO.Popup.Success.open(msg, 'Clients Deleted');
47896                GLO.UI.Form.resetProcessing();
47897                GLO.Message.Bulk.filter();
47898            })
47899            .error(function(jqXHR, textStatus, errorThrown) {
47900                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
47901            });
47902	}
47903
47904	_conBMsg.launchMMSImageUpload = function(event) {
47905
47906		mmsImageUploadModal = $('#mms-manage-image-container').modal();
47907		var jModal = $('#simplemodal-container #mms-manage-image-container');
47908		var h = $(window).height() * 0.8;
47909        var w = $(window).width() * 0.8;
47910        
47911        $.modal.update(h,w);
47912        $(window).resize(); 
47913		$('.modalCloseImg').css("margin-top","20px");
47914		$('.modalCloseImg').css("margin-right","20px");
47915		$('.modalCloseImg').on("click",function() { GLO.Message.Bulk.closeMMSImageUpload(); });
47916		
47917		if (GLO.Info.isMobile()) {
47918			$('#simplemodal-container').draggable({disable:true});
47919		}
47920		$('#simplemodal-container').css("overflow-y","auto");
47921
47922		$('#mms-file-upload-controls').removeClass('hide');
47923		$('#mms-uploaded-file-container').addClass('hide');
47924
47925	}
47926
47927	_conBMsg.closeMMSImageUpload = function() {
47928
47929		//clear the image display
47930		document.querySelector('#mms-image').src ='';
47931		// close the modal
47932		$.modal.close();	
47933
47934	}
47935
47936	_conBMsg.removeMMSUploadedImage = function() {
47937
47938		//reset MMS upload controls
47939		$('#mms-image-path').val('');
47940		$('#mms-uploaded-file-name').text('');
47941		$('#mms-file-upload-controls').removeClass('hide');
47942		$('#mms-uploaded-file-container').addClass('hide');
47943
47944	}
47945
47946	_conBMsg.uploadMMSImageAndResize = function () {
47947		//define the width to resize e.g 180px
47948		var resize_width = 600;//without px
47949
47950		//get the image selected
47951		var item = document.querySelector('#uploader').files[0];
47952
47953		//create a FileReader
47954		var reader = new FileReader();
47955
47956		//image turned to base64-encoded Data URI.
47957		reader.readAsDataURL(item);
47958		reader.name = item.name;//get the image's name
47959		reader.size = item.size; //get the image's size
47960		reader.onload = function(event) {
47961			var img = new Image();//create a image
47962			img.src = event.target.result;//result is base64-encoded Data URI
47963			img.name = event.target.name;//set name (optional)
47964			img.size = event.target.size;//set size (optional)
47965			img.onload = function(el) {
47966				var elem = document.createElement('canvas');//create a canvas
47967
47968				//scale the image to 600 (width) and keep aspect ratio
47969				var scaleFactor = resize_width / el.target.width;
47970				elem.width = resize_width;
47971				elem.height = el.target.height * scaleFactor;
47972
47973				//draw in canvas
47974				var ctx = elem.getContext('2d');
47975				ctx.drawImage(el.target, 0, 0, elem.width, elem.height);
47976
47977				//get the base64-encoded Data URI from the resize image
47978				var srcEncoded = ctx.canvas.toDataURL('image/jpeg', 1);
47979
47980				//clear the image display
47981				document.querySelector('#mms-image').src ='';
47982
47983				//assign it to thumb src
47984				document.querySelector('#mms-image').src = srcEncoded;
47985
47986				GLO.Message.Bulk.saveMMSImage(srcEncoded,resize_width);
47987			}
47988		}
47989	}		
47990
47991	_conBMsg.saveMMSImage = function(data,width) {
47992
47993		//remove the attached handler
47994		$('#btnSaveMMSImage').off("click");
47995		
47996		var jcontainer = $('#uploader');
47997		
47998		//reset error
47999		$('#mmsImageUploadErrorMessage').addClass('hide');
48000
48001		var fnCallback = function(jcontainer, fileName, imgId, imgSize) {
48002			if (fileName!=null && fileName.length > 0) {
48003				var img_path = GLO.Data.cdnDirectory + 'upload-folder/' + fileName;
48004				// console.log(img_path);
48005
48006				$('#mms-image-path').val(img_path);
48007				$('#mms-file-upload-controls').addClass('hide');
48008				$('#mms-uploaded-file-container').removeClass('hide');
48009				//display the file name																																																																																											
48010				$('#mms-uploaded-file-name').text(fileName);
48011
48012				//close the modal
48013				// $('.simplemodal-close').click();	
48014			}
48015			else {
48016				//display error
48017				$('#mmsImageUploadErrorMessage').removeClass('hide');
48018			}
48019		}
48020		
48021		if (SA.Uploader.uploadImage(data, 'jpg', width, jcontainer, fnCallback)) {
48022			return true;
48023		}
48024	}
48025	
48026	//replace common non-GSM characters with GSM equivalents
48027	_conBMsg.replaceMmsWithGsmEquivalent = function() {
48028		let messageBody = $('#mms_text_vc').val();
48029		var result = UTIL.mmsReplaceNonGsmWithGsmChars(messageBody);
48030		$('#mms_text_vc').val(result);
48031	}
48032
48033	//calculates no. of segments in mms message and approx. price
48034	_conBMsg.calcMmsPartsAndPrice = function(messageBody) {
48035
48036		const mmsBasePrice = 0.035; //in dollars
48037		// parts, price
48038		let resultTuple = { item1: 1, item2: mmsBasePrice };
48039		let numOfParts = 1;
48040		let mmsPostFix = 'Reply STOP to opt out';
48041
48042		if (!UTIL.isUnicodeMms(messageBody)) { //gsm
48043			numOfParts = (messageBody.length + mmsPostFix.length) <= 160 ? 1 : Math.ceil((messageBody.length + mmsPostFix.length) / 153);
48044		}
48045		else { //unicode
48046			numOfParts = (messageBody.length + mmsPostFix.length) <= 70 ? 1 : Math.ceil((messageBody.length + mmsPostFix.length) / 67);
48047		}
48048
48049		resultTuple = { item1: numOfParts, item2: (numOfParts * mmsBasePrice) };
48050
48051		return resultTuple;
48052	}
48053
48054	_conBMsg.displayMmsPartsAndPrice = function() {
48055
48056		let messageBody = $('#mms_text_vc').val();
48057		var resultTuple = GLO.Message.Bulk.calcMmsPartsAndPrice(messageBody);
48058
48059		var result = resultTuple.item1 + " SMS / " + (resultTuple.item2 * 100).toFixed(2) + '\u00A2  cents per message'; //to cents
48060		$('#mms-price').text(result);
48061	}
48062
48063	return _conBMsg;
48064})();
48065
48066
48067GLO.Message.Marketing = (function() {
48068	function _conMarketing() { }
48069	
48070	_conMarketing.initUpgradeEmail = function(hasValidCreditCard) {
48071		if (!hasValidCreditCard) {
48072			var j = $('#email-option-container');
48073			
48074			//Override save functions
48075				j.find('#Text_Package_fl').attr('onchange', 'GLO.Message.Marketing.displayPleaseAddCreditCard(this)');
48076				j.find('#email-option-list').find('.btnSave > a').attr('onclick', 'GLO.Message.Marketing.displayPleaseAddCreditCard(this)');
48077		}
48078		
48079		//$('#text-package-edit-container').find(':radio').on('click', GLO.Message.Marketing.changeTextPackage);
48080		_initOptIn();
48081		_initMessagePlan();
48082		_initUrlActions();
48083	}
48084	
48085	function _initOptIn() {
48086		var plan = $('#Message_Plan_cd').val();
48087		var j = $('#text-package-edit-container').addClass('message-plan-' + plan);
48088		
48089		if ($('#text-optin-phoneco-optional').length) {			//= has valid cc or is VAR
48090			j.addClass('is-paid-account');
48091		} else {
48092			j.addClass('is-not-paid-account');
48093		}
48094	}
48095	function _initMessagePlan() {
48096		var j = $('#message-opt-in-and-plan');
48097		var jplan = j.find('#Message_Plan_cd');
48098		var trpackage = j.find('#message-plan-body-package tr.is-current-package');
48099		//var textPackage = j.find(':radio[name="Text_Package_cd"]:checked').val();
48100		
48101		if (trpackage.length) {
48102			var emailCount = trpackage.find('.email-option-email').text();
48103			var textCount = trpackage.find('.email-option-text').text();
48104			var htmOption = '<option class="current-plan" value="package" selected="selected">Package: ' + emailCount + ' Email / ' + textCount + ' Text</option>';
48105			
48106			jplan.find('option[value="package"]').replaceWith(htmOption);
48107		}
48108		
48109		$('#message-plan-tab-' + jplan.val() + ' > a').click();
48110	}
48111	
48112	_conMarketing.displayPleaseAddCreditCard = function() {
48113		var fn = function() { document.location = GLO.Link.WebsiteDomain + 'provider/profile/6'; };
48114		var msg = '<div class="friendly-msg2">Please add a valid credit card before adding an email blast package</div>';
48115    	new GLO.Popup.Warning(msg, fn);
48116	}
48117	
48118	function _initUrlActions() {
48119    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
48120    	var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
48121    	
48122    	if (!UTIL.isEmpty(open)) {
48123    		if (open === 'help') {
48124    			var page = UTIL.coalesceInt(GLO.Uri.hash('page'), 0);
48125    			GLO.Message.Marketing.openHelp(page);
48126    		}
48127    	}
48128    	
48129    	if (highlight.toLowerCase() === 'message-plan') {
48130			_conMarketing.gotoMessagePlan();
48131		} else if (highlight.toLowerCase() === 'message-package') {
48132			_conMarketing.gotoMessagePackage();
48133		} else if (highlight.toLowerCase() === 'text-option') {
48134			var jtext = $('#email-option-help-extra-text-package');
48135			UI.highlight(jtext, 1200, 6400, true);
48136		} else if (!UTIL.isEmpty(highlight)) {
48137			var jhighlight = $('#' + highlight + ', .' + highlight);
48138			
48139			if (jhighlight.length > 0) {
48140				UI.highlight(jhighlight, 800, 6400, true);
48141			}
48142		}
48143		
48144		GLO.Info.displayHelloBarBackToAdvanced();
48145    }
48146	
48147	_conMarketing.setMessagePlan = function(msgPlanValue) {
48148		$('#Message_Plan_cd').val(msgPlanValue).change();
48149	}
48150	_conMarketing.changeMessagePlan = function(selectElement) {
48151		var jPlanCurrent = $('#Message_Plan_cd').find('option.current-plan');
48152		
48153		if (selectElement.value == 'package') {
48154			$('#message-plan-tab-package > a').click();
48155			
48156			function fn() {
48157				var jhigh = $('#email-option-list');
48158				UI.highlight(jhigh, 600, 5000, true);
48159			}
48160			
48161			GLO.Popup.Info.openSimple('Select a Message Package', 'Change Message Plan', fn);
48162			var textPackage = null, emailPackage = null;			//, isRemovePackage = false;
48163		} else {
48164			if (selectElement.value == 'free') {
48165				var emailPackage = 0;
48166				
48167				if (_canTurnOnTextPackage()) {
48168					var textPackage = 20;
48169				} else {
48170					var textPackage = 0;
48171				}
48172			} else if (selectElement.value == 'pay-as-use') {
48173				var textPackage = 50, emailPackage = 100;
48174			}
48175			
48176			//var isRemovePackage = (jPlanCurrent.val() == 'package');
48177		}
48178		
48179		jPlanCurrent.prop('selected', true);
48180		
48181		/* if (isRemovePackage) {
48182			$('#email-option-list').find('tbody tr:first .btnSave > a').click();
48183			//_conMarketing.changeTextPackage(textPackage);
48184		} */
48185		
48186		if (textPackage && textPackage != $('#message-opt-in').find(':radio[name="Text_Package_cd"]').val()) {
48187			//$('#message-opt-in').find(':radio[name="Text_Package_cd"][value="' + textPackage + '"]').click();
48188			GLO.Message.Marketing.changeTextPackage(textPackage);
48189		}
48190		
48191		if (!UTIL.isEmpty(emailPackage) && _canChangeMessagePackage()) {
48192			GLO.Message.Marketing.changeEmailPackageConfirmed(emailPackage);
48193		}
48194	}
48195	
48196	function _canTurnOnTextPackage() {
48197		var epackage = $.trim($('#email-option-list').find('.check-mark').closest('tr').attr('package_upgrade_cd'));
48198		
48199		if (!GLO.Provider.isPaidAccount()) {
48200			var fn = function() { document.location = document.location.protocol + '//' + location.host + '/provider/profile/6'; };
48201			
48202			var h1 = '<h1 class="friendly-msg2">Requires Paid Package</h1>';
48203			
48204			if (GLO.Data.provider.signupDetail > 499) {
48205				var msg = '<p>To enable this option please use a valid credit card</p>';
48206			} else {
48207				var msg = '<p>To enable this option please select a paid ' + GLO.Info.getScheduleAnyoneHtm(
48207) + ' package</p>';
48208			}
48209			
48210			new GLO.Popup.Info('<div>' + h1 + '<div class="friendly-msg2">' + msg + '</div></div>', fn);
48211			return false;
48212		/* Mar 2019: only requires paid package
48213		} else if (epackage === '' && !GLO.Provider.isValidGoldPackage()) {
48214			var fn = function() { GLO.Message.Marketing.gotoMessagePackage(true); };
48215			var h1 = '<h1 class="friendly-msg2">Requires Paid Message Package</h1>';
48216			var msg1 = '<p>To enable this option please select a paid message package</p>';
48217			var msg2 = '<p>' + GLO.Info.getScheduleAnyoneHtm() + ' offers paid email from $5/month - $125/month</p>';
48218			
48219			new GLO.Popup.Info('<div>' + h1 + '<div class="friendly-msg2">' + msg1 + msg2 + '</div></div>', fn);
48220			return false;
48221		*/
48222		} else {
48223			return true;
48224		}
48225	}
48226	
48227	_conMarketing.saveTextPackage = function(textPackage) {
48228		var url = GLO.Link.Page.Provider.Home + 'manage/TextPackage?textPackage=' + textPackage;
48229    	
48230        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
48231            .success(function(data, textStatus, jqXHR) {
48232                new GLO.Popup.Success('Text Configuration Changed');
48233                var rdo = $('#text-package-edit-container :radio');
48234                
48235                for (var i=0; i < rdo.length; i++) {
48236                	if (rdo.eq(i).val() == textPackage) {
48237                		rdo.eq(i).attr('checked', 'checked');
48238                	} else {
48239                		rdo.eq(i).removeAttr('checked');
48240                	}
48241                }
48242                
48243                if (textPackage > 0) {
48244                	$('#Text_Package_fl').prop('checked', true);
48245                } else {
48246                	$('#Text_Package_fl').prop('checked', false);
48247                }
48248                
48249                var htm = '<div id="pop-processing-save-text"> <p>Your change has been saved</p> <p>Re-loading your new settings...</p> </div>';
48250                GLO.Popup.Processing.open(htm, 'Text Configuration Changed');
48251                
48252                setTimeout(function() {
48253                	location.reload();
48254                }, 800);
48255            })
48256            .error(function(jqXHR, textStatus, errorThrown) {
48257                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48258            });
48259	}
48260	
48261	_conMarketing.changeTextFlag = function(element, event) {
48262		var isYes = $(element).is(':checked');
48263		
48264		if (isYes) {
48265			if (_canTurnOnTextPackage()) {
48266				var textPackage = $('#text-package-edit-container').attr('original_text_package_cd');
48267				
48268				if (textPackage == 0) { textPackage = 20; }
48269				
48270				_conMarketing.saveTextPackage(textPackage);
48271			} else {
48272				$(element).prop('checked', false);
48273			}
48274		} else {
48275			_conMarketing.saveTextPackage(0);
48276		}
48277	}
48278	
48279	_conMarketing.selectTextPackage = function(radioElement) {
48280		var j = $('#text-package-edit-container');
48281		var originalPackage = UTIL.coalesceInt(j.attr('original_text_package_cd'), 0);
48282		var textPackage = radioElement.value;
48283		
48284		j.find(':radio[name="Text_Package_cd"][value="' + originalPackage + '"]').prop('checked', true);
48285		
48286		setTimeout(function() {
48287			$('#text-package-edit-container').find(':radio[name="Text_Package_cd"][value="' + originalPackage + '"]').prop('checked', true);
48288		}, 800);
48289		
48290		_conMarketing.openTextOptInHelp(textPackage, originalPackage, true);
48291	}
48292	_conMarketing.changeTextPackage = function(textPackage) {
48293		//var textPackage = element.value;
48294		
48295		if (textPackage == 0 || _canTurnOnTextPackage()) {
48296			_conMarketing.saveTextPackage(textPackage);
48297		}
48298	}
48299	
48300	_conMarketing.gotoMessagePlan = function() {
48301		GLO.Popup.close();
48302		UI.highlight($('#message-plan-container'), 1200, 4800, true);
48303	}
48304	_conMarketing.gotoMessagePackage = function(ignoreFreeOption) {					//great animation example!
48305		GLO.Popup.close();
48306		$('#message-plan-tab-package > a').click();			//=open tab
48307		
48308		var tblPackages = $('#email-option-list');
48309		UI.highlight(tblPackages, 1200, 4800, true);
48310	}
48311	
48312	function _canChangeMessagePackage() {
48313		if (GLO.Provider.isPaidAccount()) {
48314			return true;
48315		}
48316		
48317		if (GLO.Data.provider.signupDetail > 499) {
48318			var upgradeLabel = 'Update Credit Card';
48319		} else {
48320			var upgradeLabel = 'Upgrade Now';
48321		}
48322		
48323		var upgradeButton = '<span style="position: absolute; left: 4px; bottom: 12px; min-height: 20px;" class="btnAdd">
48323<a onclick="GLO.Uri.gotoUri(\'/provider/profile/6\')">' + upgradeLabel + '</a></span>';
48324		
48325		var h1 = '<h1 class="friendly-msg2">Paid Package Required to Send Marketing Message</h1>';
48326		var msg = '<div>You must have an active paying account to send marketing messages</div>';
48327		var htm = '<div>' + h1 + '<div class="friendly-msg2">' + msg + '</div></div>';
48328		
48329		var jpop = new GLO.Popup.Info(htm).getPopup();
48330		var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
48331		
48332		jbtns.find('.btnOk').css({ "padding-top": "7px" }).find('>a').text('Close').css({ "padding-top": "4px", "padding-bottom": "3px" });
48333		jbtns.prepend(upgradeButton);
48334		
48335		return false;
48336	}
48337	
48338	_conMarketing.changeEmailPackage = function(btn) {
48339		if (!_canChangeMessagePackage()) { return false; }
48340		
48341		var btn = $(btn).parent();
48342		var j = $('#email-option-list');
48343		var jcurrent = j.find('.check-mark').closest('tr');
48344		var jnew = btn.closest('tr');
48345		
48346		var currentPrice = UTIL.coalesceMoney(jcurrent.find('.email-option-price').text().replace('$', ''), 0);
48347		var newPrice = UTIL.coalesceMoney(jnew.find('.email-option-price').text().replace('$', ''), 0);
48348		var package_upgrade_cd = jnew.attr('package_upgrade_cd');
48349		
48350		var emailCount = '<b class="narrow-text" style="color: inherit;">' + jnew.find('.email-option-email').text() + ' Email Blast / Normal Texts</b>';
48351		var textCount = '<b class="narrow-text" style="color: inherit;">' + jnew.find('.email-option-text').text() + ' Text Blast</b></p>';
48352		var newPlan = '<p style="margin-left: 12px; line-height: 1.4; font-size: larger;">' + emailCount + ' or ' + textCount + '</p>';
48353		var combo = '<p style="margin-left: 24px; line-height: 1.4; letter-spacing: 0;">(or combination of Normal Texts / Email Blasts and Text Blasts)</p>';
48354		
48355		if (newPrice > currentPrice) {
48356			var msg = '<p style="line-height: 1.4;">Do you want to upgrade your <b>Message Package</b> to:</p>' + newPlan + combo
48357						+ '<p style="margin-top: 24px; margin-bottom: 12px;">You will be billed ' + UTIL.displayMoney(newPrice - currentPrice) + ' today</p>'
48358						+ '<p>Your monthly price will be ' + UTIL.displayMoney(newPrice) + '</p>';
48359		} else if (newPrice < currentPrice) {
48360			var msg = '<p style="line-height: 1.4;">Do you want to downgrade your <b>Message Package</b> to:</p>' + newPlan + combo;
48361			
48362			if (newPrice != 0) {
48363				msg += '<p style="margin-top: 24px;">Your new monthly price will be ' + UTIL.displayMoney(newPrice) + '</p>';
48364			}
48365		}
48366		
48367		var htm = '<div id="pop-email-package-confirm" package_upgrade_cd="' + package_upgrade_cd + '" style="margin-bottom: 24px;">' + msg + '</div>';
48368		var jpop = GLO.Popup.Confirm.open(htm, 'Change Monthly Message Package', GLO.Message.Marketing.changeEmailPackageConfirmed).getPopup();
48369		jpop.find('.msg').css({ "margin-top": "0", "line-height": "200%" });
48370	}
48371	
48372	_conMarketing.changeEmailPackageConfirmed = function(package_upgrade_cd) {
48373		var jpop = $('#pop-email-package-confirm');
48374		
48375		if (jpop.length) {
48376			package_upgrade_cd = jpop.attr('package_upgrade_cd');
48377		}
48378		
48379    	var url = GLO.Link.Page.Provider.Home + 'manage/UpdateEmailPackage';
48380    	var jsave = $('#email-option-list').find('tr[package_upgrade_cd = "' + package_upgrade_cd + '"] .btnSave');
48381    	
48382    	GLO.UI.Form.beginProcessing(jsave);
48383    	
48384        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "email_package_cd": package_upgrade_cd } })
48385            .success(function(data, textStatus, jqXHR) {
48386                //GLO.UI.Form.resetProcessing(jsave);
48387                
48388                GLO.Popup.close(jpop.closest('.glopop'));
48389                new GLO.Popup.Success('Email Package Changed');
48390                setTimeout(function() { location.reload(); }, 600);
48391            })
48392            .error(function(jqXHR, textStatus, errorThrown) {
48393                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48394            });
48395	}
48396	
48397	_conMarketing.lookupStaffAlertHelp = function() {
48398		var loadUrl = GLO.Link.Object.Provider.Wiz5StaffConfig + '?dt=' + UTIL.getDateString();
48399        var pop = $('#wiz5-popupStaffConfig');
48400        
48401        pop.load(loadUrl, function() {
48402        	jhtm = pop.find('#wiz5-popupStatus-alert-help > div');
48403        	_conMarketing.openStaffAlertHelp(jhtm);
48404        });
48405    }
48406	
48407	_conMarketing.openStaffAlertHelp = function(jhtm) {
48408		if (UTIL.isEmpty(jhtm)) {
48409			jhtm = $('#wiz5-popupStatus-alert-help > div').clone();
48410		}
48411		
48412		var ojpop = new GLO.Popup.Custom(jhtm);
48413		var jpop = ojpop.getPopup();
48414        var h1 = jpop.find('h1').css({ "margin-bottom": "0" });
48415        
48416        var jbtns = jpop.find('.pop-buttons-parent');
48417        jbtns.find('.btnSave').remove();
48418        jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').css({ "float": "none", "margin": "auto", "padding": 0 }).find('>a').text('Close');
48419        
48420        _addMoreHelpButton(jpop, h1);
48421        _customizeStaffAlertHelp(jpop);
48422        ojpop.realign();
48423	}
48424	
48425	function _addMoreHelpButton(jpop, h1) {
48426		if (GLO.Info.roleType < 210) { return; }
48427		
48428		var jmsg = jpop.find('.msg').addClass('help-post').css({ "padding-top": "0" });
48429        var htmButtonText = 'More on Notifications sent from <span class="sa-brand"><i>Schedule</i><b>Anyone</b></span>';
48430        var btnCss = 'btnAdd';
48431        
48432        if (innerWidth < 400) {
48433        	btnCss += ' btn3lines';
48434        } else if (innerWidth < 600) {
48435        	btnCss += ' btn2lines';
48436        } else {
48437        	h1.css({ "letter-spacing": "1px" });
48438        }
48439        
48440        var htmButton = '<span class="' + btnCss + '">
48440<a onclick="GLO.Message.Marketing.openStaffAlertHelpMore(this, event)" style="background-color: #275264;">' + htmButtonText + '</a></span>';
48441        var htmMore = '<div style="margin-top: 20px; margin-bottom: 12px; text-align: center;">' + htmButton + '</div>';
48442        jmsg.append(htmMore);
48443	}
48444	
48445	function _customizeStaffAlertHelp(jpop) {
48446		var jStaffConfig = $('#wiz5-popupStaffConfig');
48447		var jsummary = jpop.find('#wiz5-popupStatus-alert-help-summary');
48448		var jintro = jpop.find('#wiz5-popupStatus-alert-help-intro').css({ "padding-top": "6px" });
48449		
48450		if (jStaffConfig.length !== 1 || jsummary.length !== 1) { return; }
48451		
48452		var sname = jStaffConfig.find('#wiz5-staffName').text();
48453		var emailDays = UTIL.coalesceInt(jStaffConfig.find('#Email_Notify_Day_sr').val(), 0);
48454		// var textHours = UTIL.coalesceInt(jStaffConfig.find('#Text_Notify_Hr_sr').val(), 0);
48455		var textHours = 0;
48456		
48457		if (!UTIL.isEmpty(sname)) {
48458			sname += ' is';
48459		} else {
48460			sname = 'You are';
48461		}
48462		
48463		if (emailDays > 0 && textHours > 0) {
48464			var htm = '<b>' + sname + ' setup to get notified</b> <ul>'
48465						+ '<li style="margin-bottom: 4px; color: #222;">by email for changes on appointments that start in ' + emailDays + ' days</li>'
48466						+ '<li style="margin-bottom: 4px; color: #222;">by text for changes on appointments that start in ' + textHours + ' hours</li>'
48467					+ '</ul>';
48468		} else if (textHours > 0) {
48469			var htm = sname + ' setup to get notified by text for changes on appointments that start in ' + textHours + ' hours';
48470		} else if (emailDays > 0) {
48471			var htm = sname + ' setup to get notified by email for changes on appointments that start in ' + emailDays + ' days';
48472		} else {
48473			var htm = sname + ' <b>NOT</b> setup to get notified by email or push notifications for appointment changes';
48474		}
48475		
48476		var divCSS = 'padding-left: 20px; margin-bottom: 32px; padding-bottom: 8px; border-bottom: 1px solid black; font-weight: bold; color: #222;';
48477		jsummary.replaceWith('<div style="' + divCSS + '">' + htm + '</div>');
48478		
48479		jintro.css({ "background-color": "pink" });
48480	}
48481	
48482	_conMarketing.openStaffAlertHelpMore = function(element, event) {
48483		GLO.UI.Form.beginProcessing( $(element) );
48484		
48485		setTimeout(function() {
48486			document.location = GLO.Link.WebsiteDomain + 'provider/manage/Upgrade?reason=email-blast&helloback=profile#open=help&page=1';
48487		}, 400);
48488	}
48489	
48490	_conMarketing.openHelp = function(stepNumber, highlight) {
48491		SA.Help.openReportHelp('#message-help-pop-container', stepNumber, 'info/MessageHelp');
48492		
48493		if (!UTIL.isEmpty(highlight)) {
48494			var jhigh = $(highlight);
48495			UI.highlight(jhigh);
48496		}
48497	}
48498	
48499	_conMarketing.openTextOptInHelp = function(textPackage, originalPackage, isConfirm) {
48500		if (textPackage == 20) {
48501			var labelId = '', jhtm = $('#client-message-default-opt-in');
48502		} else if (textPackage == 50) {
48503			var jhtm = $('#client-message-direct-text');
48504		} else {
48505			var jhtm = $('#client-message-default-opt-out');
48506		}
48507		
48508		var htm = jhtm.outerHTML();
48509		var label = $('#message-text-package' + textPackage).html();
48510		
48511		if (!UTIL.isEmpty(label)) {
48512			htm = '<div id="pop-client-text-optin">' + htm + '<div id="text-optin-header-label">' + label + '</div> </div>';
48513		}
48514		
48515		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Text Opt-In Setting', null, null, true);
48516		var jpop = ojpop.getPopup().addClass('pop-text-opt-in');
48517		var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
48518		
48519		if (isConfirm && originalPackage != textPackage) {
48520			var fnSave = function() {
48521				GLO.Message.Marketing.changeTextPackage(textPackage);
48522			};
48523			
48524			jbtns.find('.btnSave').find('> a').text('Change Text Setting').click(fnSave);
48525		} else {
48526			GLO.Popup.Custom.singleButton(jpop, 'Close');
48527		}
48528		
48529		ojpop.realign();
48530	}
48531	
48532	return _conMarketing;
48533})();
48534
48535
48536GLO.Message.Marketing.NewClient = (function() {
48537	function _cNewClient() { }
48538	
48539	_cNewClient.init = function() {
48540		var jcontainer = $('#welcome-email');
48541		
48542		jcontainer.find('input:text, textarea, .sa-text-editor').on('keyup', function() {
48543			jcontainer.find('.btnSave > a').addClass('unsaved');
48544		});
48545		jcontainer.find('input, select, textarea, .sa-text-editor').on('change', function() {
48546			jcontainer.find('.btnSave > a').addClass('unsaved');
48547		});
48548		
48549		var jtext = jcontainer.find('.sa-text-editor');
48550		SA.TextEditor.init(jtext, 'Welcome New Client Message');
48551	}
48552	
48553	_cNewClient.changeEnabled = function() {
48554		var j = $('#welcome-email');
48555		var jenabled = j.find('#Message_New_Client_fl')
48556		
48557		if (jenabled.prop('checked') && !UTIL.parseBool(j.attr('online_booking_fl'))) {
48558			var msg = '<p>Enabling <b class="narrow-text">Welcome New Client Email</b> requires enabling <b class="narrow-text">Oline Booking</b></p>';
48559			var btn = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced?highlight=aob-allow-online-booking\', this, event, true)">Go To Enable Online Booking</a>';
48560			var htmWarn = '<div id="pop-warn-require-online-booking">' + msg + '<div style="margin: 24px auto;">' + btn + '</div></div>';
48561			
48562			jenabled.prop('checked', false);
48563			GLO.Popup.Warning.open(htmWarn, 'Requires Enabling Online Booking');
48564		}
48565	}
48566	
48567	_cNewClient.sendSample = function() {
48568		var jcontainer = $('#welcome-email');
48569    	var jsample = $('.btnSendSample'), jsave = jcontainer.find('.btnSave');
48570    	var url = GLO.Link.WebsiteDomain + 'message/WelcomeClientMessageSample';
48571    	
48572    	if (!GLO.Staff.hasEmail(GLO.Info.StaffId)) {
48573    		var aProfileMe = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/1\', this, event, true)">Profile -> Me</a>';
48574    		var htmWarn = '<p>Email required to send yourself a sample message</p> <p>Please go to ' + aProfileMe + ' and add your email address</p>';
48575    		
48576    		GLO.Popup.Warning.open(htmWarn, 'Email Missing');
48577    		return;
48578    	} else if (jsave.hasClass('unsaved')) {
48579			_cNewClient.save(false, true);
48580			return;
48581		}
48582		
48583    	GLO.UI.Form.beginProcessing(jsample);
48584    	
48585        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
48586            .success(function(data, textStatus, jqXHR) {
48587                GLO.UI.Form.resetProcessing();
48588                
48589                if (UTIL.parseBool($(data).attr('error_fl'))) {
48590                	GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview');
48591                } else {
48592                	var htmEmail = '<div style="margin: 8px 0; font-weight: bold;">' + SA.StaffContact[0].email + '</div>';
48593	                var astyle = 'display: inline-block; line-height: 100%; white-space: nowrap; border-bottom-width: 1px; border-bottom-style: solid;';
48594	                var aProfileMe = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + GLO.Link.WebsiteDomain + 'provider/profile/1\', this, event, true)" style="' + astyle + '">Profile ' + UI.arrow + ' Me</a>';
48595	                var htmChangeEmail = '<div style="margin: 12px 0;"> <p>You can change your email by going to ' + aProfileMe + '</p></div>';
48596	                var htm = '<div id="pop-info-sample-sent" style="margin-bottom: 24px;"><p>' + SA.Resource.SendSampleSent + '</p>' + htmEmail + htmChangeEmail + '</div>'
48597	                
48598	                GLO.Popup.Info.openSimple(htm, 'Welcome New Client Email');
48599                }
48600            })
48601            .error(function(jqXHR, textStatus, errorThrown) {
48602                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48603            });
48604	}
48605	_cNewClient.preview = function() {
48606		var jcontainer = $('#welcome-email');
48607    	var jpreview = jcontainer.find('.btnPreview'), jsave = jcontainer.find('.btnSave');
48608    	var url = GLO.Link.WebsiteDomain + 'message/WelcomeClientPreview';
48609    	
48610    	if (jsave.hasClass('unsaved')) {
48611			_cNewClient.save(true, false)
48612			return;
48613		}
48614		
48615    	GLO.UI.Form.beginProcessing(jpreview);
48616    	
48617        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
48618            .success(function(data, textStatus, jqXHR) {
48619                GLO.UI.Form.resetProcessing();
48620                
48621                if (UTIL.parseBool($(data).attr('error_fl'))) {
48622                	GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview');
48623                } else {
48624                	_displayPreview(data);
48625                }
48626            })
48627            .error(function(jqXHR, textStatus, errorThrown) {
48628                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48629            });
48630	}
48631	
48632	_cNewClient.save = function(isPreview, isSendSample) {
48633		var jcontainer = $('#welcome-email');
48634		var msg = UTIL.htmlEncode(DOMPurify.sanitize(jcontainer.find('.sa-editor .sa-text-editor')[0].innerHTML));
48635		var subject = jcontainer.find('#Email_Subject_vc').val();
48636		var isEnabled = jcontainer.find('#Message_New_Client_fl').prop('checked');
48637		
48638		var jd = { "subject": subject, "body": msg, "enable": isEnabled };
48639		var url = GLO.Link.WebsiteDomain + 'message/WelcomeClientMessage';
48640    	var jsave = jcontainer.find('.btnSave');
48641    	
48642    	GLO.UI.Form.beginProcessing(jsave);
48643    	
48644        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
48645            .success(function(data, textStatus, jqXHR) {
48646                GLO.UI.Form.resetProcessing();
48647                jsave.find('>a').removeClass('unsaved');
48648                GLO.Popup.Success.open('Welcome New Client Email Settings Saved', 'New Client Email');
48649                
48650                if (isPreview) {
48651                	_cNewClient.preview();
48652                } else if (isSendSample) {
48653                	_cNewClient.sendSample();
48654                }
48655            })
48656            .error(function(jqXHR, textStatus, errorThrown) {
48657                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48658            });
48659	}
48660	
48661	function _displayPreview(data) {
48662		if (GLO.Info.isMobile() || innerWidth < 500) {
48663			var style = '', btnSample = 'Send Sample', btnSendAll = 'Send', h1Text = 'Preview';
48664			var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;';
48665		} else {
48666			var btnSample = 'Send Sample (to me)', btnSendAll = 'Send Message', h1Text = 'Email Preview';
48667			var style = '';				//' style="width: ' + parseInt(innerWidth * .9) + 'px;"'
48668			var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;';
48669		}
48670		
48671		var htmlButtons = '<div id="pop-preview-message-buttons">'
48672							+ '<span id="btnSendSample" class="btnSendSample btnAdd"> <a onclick="GLO.Message.Marketing.NewClient.sendSample()">' + btnSample + '</a> </span>'
48673							+ '<span class="btnOk btn">
48673<a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>'
48674						+ '</div';
48675		
48676		var h1 = '<h1 style="position: relative; margin-bottom: 0;">' + '<span style="' + h1style + '">' + h1Text + '</span>' + '</h1>';
48677		var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>');
48678		GLO.Mobile.formatExternalLinksForIos(jhtm);
48679		
48680		var ojpop = new GLO.Popup.Custom(jhtm);
48681		var jpop = ojpop.getPopup().addClass('no-persist').css({ "top": "10px" });
48682		
48683		jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons);
48684		jpop.find('.msg').css({ "max-width": "900px" });
48685		
48686		var h1 = jpop.find('h1');
48687		h1.find('form').css({ "float": "left" });
48688		h1.find('input');
48689		
48690		SA.Uploader.init(jpop, GLO.Message.Bulk.imageUploadComplete);
48691		
48692		if (!GLO.Info.isMobile()) {
48693			var jscroll = jpop.find('.msg');
48694			jscroll.width(jscroll.width() + 12);
48695		}
48696		
48697		setTimeout(ojpop.realign, 800);		//= displays scroll bar on popup after email image has loaded. //toDo: run on-image-load (not setTimeout).
48698	}
48699	
48700	return _cNewClient;
48701})();
48702
48703
48704GLO.Message.Marketing.Birthday = (function() {
48705	function _cBdayEmail() { }
48706	
48707	_cBdayEmail.init = function() {
48708		var jcontainer = $('#birthday-email');
48709		
48710		jcontainer.find('input:text, textarea, .sa-text-editor').on('keyup', function() {
48711			$('#birthday-email').find('.btnSave > a').addClass('unsaved');
48712		});
48713		jcontainer.find('input, select, textarea, .sa-text-editor').on('change', function() {
48714			$('#birthday-email').find('.btnSave > a').addClass('unsaved');
48715		});
48716		
48717		var jtext = jcontainer.find('.sa-text-editor');
48718		SA.TextEditor.init(jtext, 'Birthday Email Message');
48719		
48720		_initDiscountButton(jcontainer);
48721	}
48722	function _initDiscountButton(jcontainer) {
48723		var btnNew = jcontainer.find('#btnNewBdayDiscount');
48724		var existingProviderDiscountId = _getBirthdayDiscountId();
48725		
48726		if (!UTIL.isEmpty(existingProviderDiscountId)) {
48727			var url = 'provider/manage/discount?open=discount&id=' + existingProviderDiscountId;
48728			var btnUpdate = '<span id="btnUpdateBdayDiscount" class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)">Update Birthday Discount</a></span>';
48729			btnNew.replaceWith(btnUpdate);
48730		} else {
48731			btnNew.removeClass('hide');
48732		}
48733	}
48734	
48735	function _getBirthdayDiscountId() {
48736		var arr = GLO.Data.DiscountList;
48737        
48738		for (var i=0; i < arr.length; i++) {
48739			if (arr[i].discount_type1_cd == 70 || arr[i].discount_type2_cd == 70 || arr[i].discount_type3_cd == 70) {
48740				return arr[i].provider_discount_id;
48741			}
48742		}
48743	}
48744	
48745	function _displayPreview(data) {
48746		if (GLO.Info.isMobile() || innerWidth < 500) {
48747			var style = '', btnSample = 'Send Sample', h1Text = 'Preview';
48748			var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;';
48749		} else {
48750			var btnSample = 'Send Sample (to me)', h1Text = 'Email Preview';
48751			var style = '';				//' style="width: ' + parseInt(innerWidth * .9) + 'px;"'
48752			var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;';
48753		}
48754		
48755		var htmlButtons = '<div id="pop-preview-message-buttons">'
48756							+ '<span id="btnSendSample" class="btnAdd"> <a onclick="GLO.Message.Marketing.Birthday.sendSample()">' + btnSample + '</a> </span>'
48757							+ '<span class="btnOk btn"><a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>'
48758						+ '</div';
48759		
48760		var h1 = '<h1 style="position: relative; margin-bottom: 0;"><span style="' + h1style + '">' + h1Text + '</span></h1>';
48761		var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>');
48762		GLO.Mobile.formatExternalLinksForIos(jhtm);
48763		
48764		var ojpop = new GLO.Popup.Custom(jhtm);
48765		var jpop = ojpop.getPopup().addClass('no-persist').css({ "top": "10px" });
48766		
48767		jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons);
48768		jpop.find('.msg').css({ "max-width": "900px" });
48769		
48770		var h1 = jpop.find('h1');
48771		h1.find('form').css({ "float": "left" });
48772		h1.find('input');
48773		
48774		if (!GLO.Info.isMobile()) {
48775			var jscroll = jpop.find('.msg');
48776			jscroll.width(jscroll.width() + 12);
48777		}
48778		
48779		setTimeout(ojpop.realign, 800);		//= displays scroll bar on popup after email image has loaded. //toDo: run on-image-load (not setTimeout).
48780	}
48781	
48782	function _canSendSample(messageFormat, isUseSmsGateway) {
48783		if (messageFormat == 3) {
48784			if (GLO.Staff.hasText(GLO.Info.StaffId, isUseSmsGateway)) {
48785				return true;
48786			}
48787		} else if (GLO.Staff.hasEmail(GLO.Info.StaffId)) {
48788			return true;
48789		}
48790		
48791		return false;
48792	}
48793	
48794	_cBdayEmail.preview = function() {
48795		var jcontainer = $('#birthday-email');
48796    	var jpreview = jcontainer.find('.btnPreview'), jsave = jcontainer.find('.btnSave');
48797    	var url = GLO.Link.WebsiteDomain + 'message/BirthdayPreview';
48798    	
48799    	if (jsave.hasClass('unsaved')) {
48800			_cBdayEmail.save(true, false)
48801			return;
48802		}
48803		
48804    	GLO.UI.Form.beginProcessing(jpreview);
48805    	
48806        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
48807            .success(function(data, textStatus, jqXHR) {
48808                GLO.UI.Form.resetProcessing();
48809                
48810                if (UTIL.parseBool($(data).attr('error_fl'))) {
48811                	GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview');
48812                } else {
48813                	_displayPreview(data);
48814                }
48815            })
48816            .error(function(jqXHR, textStatus, errorThrown) {
48817                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48818            });
48819	}
48820	_cBdayEmail.sendSample = function() {
48821		var jcontainer = $('#birthday-email');
48822    	var jsample = $('.btnSendSample'), jsave = jcontainer.find('.btnSave');
48823    	var url = GLO.Link.WebsiteDomain + 'message/BirthdaySample';
48824    	
48825    	if (jsave.hasClass('unsaved')) {
48826			_cBdayEmail.save(true, false)
48827			return;
48828		} else if (!_canSendSample()) {
48829			return;
48830		}
48831		
48832    	GLO.UI.Form.beginProcessing(jsample);
48833    	
48834        var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
48835            .success(function(data, textStatus, jqXHR) {
48836                GLO.UI.Form.resetProcessing();
48837                
48838                if (UTIL.parseBool($(data).attr('error_fl'))) {
48839                	GLO.Popup.Error.open($(data).outerHTML(), 'Create Preview');
48840                } else {
48841                	var htmEmail = '<div style="margin: 8px 0; font-weight: bold;">' + SA.StaffContact[0].email + '</div>';
48842	                var astyle = 'display: inline-block; line-height: 100%; white-space: nowrap; border-bottom-width: 1px; border-bottom-style: solid;';
48843	                var aProfileMe = '<a href="' + GLO.Link.WebsiteDomain + 'provider/profile/1" style="' + astyle + '">Profile ' + UI.arrow + ' Me</a>';
48844	                var htmChangeEmail = '<div style="margin: 12px 0;"> <p>You can change your email by going to ' + aProfileMe + '</p></div>';
48845	                var htm = '<div id="pop-info-sample-sent" style="margin-bottom: 24px;"><p>' + SA.Resource.SendSampleSent + '</p>' + htmEmail + htmChangeEmail + '</div>'
48846	                
48847	                GLO.Popup.Info.openSimple(htm, 'Birthday Email');
48848                }
48849            })
48850            .error(function(jqXHR, textStatus, errorThrown) {
48851                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48852            });
48853	}
48854	_cBdayEmail.save = function(isPreview, isSendSample) {
48855		var jcontainer = $('#birthday-email');
48856		var msg = UTIL.htmlEncode(DOMPurify.sanitize(jcontainer.find('.sa-editor .sa-text-editor')[0].innerHTML));
48857		var subject = jcontainer.find('#Email_Subject_vc').val();
48858		var rdoWhenSend = jcontainer.find('input[type="radio"][name="rdoWhenSend"]:checked').val();
48859		var jdays = jcontainer.find('#Send_Email_Day_Before_sr');
48860		
48861		if (rdoWhenSend == 'none') {
48862			var days = '';
48863		} else if (rdoWhenSend == 'bday') {
48864			var days = 0;
48865		} else if (rdoWhenSend == 'before') {
48866			var days = jdays.val();
48867		}
48868		
48869		var jd = { "subject": subject, "body": msg, "days": days };
48870		var url = GLO.Link.WebsiteDomain + 'message/birthday';
48871    	var jsave = jcontainer.find('.btnSave');
48872    	
48873    	jdays.val(days);
48874    	GLO.UI.Form.beginProcessing(jsave);
48875    	
48876        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
48877            .success(function(data, textStatus, jqXHR) {
48878                GLO.UI.Form.resetProcessing();
48879                jsave.find('>a').removeClass('unsaved');
48880                GLO.Popup.Success.open('Birthday Email Settings Saved', 'Birthday Email');
48881                
48882                if (isPreview) {
48883                	_cBdayEmail.preview();
48884                } else if (isSendSample) {
48885                	_cBdayEmail.sendSample();
48886                }
48887            })
48888            .error(function(jqXHR, textStatus, errorThrown) {
48889                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
48890            });
48891	}
48892	
48893	return _cBdayEmail;
48894})();
48895
48896
48897GLO.Message.Marketing.Auto = (function() {
48898	function _conMMAuto() { }
48899	
48900	_conMMAuto.init = function(fmtType) {
48901		GLO.Info.requireGoldOrIndependentPackage = true;
48902		UI.initTableSorter($('table.tablesorter:visible'));
48903		_initGrid();
48904		_initUrlHelp();
48905	}
48906	function _initUrlHelp() {
48907		var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
48908		
48909		if (open == 'help') {
48910			GLO.Message.Marketing.Auto.openHelp();
48911		}
48912	}
48913	function _initGrid() {
48914		var trs = $('#auto-marketing-grid > tbody').find('tr');
48915		var jdd = $('#auto-marketing-edit-service');
48916		
48917		_initServiceList(jdd);
48918		_resetServiceList(jdd, trs);
48919		_resetOtherService(jdd, trs);
48920	}
48921	
48922	function _resetOtherService(jdd, trs) {
48923		if (trs.length > 1) {
48924			var firstOption = jdd.find('option:not(.no):first').text('(' + SA.Resource.any_other_service + ')');
48925			
48926			if (trs.length > 1) {
48927				for (var i=0; i < trs.length; i++) {
48928					if (UTIL.isEmpty(trs.eq(i).attr('service_group_id')) && UTIL.isEmpty(trs.eq(i).attr('service_id'))) {
48929						trs.eq(i).find('.auto-service').text(SA.Resource.any_other_service);
48930						_hideOtherService(jdd, firstOption);
48931					}
48932				}
48933			} else if (UTIL.isEmpty(trs.attr('service_group_id')) && UTIL.isEmpty(trs.attr('service_id'))) {
48934				trs.find('.auto-service').text(SA.Resource.AnyService.toLowerCase());
48935				_hideOtherService(jdd, firstOption);
48936			}
48937		} else if (trs.length === 0) {
48938			jdd.find('option[value=""]').text(SA.Resource.AnyService.toLowerCase())
48939		}
48940	}
48941	
48942	function _hideOtherService(jdd, firstOption) {
48943		firstOption.addClass('hide');
48944		
48945		var blankOption = jdd.find('option.no').removeClass('hide');
48946		
48947		if (blankOption.length === 0) {
48948			jdd.prepend('<option class="no" value="no"></option>');
48949		}
48950	}
48951	
48952	function _displayOtherService(jdd, firstOption) {
48953		firstOption.removeClass('hide');
48954		jdd.find('option.no').remove();			//.addClass('hide');
48955	}
48956	
48957	function _resetServiceList(jdd, trs) {
48958		var svc, sg, opt;
48959		
48960		for (var i=0; i < trs.length; i++) {
48961			svc = trs.eq(i).attr('service_id');
48962			sg  = trs.eq(i).attr('service_group_id');
48963			
48964			if (!UTIL.isEmpty(svc)) {
48965				opt = jdd.find('option[value="' + svc + '"]');
48966			} else if (!UTIL.isEmpty(sg)) {
48967				opt = jdd.find('option[value="' + sg + '"]');
48968			}
48969			
48970			if (opt) {
48971				opt.addClass('hide');
48972				opt = null;
48973			}
48974		}
48975	}
48976	
48977	function _initServiceList(jdd) {
48978		var j = jdd.find('.hide');
48979		
48980		for (var i=0; i < j.length; i++) {
48981			j.eq(i).removeClass('hide');
48982		}
48983	}
48984	
48985	_conMMAuto.openHelp = function(onDiffPage) {
48986		var h1 = 'Follow-up Emails';
48987		
48988		if (onDiffPage) {
48989			var url = '\'message/AutoMarketing?helloback=advanced&tabback=client\'';
48990			var btn = '<span class="btnAdd" onclick="GLO.Uri.gotoUri(' + url + ')"> <a style="background-color: blue; border-radius: 4px;">Follow-up Setup</a></span>';
48991		} else {
48992			var btn = '<span class="btnAdd" onclick="GLO.Message.Marketing.Auto.openEdit()"> <a>New <span>Follow-up Message</span><i class="fa fa-envelope"></i></a></span>';
48993		}
48994		
48995		var msg1 = '<p>Setup ' + GLO.Info.getScheduleAnyoneHtm() + ' to automatically send follow-up messages to clients who have not scheduled their next appointment</p>';
48996        var msg2 = '<p>Just press ' + btn + ' and select the number of days or weeks after the appointment you want the follow-up to be sent</p>'
48997        var msg3 = '<p>You can create custom messages for different types of services and have them set at different times</p>';
48998		
48999		var ojInfo = GLO.UI.openHelp2(h1, msg1 + msg2 + msg3, 'pop-help-followup');
49000		var jpop = ojInfo.getPopup().addClass('pop-info2');
49001	}
49002	
49003	_conMMAuto.info = function() {
49004		var ulstyle = 'text-align: left;', style = 'white-space: pre-wrap; line-height: 170%;';
49005		var p = '<p style="margin-bottom: 12px;">';
49006		
49007		if (GLO.Info.isMobile()) {
49008			ulstyle = 'margin-left: -36px; margin-right: 0;';
49009			style += ' padding-right: 8px;';
49010		}
49011		
49012		var htm = $('<div id="pop-from-email-help"> <h1 class="friendly-msg">' + SA.Resource.HowMessageIsCreatedUsingAutofills + '</h1>'
49013					+'<div>'
49014						+ '<div class="friendly-msg" style="' + style + '">'
49015							+ p + 'You can change the subject and message as desired.  Some information in the message can be populated for you.  </p>'
49016							+ p + 'For example, <i><b>{client-name}</b></i> indicates that the client\'s name will be placed there in the message.</p>'
49017							+ p + 'Below are some other auto-fills:</p>'			//If you preview the message your name will be used as both the client name and staff name.  
49018							+ '<ul style="' + ulstyle + '">'
49019								+ '<li><i style="padding-right: 6px;"><b>{first-name}</b></i> Client First Name</li>'
49020								+ '<li><i style="padding-right: 6px;"><b>{client-name}</b></i> Client Name</li>'
49021								+ '<li><i style="padding-right: 6px;"><b>{staff-name}</b></i> Staff Name</li>'
49022								+ '<li><i style="padding-right: 6px;"><b>{service-name}</b></i> Service Name</li>'
49023								+ '<li><i style="padding-right: 6px;"><b>{last-visit}</b></i> Date of Last Visit for this service</li>'
49024								+ '<li><i style="padding-right: 6px;"><b>{last-visit-days}</b></i>
49024 Number of days since the Last Visit for this service</li>'
49025								//+ '<li><i style="padding-right: 6px;"><b>{client-username}</b></i> Client\'s Username</li>'
49026								//+ '<li><i style="padding-right: 6px;"><b>{client-password}</b></i> Client\'s Password</li>'
49027							+ '</ul>'
49028						+ '</div>'
49029						+ '<div style="margin-left: -32px; margin-top: 20px; margin-bottom: 24px;"> <i style="padding-right: 8px;">Have More Questions?</i>  <a href="/contact">Contact Us</a></div>'
49030					+ '</div>'
49031				+ '</div>');
49032		 var oj = new GLO.Popup.Info(htm);
49033		 
49034		 if (GLO.Info.isMobile()) {
49035		 	oj.getPopup().find('.msg').css({ "padding-right": "4px" });
49036		 }
49037		 
49038		 return oj
49039	}
49040	
49041	_conMMAuto.openEdit = function(element) {
49042		GLO.Popup.close( $('#pop-help-followup').closest('.glopop') );
49043		
49044		if (!GLO.Info.isRequireGold()) {
49045			return false;
49046		}
49047		
49048		_initGrid();
49049		
49050		if (element) {
49051			var tr = $(element).closest('tr');
49052			var id = tr.attr('message_auto_marketing_id');
49053		} else {
49054			var tr = null;
49055		}
49056		
49057		var jpop = $('#auto-marketing-edit');
49058		
49059		if (!GLO.Info.isMobile(true) && innerHeight > 720) {
49060			jpop.addClass('tall-auto-marketing-edit');
49061		}
49062		
49063        jpop = new GLO.Popup.Custom(jpop, GLO.Message.Marketing.Auto.save).getPopup();
49064        jpop.find('.pop-buttons').remove();
49065        
49066        jpop.find('input, select, textarea').keyup( function() {
49067            $(this).closest('.glopop').find('.btnSave a').css({ "border": "3px solid Red" });
49068        });
49069        
49070        if (tr !== null) {
49071        	jpop.find('h1').attr('message_auto_marketing_id', id);
49072        	jpop.find('#Days_After_sr').val(tr.attr('days_after_sr'));
49073        	
49074        	var svc = tr.attr('service_id');
49075        	var sg = tr.attr('service_group_id');
49076        	
49077        	if (UTIL.isEmpty(svc) && !UTIL.isEmpty(sg)) { svc = 'sg' + sg; }
49078        	
49079        	var img = tr.attr('banner_image_vc');
49080        	var msg = tr.find('.message').text();
49081        	
49082        	var subject = tr.find('.auto-subject');
49083        	subject = UTIL.coalesce(subject.attr('title'), subject.text());
49084        	
49085        	var jsvc = jpop.find('#auto-marketing-edit-service').val(svc);
49086        	jsvc.find('[value="' + svc + '"]').removeClass('hide');
49087        	
49088        	jpop.find('#Subject_vc').val(subject);
49089        	jpop.find('#Body_vc').val(msg);
49090        	
49091        	if (UTIL.parseBool(tr.attr('default_subject_fl'))) {
49092        		jpop.find('#Default_Subject_fl').prop('checked', true);
49093        	} else {
49094        		jpop.find('#Default_Subject_fl').prop('checked', false);
49095        	}
49096        	
49097        	if (UTIL.parseBool(tr.attr('default_body_fl'))) {
49098        		jpop.find('#Default_Body_fl').prop('checked', true);
49099        	} else {
49100        		jpop.find('#Default_Body_fl').prop('checked', false);
49101        	}
49102        } else {
49103        	var jdefaults = $('#auto-marketing-defaults');
49104        	var subject = UTIL.coalesce(jdefaults.find('#auto-marketing-service-subject').text(), jdefaults.find('#auto-marketing-class-subject').text());
49105        	var msg = UTIL.coalesce(jdefaults.find('#auto-marketing-service-body').text(), jdefaults.find('#auto-marketing-class-body').text());
49106        	
49107        	jpop.find('#Subject_vc').val(subject);
49108        	jpop.find('#Body_vc').val(msg);
49109        	jpop.find('#Days_After_sr').val(28)
49110        }
49111	}
49112	
49113	function _hasDuplicate(sgid, svcid, id) {
49114		if (UTIL.isEmpty(sgid)) { sgid = ''; }
49115		if (UTIL.isEmpty(svcid)) { svcid = ''; }
49116		
49117		var trs = $('#auto-marketing-grid > tbody > tr[service_group_id="' + sgid + '"]');
49118		
49119		for (var i=0; i < trs.length; i++) {
49120			if (trs.attr('service_id') == svcid && trs.attr('message_auto_marketing_id') != id) {
49121				return true;
49122			}
49123		}
49124		
49125		return false;
49126	}
49127	
49128	function _hasFollowup(joption, popid) {
49129		var val = joption.val();
49130		
49131		if (val.substring(0,2) === 'sg') {
49132			var trs = $('#auto-marketing-grid > tbody > tr[service_group_id="' + val.substring(2) + '"]');
49133		} else {
49134			var trs = $('#auto-marketing-grid > tbody > tr[service_id="' + val + '"]');
49135		}
49136		
49137		if (trs.length > 0) {
49138			var tr_id = trs.attr('message_auto_marketing_id');
49139			
49140			if (tr_id != popid) {
49141				var selectedText = $.trim(joption.text());
49142				
49143				var div1 = '<div style="margin-bottom: 8px;">', div2 = '</div>';
49144				var msg1 = 'Followup Message for ' + selectedText + ' already exists';
49145				var msg2 = 'Please select a different service / service group or edit the existing followup';
49146				var h1 = 'Followup Exists for ' + selectedText;
49147				var htm = div1 + msg1 + div2 + div1 + msg2 + div2;
49148				var fnOk = function() { UI.highlight(joption.closest('select'), 1200, 4800, true); };
49149				
49150				GLO.Popup.Warning.open(htm, h1, fnOk);
49151				return true;
49152			}
49153		}
49154		
49155		return false;
49156	}
49157	
49158	_conMMAuto.changeService = function(element, event) {
49159		var joption = $(element).find(':selected');
49160		var accessType = joption.attr('min_access_type');
49161		var hasClass = UTIL.parseBool(joption.attr('has_class_fl'));
49162		return;
49163		/*
49164		var jpop = $('#auto-marketing-edit').closest('.glopop');
49165		var id = jpop.find('h1').attr('message_auto_marketing_id');
49166		
49167		if (_hasFollowup(joption, id)) {
49168			return false;
49169		}
49170		
49171		var jdefaults = $('#auto-marketing-defaults');
49172		
49173		if (hasClass) {
49174			var subject = jdefaults.find('#auto-marketing-class-subject').text();
49175			var msg = jdefaults.find('#auto-marketing-class-body').text()
49176		} else {
49177			var subject = jdefaults.find('#auto-marketing-service-subject').text();
49178    		var msg = jdefaults.find('#auto-marketing-service-body').text();
49179		}
49180		
49181		if (jpop.find('#Default_Subject_fl').prop('checked')) {
49182			jpop.find('#Subject_vc').val(subject);
49183		}
49184		
49185		if (jpop.find('#Default_Body_fl').prop('checked')) {
49186			jpop.find('#Body_vc').val(msg);
49187		}
49188		*/
49189	}
49190	
49191	_conMMAuto.changeSubject = function(element, event) {
49192		$('#Default_Subject_fl').prop('checked', false);
49193	}
49194	
49195	_conMMAuto.changeBody = function(element, event) {
49196		$('#Default_Body_fl').prop('checked', false);
49197	}
49198	
49199	_conMMAuto.remove = function() {
49200		GLO.Popup.Confirm('Are you sure you want to delete this automatic message?', function() { GLO.Message.Marketing.Auto.removeConfirmed(); });
49201	}
49202	
49203	_conMMAuto.removeConfirmed = function() {
49204		var jpop = $('#auto-marketing-edit').closest('.glopop');
49205    	var id = jpop.find('h1').attr('message_auto_marketing_id');
49206    	
49207    	var url = GLO.Link.WebsiteDomain + 'message/AutoDelete';
49208    	var jsave = jpop.closest('.glopop').find('.btnDelete');
49209    	
49210    	GLO.UI.Form.beginProcessing(jsave);
49211    	
49212        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "id": id } })
49213            .success(function(data, textStatus, jqXHR) {
49214                $('#auto-marketing-grid').find('tr[message_auto_marketing_id="' + id + '"]').remove();
49215                _initGrid();
49216                GLO.Popup.close(jpop);
49217            })
49218            .error(function(jqXHR, textStatus, errorThrown) {
49219                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
49220            });
49221	}
49222	
49223	function _getShortSubject(subject) {
49224		if (GLO.Info.isMobile()) { var max = 20; } else { var max = 60; }
49225		return UTIL.maxString(subject, max, false);
49226	}
49227	
49228	function _getSubjectTitle(subject, shortSubject) {
49229		var subjectTitle = '';
49230		
49231		if (shortSubject.length !== subject.length) {
49232			return subject;
49233		} else {
49234			return '';
49235		}
49236	}
49237	
49238	function _insertGridRow(data, days, daysText, sg, svc, svcText, subject, msg, img, isDefaultSubject, isDefaultBody) {
49239		var id = $(data).attr('id');
49240		var shortSubject = _getShortSubject(subject);
49241		var subjectTitle = _getSubjectTitle(subject, shortSubject);
49242		
49243		var tr = '<tr message_auto_marketing_id="' + id + '" days_after_sr="' + days + '" service_id="' + svc + '" service_group_id="' + sg 
49244						+ '" create_dt="' + new Date() + '" create_by_staff_id="' + GLO.Info.StaffId + '" banner_image_vc="' + UTIL.cleanString(img) 
49245						+ '" default_subject_fl="' + isDefaultSubject + '" default_body_fl="' + isDefaultBody + '">'
49246                    + '<td class="auto-range">' + daysText + '</td>'
49247                    + '<td class="auto-service">' + svcText + '</td>'
49248                    + '<td class="auto-subject" title="' + subjectTitle + '">' + subject + '</td>'
49249                    + '<td class="auto-edit">'
49250                        + '<span class="btnAdd btnAction2"> <a onclick="GLO.Message.Marketing.Auto.openEdit(this)">Edit</a> </span>'
49251                        + '<span class="message hide">' + msg + '</span>'
49252                    + '</td>'
49253                + '</tr>';
49254		
49255		$('#auto-marketing-grid').removeClass('hide').find('> tbody').prepend(tr);
49256	}
49257	
49258	function _updateGrid(data, id, days, daysText, sg, svc, svcText, subject, msg, img, isDefaultSubject, isDefaultBody) {
49259		if (UTIL.isEmpty(id)) {
49260			_insertGridRow(data, days, daysText, sg, svc, svcText, subject, msg, img, isDefaultSubject, isDefaultBody);
49261			return;
49262		}
49263		
49264		var tr = $('#auto-marketing-grid > tbody').find('tr[message_auto_marketing_id="' + id + '"]');
49265		tr.attr('update_dt', new Date());
49266		tr.attr('days_after_sr', days);
49267		tr.attr('service_id', svc);
49268		tr.attr('service_group_id', sg);
49269		tr.attr('banner_image_vc', UTIL.cleanString(img));
49270		
49271		var shortSubject = _getShortSubject(subject);
49272		var subjectTitle = _getSubjectTitle(subject, shortSubject);
49273		
49274		tr.find('.auto-range').text(daysText);
49275		tr.find('.auto-service').text(svcText);
49276		tr.find('.auto-subject').attr('title', subjectTitle).text(shortSubject);
49277		tr.find('.message').text(msg);
49278		
49279		if (isDefaultSubject === undefined) { isDefaultSubject = true; }
49280		if (isDefaultBody === undefined) { isDefaultBody = true; }
49281		tr.find('#Default_Subject_fl').prop('checked', isDefaultSubject);
49282		tr.find('#Default_Body_fl').prop('checked', isDefaultBody);
49283	}
49284	
49285	function _displayPreview(data) {
49286		if (GLO.Info.isMobile()) {
49287			var style = '', btnSample = SA.Resource.SendSample, h1Text = SA.Resource.Preview;
49288			var h1style = 'display: inline-block; padding-top: 2px; padding-bottom: 4px; letter-spacing: 2px; font-size: 18px; color: white;';
49289		} else {
49290			var style = ' style="width: ' + parseInt(innerWidth * .9) + 'px;"', btnSample = SA.Resource.SendSample + ' (' + SA.Resource.to_me + ')', h1Text = SA.Resource.EmailPreview;
49291			var h1style = 'letter-spacing: 2px; font-size: 24px; color: white;';
49292		}
49293		
49294		var htmlButtons = '<div id="pop-preview-message-buttons">'
49295							+ '<span class="btnOk btn"><a onclick="GLO.Popup.close()" style="letter-spacing: 1px;">' + SA.Resource.Close + '</a></span>'
49296							+ '<span id="btnSendSample" class="btnAdd"> <a onclick="GLO.Message.Marketing.Auto.sendSample()">' + btnSample + '</a> </span>'
49297						+ '</div';
49298		
49299		var uploadHtm = $('#be-message-widgets .sa-upload').outerHTML();
49300		
49301		var h1 = '<h1 style="position: relative; margin-bottom: 0;">'
49302					+ uploadHtm 		//+ '<span id="btnChangeImage" class="btnAdd"> <a onclick="GLO.Message.Bulk.changeImage()">Change Image</a> </span>'
49303					+ '<span style="' + h1style + '">
49303' + h1Text + '</span>'
49304				+ '</h1>';
49305		
49306		var jhtm = $('<div id="pop-preview-message"' + style + '>' + h1 + data + '</div>');
49307		GLO.Mobile.formatExternalLinksForIos(jhtm);
49308		var jpop = new GLO.Popup.Custom(jhtm).getPopup().addClass('no-persist').css({ "top": "10px" });
49309		
49310		jpop.find('.pop-buttons').css({ "width": "100%" }).html(htmlButtons);
49311		jpop.find('.msg').css({ "max-width": "900px" });
49312		
49313		var h1 = jpop.find('h1');
49314		h1.find('form').css({ "float": "left" });
49315		h1.find('input');
49316		
49317		SA.Uploader.init(jpop, GLO.Message.Marketing.Auto.imageUploadComplete);
49318		
49319		if (!GLO.Info.isMobile()) {
49320			var jscroll = jpop.find('.msg');
49321			jscroll.width(jscroll.width() + 12);
49322		}
49323	}
49324	
49325	_conMMAuto.imageUploadComplete = function(jupload, fileName, imgId, imgSize) {
49326		var jbanner = $('#pop-preview-message .banner img');
49327		jbanner.attr('src', GLO.Data.cdnDirectory + 'upload-folder/' + fileName);
49328	}
49329	
49330	_conMMAuto.sendSample = function() {
49331		if (!GLO.Message.Bulk.canSendSample()) { return; }
49332		
49333		var j = $('#auto-marketing-edit').closest('.glopop');
49334		var sg = '', svc = j.find('#auto-marketing-edit-service').val();
49335		
49336		if (svc.indexOf('sg') !== -1) { sg = svc.substring(2); svc = ''; }
49337		
49338		var jd = { "service_group_id": sg, "service_id": svc };
49339		var url = GLO.Link.WebsiteDomain + 'message/AutoSendSample';
49340    	var jbtn = $('.glopop #btnSendSample');
49341    	
49342    	GLO.UI.Form.beginProcessing(jbtn);
49343    	
49344        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
49345            .success(function(data, textStatus, jqXHR) {
49346                GLO.UI.Form.resetProcessing();
49347                new GLO.Popup.Info(SA.Resource.SendSampleSent);
49348            })
49349            .error(function(jqXHR, textStatus, errorThrown) {
49350                GLO.UI.Form.resetProcessing();
49351                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
49352            });
49353	}
49354	
49355	_conMMAuto.preview = function() {
49356		_conMMAuto.save(true);
49357	}
49358	
49359	_conMMAuto.save = function(isPreview) {
49360		var j = $('#auto-marketing-edit').closest('.glopop');
49361    	var days = j.find('#Days_After_sr').val();
49362    	var daysText = j.find('#Days_After_sr :selected').text();
49363    	var id = j.find('h1').attr('message_auto_marketing_id');
49364    	var existingFollowupCount = $('#auto-marketing-grid > tbody > tr').length;
49365    	
49366    	var jsvc = j.find('#auto-marketing-edit-service');
49367    	var sg = '', svc = jsvc.val(), joption = jsvc.find(':selected');
49368    	var svcText = $.trim(j.find('#auto-marketing-edit-service :selected').text());
49369    	
49370    	if (existingFollowupCount > 0) {
49371	    	if ((svc === '' && _hasDuplicate('', '', id)) || svc == 'no') {
49372				var msgWarn = '<div style="text-align: left;">'
49373								+ '<div>Only one automatic follow-up message can be sent per service</div>'
49374								+ '<div style="margin-top: 8px;">Please select the service (or service group) for this follow-up message</div>'
49375							+ '</div>';
49376				
49377				GLO.Popup.Warning.open(msgWarn, SA.Resource.PleaseSelectService, function() { $('#auto-marketing-edit-service').focus(); });
49378				return;
49379	    	} else if (svc !== '' && _hasFollowup(joption, id)) {
49380				return false;
49381			}
49382    	}
49383    	
49384    	var msg = j.find('#Body_vc').val();
49385    	var subject = j.find('#Subject_vc').val();
49386    	
49387    	if (svc.indexOf('sg') !== -1) { sg = svc.substring(2); svc = ''; }
49388    	
49389    	var url = GLO.Link.WebsiteDomain + 'message/AutoEdit';
49390    	var jsave = j.closest('.glopop').find('.btnSave');
49391    	
49392    	var jd = { "service_group_id": sg, "service_id": svc, "days_after_sr": days, "subject_vc": subject, "message_vcm": msg };
49393    	
49394    	if (j.find('#Default_Subject_fl').prop('checked')) { jd.default_subject_fl = 1; } else { jd.default_subject_fl = 0; }
49395    	if (j.find('#Default_Body_fl').prop('checked')) { jd.default_body_fl = 1; } else { jd.default_body_fl = 0; }
49396    	
49397    	if (isPreview) { jd.preview_fl = true; }
49398    	//if (isSendSample) { jd.send_sample_fl = true; }
49399    	if (!UTIL.isEmpty(id)) { jd.message_auto_marketing_id = id; }
49400    	
49401    	GLO.UI.Form.beginProcessing(jsave);
49402    	
49403        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
49404            .success(function(data, textStatus, jqXHR) {
49405                var jdata = $(data);
49406                
49407                if (!UTIL.isEmpty(jdata.attr('warning'))) {
49408                	GLO.Popup.Warning.open(jdata.outerHTML(), 'Unable to Save');
49409                	return;
49410                }
49411                
49412                _updateGrid(data, id, days, daysText, sg, svc, svcText, subject, msg, null, jd.default_subject_fl, jd.default_body_fl);
49413                _initGrid();
49414                
49415                if (isPreview) {
49416                	GLO.UI.Form.resetProcessing();
49417                	_displayPreview(data);
49418                } else {
49419                	GLO.Popup.close(j);
49420                }
49421            })
49422            .error(function(jqXHR, textStatus, errorThrown) {
49423                GLO.UI.Form.resetProcessing();
49424                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
49425            });
49426	}
49427	
49428	return _conMMAuto;
49429})();
49430
49431GLO.Image = (function() {
49432    function _constructor() { }
49433    
49434    var repressClick = false;
49435    _constructor.current;
49436
49437    _constructor.init = function() {
49438        if (GLO.Info.isIPad) {					//= <img onload=''> --> does NOT reliably fire on the iPad.
49439            GLO.Image.resizeLargeImage();
49440        }
49441    }
49442    
49443    _constructor.initTouch = function() {
49444    	var j = $('#frmEditImg');
49445    	
49446    	if (j.length > 0) {
49447    		var jbtns = j.find('.cancelButton, .btnSave > a, .btnDelete > a');
49448    	} else {
49449    		var j = $('#frmPhotoEditor');
49450    		var jbtns = j.find('.btnCancel > a, .btnSave > a');
49451    	}
49452    	
49453    	_changeOnClickToOnTouchStart(jbtns);
49454    	
49455    	if (GLO.Info.isMobile(true)) {
49456			$('#hd-parent').remove();
49457		}
49458		
49459		if (j.find('#noImage').length > 0) {
49460    		j.find('#btnDelete').remove();
49461    		$('#buttonRow').css({ "margin-top": "120px" });
49462    		
49463    		j.find('#buttonRow .left').addClass('center');
49464    	} else if (GLO.Info.isMobile()) {
49465    		j.find('#buttonRow .btnDelete').css({ "position": "relative", "display": "block", "right": "inherit", "margin": "auto" });
49466    	}
49467    }
49468    
49469    function _changeOnClickToOnTouchStart(jbtns) {
49470    	return;
49471    	/*
49472    	if (!GLO.Info.isMobile(true)) { return; }
49473    	
49474    	for (var i=0; i < jbtns.length; i++) {
49475    		var fn = jbtns.eq(i).attr('onclick');
49476    		jbtns.eq(i).removeAttr('onclick')
49477    		jbtns.eq(i).attr('ontouchstart', fn);
49478    	}
49479    	*/
49480    }
49481    
49482    _constructor.gotoUrl = function(element, url) {
49483    	var jbtn = $(element).parent();
49484    	GLO.UI.Form.beginProcessing(jbtn);
49485    	
49486    	if (url.indexOf('http') !== 0) { url = GLO.Info.http + document.location.host + url; }
49487    	
49488    	setTimeout(function() { document.location = url }, 100);
49489    }
49490    
49491    _constructor.resizeLargeImage = function() {
49492    	return;
49493    	/*
49494        var max = 760;
49495        var img = $('#photoEdit-main img')[0];	
49496        
49497        if (IMAGE_WIDTH_SCALE !== null) {
49498        	if (img.width < max) { return; }
49499        	
49500        	IMAGE_WIDTH_SCALE = (img.width * IMAGE_WIDTH_SCALE)/max
49501        	var iwidth = max;
49502        } else {
49503        	var iwidth = img.width;
49504        }
49505        
49506        if ((iwidth / max) > 1) {
49507	        IMAGE_WIDTH_SCALE = iwidth / max;            //parseInt(img.width / max);
49508	    } else {
49509	        IMAGE_WIDTH_SCALE = 1;
49510	    }
49511	    
49512		iwidth /= IMAGE_WIDTH_SCALE;
49513		img.onload = null;
49514		
49515		if ($('#doc3').width() > max) {
49516			$('#doc3').width(max + 50);
49517		}
49518		
49519		//alert('GLO.Image: iwidth = ' + iwidth + '; IMAGE_WIDTH_SCALE = ' + IMAGE_WIDTH_SCALE + '; max = ' + max);
49520		*/
49521    }
49522    
49523    _constructor.close = function() {
49524            if (window.opener) { window.opener.location.reload(); }
49525            window.close();
49526        }
49527	
49528    _constructor.setSelection = function(jcropAPI) {
49529        var rw = $('#ResizeWidth').val();
49530        var rh = $('#ResizeHeight').val();
49531        var dim = jcropAPI.getBounds();
49532
49533        if (UTIL.isNumber(rw) && UTIL.isNumber(rh)) {
49534            rw = parseInt(rw);
49535            rh = parseInt(rh);
49536
49537            if (rw > dim[0] || rh > dim[1]) {
49538                jcropAPI.setSelect(getRandomSelection(dim));
49539            } else {
49540                jcropAPI.setSelect([0, 0, rw, rh]);
49541            }
49542        } else {
49543	        jcropAPI.setSelect(getRandomSelection(dim));
49544        }
49545    }
49546
49547    function getRandomSelection(dim) {
49548        //var dim = jcropAPI.getBounds();
49549
49550	    return [
49551		    Math.round(Math.random() * dim[0]),
49552		    Math.round(Math.random() * dim[1]),
49553		    Math.round(Math.random() * dim[0]),
49554		    Math.round(Math.random() * dim[1])
49555	    ];
49556    }
49557
49558    _constructor.gotoTemplateHome = function() {
49559        document.location = GLO.Link.WebsiteDomain + $('#Uri_Key_vc').val() + '/home/edit';
49560    }
49561
49562    _constructor.uploadComplete = function(imgName) {
49563        var frm = $('form#OrganizePhotoForm');
49564        
49565        if (frm.length === 1) {
49566	        frm.find('#Image_Uri_vc').val(imgName);
49567	        frm.submit();
49568	    } else {
49569	    	$('#Image_Path_vc').val(imgName);
49570	        $('form#file_upload, #btnDelete').remove();
49571	        $('#frmEditImg').find('.jcrop-holder').remove();
49572	        GLO.UI.Form.beginProcessing($('#frmEditImg .btnSave'));
49573	        
49574	        var jmain = $('#photoEdit-main');
49575	        var imgHtm = '<img src="' + imgName + '" style="max-width: ' + jmain.width() + 'px;">';
49576	        
49577	        jmain.css({ "max-width": jmain.width() + "px", "height": "auto" });
49578	        jmain.find('img:first').replaceWith(imgHtm);
49579	        
49580	        setTimeout(function() {
49581		        var frm = $('#frmEditImg');
49582		        frm.find('#dbAction').val('insert');
49583		        UTIL.DefaultText.deInit(frm);
49584		        frm.attr('action', '').submit();
49585	        }, 100);
49586	    }
49587    }
49588	
49589    _constructor.goToEditor = function(img) {
49590        if (repressClick) { repressClick = false; return false; }
49591        //alert('goToEditor');
49592        document.location.href = GLO.Link.Page.Provider.WebTemplate + 'photoEditor?img=' + $(this).attr('id');
49593    }
49594
49595    _constructor.remove = function(ev, dropObj) {
49596        dropObj.helper.remove();
49597        //alert('GLO.Image.remove()');
49598
49599        var uri = GLO.Link.Page.Provider.WebTemplate + 'DeletePhoto';
49600        var id = dropObj.helper.attr('id');
49601
49602        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { Template_Home_Image_id: id } })
49603            .success(function(data, textStatus, jqXHR) {
49604                //alert("success:" + data + '\n\ndivID = ' + jDiv.html());
49605            })
49606            .error(function(jqXHR, textStatus, errorThrown) {
49607                //alert("error: remove()\n" + textStatus);
49608            })
49609    }
49610    
49611    _constructor.removeAsk = function() {
49612        var msg = '<div id="pop-confirm-image-delete" style="letter-spacing: 1px;">' + SA.Resource.DeleteImageConfirm + '?</div>';
49613        GLO.Popup.Confirm(msg, GLO.Image.removeConfirmed);
49614        
49615        if (GLO.Info.isMobile(true)) {
49616        	var jpop = $('.pop-confirm.glopop');
49617        	
49618        	setTimeout(function() {
49619	        	var btnClose = jpop.find('a.modalClose, .btnNo > a');
49620	        	
49621	        	for (var i=0; i < btnClose.length; i++) {
49622	        		btnClose.eq(i).removeAttr('onclick');
49623	        		btnClose.eq(i).attr('ontouchstart', 'GLO.Popup.close()');
49624	        	}
49625	        	
49626	        	jpop.find('.btnYes > a').attr('ontouchstart', 'GLO.Image.removeConfirmed()').removeAttr('onclick');
49627	        }, 400);
49628        }
49629    }
49630    
49631    _constructor.removeConfirmed = function() {
49632        $('#Image_Path_vc').val('');
49633        
49634        var frm = $('#frmEditImg');
49635        frm.find('#dbAction').val('delete');
49636        //UTIL.DefaultText.deInit(frm);
49637        
49638        var jbtn = $('#frmEditImg').find('.btnDelete');
49639		var path = document.location.pathname.toLowerCase();
49640		
49641		GLO.UI.Form.beginProcessing(jbtn);
49642		GLO.UI.Form.beginProcessing( $('#pop-confirm-image-delete').closest('.glopop').find('.btnYes') );
49643        
49644        if ((path === '/provider/aboutphoto/' || path === '/provider/emailimage') && UTIL.isEmpty(GLO.Uri.query('staff'))) {
49645        	if (path === '/provider/emailimage') {
49646        		var url = GLO.Link.Object.Provider.Ajax + 'RemoveEmailBannerImage';
49647        	} else {
49648        		var url = GLO.Link.Object.Provider.Ajax + 'RemoveAboutImage';
49649        	}
49650        	
49651	        $.ajax({ "type": "POST", "url": url, "cache": false })
49652	            .success(function(data, textStatus, jqXHR) {
49653	                GLO.Popup.Success.open('Image Deleted');
49654	                
49655	                setTimeout(function() {
49656	                	location.reload();				//GLO.UI.Form.resetProcessing(jbtn);
49657	                }, 150);
49658	            }).error(function(jqXHR, textStatus, errorThrown) {
49659	                GLO.UI.Form.resetProcessing(jbtn);
49660	                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
49661	            });
49662        } else {
49663        	var jqxhr = $.ajax({ type: "POST", url: document.location.href, "cache": false, data: frm.serialize() })
49664            	.success(function(data, textStatus, jqXHR) {
49665            		GLO.Popup.Success.open('Image Deleted');
49666	                
49667	                setTimeout(function() {
49668	                	var backUrl = GLO.Uri.query('back');
49669	            		
49670	            		if (!UTIL.isEmpty(backUrl)) {
49671	            			document.location = GLO.Info.http + document.location.host + backUrl;
49672	            		} else if (path.startsWith('/provider/giftcardimage')) {
49673	            			document.location.href = document.location.origin + '/' + GLO.Data.provider.urikey + '/GiftCard?IsEdit=1';
49674	            		} else {
49675	            			document.location.href = document.location.origin + '/wizard/website';
49676	            		}
49677	            	}, 150);
49678            	})
49679	        .error(function(jqXHR, textStatus, errorThrown) {
49680	            GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
49681	        });
49682        	
49683        	//frm.attr('action', '').submit();
49684        }
49685    }
49686	
49687    _constructor.updateSortOrder = function(ev, dropObj) {
49688        repressClick = true;
49689        
49690        var id = dropObj.item.attr('id');
49691        var old_sort_sr = parseInt(dropObj.item.attr('order_sr'));
49692        
49693        if (dropObj.item.prev().length > 0) {
49694        	var new_sort_sr = UTIL.coalesceInt(dropObj.item.prev().attr('order_sr')) + 1;
49695        } else if (dropObj.item.next().length > 0) {
49696        	var new_sort_sr = UTIL.coalesceInt(dropObj.item.next().attr('order_sr')) - 1;
49697        	if (new_sort_sr < 0) { new_sort_sr = 0; }
49698        } else {
49699        	return;		//= drop in trash-bin
49700        }
49701        
49702        if ( UTIL.isEmpty(new_sort_sr) || new_sort_sr == old_sort_sr ) { return; }
49703        
49704        var imgid, new_sort_sr, row, xml = '';
49705        var imgList = $('#sortable li');
49706        
49707        for (var i=0; i < imgList.length; i++) {
49708            imgid = imgList.eq(i).attr('id');
49709            imgList.eq(i).attr('order_sr', (i + 1));
49710            
49711            xml += '<li image_id="' + imgid + '" order_sr="' + (i + 1) + '"/>';
49712        }
49713        
49714        var uri = GLO.Link.Page.Provider.WebTemplate + 'ReOrderPhotos';
49715		var ol = UTIL.htmlEncode('<ol>' + xml + '</ol>');									//var jd = { Template_Home_Image_id: id, Old_Order_sr: old_sort_sr, New_Order_sr: new_sort_sr };
49716		
49717        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "order_xml": ol } })
49718            .success(function(data, textStatus, jqXHR) {
49719                //alert("success:" + data + '\n\ndivID = ' + jDiv.html());
49720            })
49721            .error(function(jqXHR, textStatus, errorThrown) {
49722                //alert("error: updateSortOrder()\n" + textStatus);
49723                var abc = 123;
49724            });
49725    }
49726    
49727    return _constructor;
49728})();
49729
49730
49731GLO.Image.Crop = (function() {
49732    function _conCrop() { }
49733    
49734    _conCrop.current;
49735    _conCrop.jcrop_api; _conCrop.boundx; _conCrop.boundy;      // Create variables (in this scope) to hold the API and image size
49736	
49737	_conCrop.init = function(aspectRatio, target) {
49738		//_initPageWidth();
49739		
49740		if (target === undefined) { target = $('#target'); }
49741		if (target.length === 0) { target = $('#crop-image'); }
49742		
49743		target.Jcrop({
49744                onChange: GLO.Image.Crop.updatePreview, onSelect: GLO.Image.Crop.updatePreview,
49745                allowResize: true, allowSelect: true,
49746                aspectRatio: aspectRatio,
49747                bgFade: true, bgOpacity: .3,			//outerImage: '/_framework/ref-design/jCrop/demos/demo_files/sagomod.jpg',
49748			    setSelect: [0, 0, 700, 420]             //the home page's Slicebox image rotator --> width: 700px; height: 420px; 
49749            }, function() {
49750                var bounds = this.getBounds();          // Use the API to get the real image size
49751                _conCrop.boundx = bounds[0];
49752                _conCrop.boundy = bounds[1];
49753                
49754                _conCrop.jcrop_api = this;                       // Store the API in the jcrop_api variable
49755                
49756                if (aspectRatio === 0) {
49757                	var aRatio = $('#AspectRatio').val();   //Set aspect ratio
49758			        if (UTIL.isNumber(aRatio)) {
49759			            aRatio = parseFloat(aRatio);
49760			            //alert('aRatio = ' + aRatio);
49761			            //jcrop_api.setOptions( { aspectRatio: 2/5 } ); 
49762			            _conCrop.jcrop_api.setOptions( { aspectRatio: aRatio } ); 
49763			        }
49764					
49765			        GLO.Image.setSelection(_conCrop.jcrop_api);
49766			        //_initPageWidth();
49767                } else {
49768                	//_initPageWidth2();
49769                }
49770                
49771                UI.setAccessKey(document, null, GLO.Image.Crop.save);
49772            }
49773        );
49774	}
49775	
49776	function _initPageWidthMobile() {
49777		$('#doc3').css({ "width": "98%" });
49778		//$('#photoEdit-main').css('margin-left', marginLeft + 'px');
49779	}
49780	
49781	function _initPageWidth() {
49782		if (GLO.Info.isMobile()) {
49783			//_initPageWidthMobile();
49784			return;
49785		}
49786		
49787		var tmpWidth = $('#target').css('width');
49788		if (UTIL.isEmpty(tmpWidth)) { tmpWidth = $('#crop-image').css('width'); }
49789		
49790		if (tmpWidth) {
49791			tmpWidth = parseInt(tmpWidth.replace('px', '')) + 60;      //set the width of #doc3
49792	        
49793	        if (tmpWidth < 750) {
49794	        	tmpWidth = 750;
49795	        } else if (GLO.Info.isIPad && tmpWidth > 760) {
49796	        	tmpWidth = 760;
49797	        }
49798	        
49799	        $('#doc3').css('width', tmpWidth + 'px');
49800        }
49801	}
49802	
49803	function _initPageWidth2() {
49804		if (GLO.Info.isMobile()) {
49805			_initPageWidthMobile();
49806			return;
49807		}
49808		
49809		var marginLeft = 20;
49810		var tmpWidth = parseInt($('#target').css('width').replace('px', ''));
49811		if (UTIL.isEmpty(tmpWidth)) { parseInt($('#target').css('width').replace('px', '')); }
49812        
49813        if (tmpWidth < 750) { 
49814            marginLeft = parseInt((750 - 25 - tmpWidth) / 2);
49815            //alert('tmpWidth = ' + tmpWidth + '; marginLeft = ' + marginLeft);
49816            tmpWidth = 750;
49817        } else {
49818            //alert('tmpWidth = ' + tmpWidth);
49819            tmpWidth += 50;
49820        }
49821        
49822        $('#doc3').css('width', tmpWidth + 'px');
49823    	$('#photoEdit-main').css('margin-left', marginLeft + 'px');
49824    }
49825	
49826    _conCrop.updatePreview = function(c) {
49827        _conCrop.current = c;
49828
49829        if (parseInt(c.w) > 0) {
49830            var rx = 100 / c.w;
49831            var ry = 100 / c.h;
49832
49833            $('#preview').css({
49834                width: Math.round(rx * _conCrop.boundx) + 'px',
49835                height: Math.round(ry * _conCrop.boundy) + 'px',
49836                marginLeft: '-' + Math.round(rx * c.x) + 'px',
49837                marginTop: '-' + Math.round(ry * c.y) + 'px'
49838            });
49839        }
49840    }
49841    
49842    _conCrop.save = function() {
49843        $('#x').val(parseInt(_conCrop.current.x * IMAGE_WIDTH_SCALE));
49844        $('#y').val(parseInt(_conCrop.current.y * IMAGE_WIDTH_SCALE));
49845        $('#width').val(parseInt(_conCrop.current.w * IMAGE_WIDTH_SCALE));
49846        $('#height').val(parseInt(_conCrop.current.h * IMAGE_WIDTH_SCALE));
49847        
49848        var frm = $('#frmEditImg, #frmPhotoEditor');
49849        frm.find('#dbAction').val('update');
49850        
49851        UTIL.DefaultText.deInit(frm);
49852        GLO.UI.Form.beginProcessing(frm.find('.btnSave:visible'));
49853        
49854        //alert('GLO.Image.Crop.save(), _conCrop.current .x/.y + width/height = ' + _conCrop.current.x + ' / ' + _conCrop.current.y + ' + ' + _conCrop.current.w + ' / ' + _conCrop.current.h);
49855        window.setTimeout(function() { frm.attr('action', '').submit(); }, 200);
49856    }
49857    
49858    _conCrop.rotate = function(element, fnSave) {
49859    	var degrees = 90;
49860    	var img = $('.jcrop-holder:visible img:last');
49861        
49862        if (img.length === 0) {
49863        	img = $('img#crop-preview');
49864        	if (UTIL.isEmpty(fnSave)) { fnSave = SA.Uploader.Crop.save; }
49865        }
49866        
49867        SA.Uploader.Crop.rotate(img[0], degrees);
49868    }
49869    
49870    _conCrop.preview = function(element, fnSave) {
49871        var img = $('.jcrop-holder:visible img:last');
49872        
49873        if (img.length === 0) {
49874        	img = $('img#crop-preview');
49875        	if (UTIL.isEmpty(fnSave)) { fnSave = SA.Uploader.Crop.save; }
49876        }
49877        
49878        var xOld = 0, yOld = 0;
49879        var wOld = img.width();
49880        var hOld = img.height();
49881        
49882        if (!_isValidImage()) { return; }
49883        
49884        var xNew = parseInt(_conCrop.current.x * IMAGE_WIDTH_SCALE);
49885        var yNew = parseInt(_conCrop.current.y * IMAGE_WIDTH_SCALE);
49886        var wNew = parseInt(_conCrop.current.w * IMAGE_WIDTH_SCALE);
49887        var hNew = parseInt(_conCrop.current.h * IMAGE_WIDTH_SCALE);
49888        
49889        //alert('GLO.Image.Crop.save(), _conCrop.current .x/.y + width/height = ' + _conCrop.current.x + ' / ' + _conCrop.current.y + ' + ' + _conCrop.current.w + ' / ' + _conCrop.current.h);
49890        //fnSave(xOld, yOld, wOld, hOld, xNew, yNew, wNew, hNew);
49891        
49892        if (UTIL.isEmpty(fnSave)) { fnSave = SA.Uploader.Crop.preview; }
49893        
49894        fnSave(img[0], xNew, yNew, wNew, hNew);
49895    }
49896    
49897    function _isValidImage() {
49898    	if (_conCrop.current !== undefined && _conCrop.current.w > 0 && _conCrop.current.h > 0) { return true; }
49899    	if (GLO.Info.isMobile(true)) {
49900    		var click = 'Please touch the image and drag your finger to select the section of the image you would like';
49901    	} else {
49902    		var click = 'Please click the image and drag your mouse to select the section of the image you would like';
49903    	}
49904    	
49905    	var h1 = '<h1 class="friendly-msg2">Select Section of Image to Crop</h1>';
49906    	var msg = '<div class="friendly-msg4" style="max-width: 520px;">' + click + '</div>';
49907    	
49908    	new GLO.Popup.Info('<div>' + h1 + msg + '</div>');
49909    	return false;
49910    }
49911    
49912    return _conCrop;
49913})();
49914
49915
49916if (typeof GLO === 'undefined') { GLO = {}; }
49917if (GLO.Template === undefined) { GLO.Template = {}; }
49918
49919GLO.Template.CustomizeNewClientForm = (function() {
49920    function _cCustomizeNewClientForm() { }
49921    
49922    _cCustomizeNewClientForm.init = function() {
49923    	var jcontainer = $('#customize-form');
49924		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
49925		
49926		jcontainer.find('input:text, textarea, .sa-text-editor').on('keyup', function() {
49927			jcontainer.find('.btnSave > a').addClass('unsaved');
49928		});
49929		jcontainer.find('input, select, textarea, .sa-text-editor').on('change', function() {
49930			jcontainer.find('.btnSave > a').addClass('unsaved');
49931		});
49932		
49933		var jtext = jcontainer.find('.sa-text-editor');
49934		SA.TextEditor.init(jtext, 'New Client Form Message');
49935		
49936		_cCustomizeNewClientForm.changeType();
49937		
49938		if (!UTIL.isEmpty(highlight)) {
49939			var jhigh = $('#' + highlight);
49940    		UI.highlight(jhigh, 100, 9500, true);
49941		}
49942		
49943		_initFieldTable(jcontainer);
49944		
49945		jcontainer.find('input:checkbox').on('change', GLO.Template.CustomizeNewClientForm.changeFieldBox);
49946    }
49947    function _initFieldTable(jcontainer) {
49948    	_setConfigRow('new-client-full-name', GLO.Data.provider.new_client_full_name_cd);
49949    	_setConfigRow('new-client-mobile-phone', GLO.Data.provider.new_client_mobile_phone_cd);
49950    	_setConfigRow('new-client-opt-in', GLO.Data.provider.new_client_optin_cd);
49951    	_setConfigRow('new-client-other-phone', GLO.Data.provider.new_client_other_phone_cd);
49952    	_setConfigRow('new-client-email', GLO.Data.provider.new_client_email_cd);
49953    	
49954    	_setConfigRow('new-client-zip', GLO.Data.provider.new_client_zip_cd);
49955    	_setConfigRow('new-client-address', GLO.Data.provider.new_client_address_cd);
49956    	
49957    	_setConfigRow('new-client-birthday', GLO.Data.provider.new_client_birthday_cd);
49958    	_setConfigRow('new-client-refer-type', GLO.Data.provider.new_client_refer_type_cd);
49959    	_setConfigRow('new-client-refer-by', GLO.Data.provider.new_client_refer_by_cd);
49960    }
49961    function _setConfigRow(rowId, value) {
49962    	var tr = $('#customize-form-display-fields').find('tbody > tr#' + rowId);
49963    	
49964    	if (value == 0 || value == 99) {
49965    		tr.find('.new-client-form-hide :checkbox').prop('checked', true);
49966    	}
49967    	
49968    	if (value == 10 || value == 19 || value == 26) {
49969    		tr.find('.new-client-form-display-staff :checkbox').prop('checked', true);
49970    	}
49971    	if (value == 15 || value == 19 || value == 21) {
49972    		tr.find('.new-client-form-display-client :checkbox').prop('checked', true);
49973    	}
49974    	
49975    	if (value == 20 || value == 21 || value == 29) {
49976    		tr.find('.new-client-form-require-staff :checkbox').prop('checked', true);
49977    	}
49978    	if (value == 25 || value == 26 || value == 29) {
49979    		tr.find('.new-client-form-require-client :checkbox').prop('checked', true);
49980    	}
49981    }
49982    
49983    _cCustomizeNewClientForm.changeFieldBox = function() {
49984    	var td = $(event.currentTarget).closest('td');
49985    	var tr = td.closest('tr');
49986    	
49987    	if (td.hasClass('new-client-form-hide')) {
49988    		tr.find('.new-client-form-display :checkbox, .new-client-form-require :checkbox').prop('checked', false);
49989    		return;
49990    	
49991    	} else if (td.hasClass('new-client-form-display-staff')) {
49992    		tr.find('.new-client-form-require-staff :checkbox').prop('checked', false);
49993    	} else if (td.hasClass('new-client-form-display-client')) {
49994    		tr.find('.new-client-form-require-client :checkbox').prop('checked', false);
49995    	
49996    	} else if (td.hasClass('new-client-form-require-staff')) {
49997    		tr.find('.new-client-form-display-staff :checkbox').prop('checked', false);
49998    	} else if (td.hasClass('new-client-form-require-client')) {
49999    		tr.find('.new-client-form-display-client :checkbox').prop('checked', false);
50000    	}
50001    	
50002    	tr.find('.new-client-form-hide :checkbox').prop('checked', false);
50003    }
50004    _cCustomizeNewClientForm.changeType = function() {
50005    	var jcontainer = $('#customize-form');
50006    	var formType = jcontainer.find('#New_Client_Form_cd').val();
50007    	
50008    	if (formType == 0) {
50009    		jcontainer.find('.customize-form-simple').addClass('hide');
50010    		jcontainer.find('.customize-form-standard').removeClass('hide');
50011    	} else {
50012    		jcontainer.find('.customize-form-standard').addClass('hide');
50013    		jcontainer.find('.customize-form-simple').removeClass('hide');
50014    	}
50015    }
50016    
50017    _cCustomizeNewClientForm.helpReferType = function() {
50018    	var header = 'Referral Type';
50019    	var fnNote = 'GLO.Uri.gotoUri2(\'help?helloback=advanced&tabback=help#tab=appointment&id=calendar-appt-add-note\')';
50020    	var bNote = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnNote + '">Appointment Staff Note popup</a>';
50021    	
50022    	var bReferType = '<b class="narrow-text">Referral Type</b>';
50023    	var bForm = '<b class="narrow-text">New Client Form</b>';
50024    	
50025    	var fnClientList = 'GLO.Uri.gotoUri2(\'message/ClientList?start=4/16/2026&end=5/16/2026&minservice=1&highlight=refer-filter-container\')';
50026    	var bClientList = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnClientList + '">Client List <small>(+ send message blast)</small></a>'
50027    	
50028    	var fnTicketHistory = 'GLO.Uri.gotoUri2(\'reports/TicketHistory?highlight=group-by-column\')';
50029    	var bTicketHistory = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnTicketHistory + '">Ticket History <small>report</small></a>'
50030    	
50031    	var msg1 = '<p>Can use ' + bReferType + ' to view reports of how new clients are finding you</p>';
50032    	var msg2 = '<p>When ' + bReferType + ' is displayed to staff on the ' + bForm + ', then it is also dis
50032played on the' + bNote + '</p>';
50033    	var msg3 = '<p>Can filter the ' + bClientList + ' + ' + bTicketHistory + ' by ' + bReferType + '</p>';
50034    	
50035    	var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + msg3 + '</div>';
50036    	GLO.Popup.Info.openSimple(htm, header);
50037    }
50038    _cCustomizeNewClientForm.helpZip = function() {
50039    	var header = 'Zip Code';
50040    	var fnNote = 'GLO.Uri.gotoUri2(\'help?helloback=advanced&tabback=help#tab=appointment&id=calendar-appt-add-note\')';
50041    	var bNote = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnNote + '">Appointment Staff Note popup</a>';
50042    	
50043    	if (GLO.Data.provider.country == 'CA') {
50044    		header = 'Post Code';
50045    	}
50046    	
50047    	var bZip = '<b class="narrow-text">' + header + '</b>';
50048    	var bForm = '<b class="narrow-text">New Client Form</b>';
50049    	
50050    	var fnClientList = 'GLO.Uri.gotoUri2(\'message/ClientList?start=4/16/2026&end=5/16/2026&minservice=1&highlight=refer-filter-container\')';
50051    	var bClientList = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnClientList + '">Client List <small>(+ send message blast)</small></a>'
50052    	
50053    	var fnTicketHistory = 'GLO.Uri.gotoUri2(\'reports/TicketHistory?highlight=group-by-column\')';
50054    	var bTicketHistory = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnTicketHistory + '">Ticket History <small>report</small></a>'
50055    	
50056    	var msg1 = '<p>Can use ' + bZip + ' to view reports of where clients are coming from</p>';
50057    	var msg2 = '<p>When ' + bZip + ' is displayed to staff on the ' + bForm + ', then it is also displayed on the' + bNote + '</p>';
50058    	var msg3 = '<p>Can filter the ' + bClientList + ' + ' + bTicketHistory + ' by ' + bZip + '</p>';
50059    	
50060    	var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + msg3 + '</div>';
50061    	GLO.Popup.Info.openSimple(htm, header);
50062    }
50063    _cCustomizeNewClientForm.helpBirthday = function() {
50064    	var header = 'Birthday';
50065    	
50066    	var fnCommunicate = 'GLO.Uri.gotoUri2(\'message/Birthday\')';
50067    	var bCommunicate = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnCommunicate + '">Happy Birthday Emails</a>';
50068    	
50069    	var fnClientList = 'GLO.Uri.gotoUri2(\'message/ClientList?start=4/16/2026&end=5/16/2026&minservice=1&highlight=refer-filter-container\')';
50070    	var bClientList = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnClientList + '">Client List <small>(+ send message blast)</small></a>'
50071    	
50072    	var bBirthday = '<b class="narrow-text">Birthday</b>';
50073    	var bForm = '<b class="narrow-text">New Client Form</b>';
50074    	var bArrow = '<b class="html-arrow"></b>';
50075    	
50076    	var msg1 = '<p>Can use ' + bBirthday + ' as a marketing feature to run birthday discounts and send ' + bCommunicate + '</p>';
50077    	var msg2 = '<p>Can require birthday when have age restricted services, classes, or events ' + bBirthday + ' ' + bArrow + ' this will require clients enter birthday day, month, and year</p>';
50078    	var msg3 = '<p>Can filter the ' + bClientList + ' by ' + bBirthday + '</p>';
50079    	
50080    	var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + msg3 + '</div>';
50081    	GLO.Popup.Info.openSimple(htm, header);
50082    }
50083    _cCustomizeNewClientForm.helpEmail = function() {
50084    	var header = 'Automatic Login Link';
50085    	var fnCommunicate = 'GLO.Uri.gotoUri2(\'provider/manage/message?highlight=email-to-client-list\')';
50086    	var bCommunicate = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnCommunicate + '">free ways you can communicate with clients</a>';
50087    	
50088    	var bEmail = '<b class="narrow-text">Email</b>';
50089    	var bForm = '<b class="narrow-text">New Client Form</b>';
50090    	
50091    	var msg1 = '<p>By default, ' + bEmail + ' is required on the ' + bForm + ' filled out by clients + optional when filled out by staff</p>';
50092    	var msg2 = '<p>We recommend using the default settings because of all the ' + bCommunicate + ' by ' + bEmail + '</p>';
50093    	
50094    	var htm = '<div id="pop-info-new-client-form-email">' + msg1 + msg2 + '</div>';
50095    	GLO.Popup.Info.openSimple(htm, header);
50096    }
50097    _cCustomizeNewClientForm.helpAutoLoginLink = function() {
50098    	var header = 'Automatic Login Link';
50099    	var fnAutoLink = 'GLO.Uri.gotoUri2(\'provider/manage/advanced?open=tab-help&amp;popup=how-to-guide-online-booking&amp;step=15\')';
50100    	var blink = '<a class="narrow-text" style="font-weight: bold; color: #139ad2;" onclick="' + fnAutoLink + '">Automatic Login Link</a>';
50101    	
50102    	var msg1 = '<p>' + blink + ' sent to client is a unique link specific to that client';
50103    	var msg2 = '<p>Client can simply click ' + blink + ' to automatically login <i class="narrow-text">(without needing to enter a Username or Password)</i></p>';
50104    	
50105    	var htm = '<div id="pop-info-auto-login-link">' + msg1 + msg2 + '</div>';
50106    	GLO.Popup.Info.openSimple(htm, header);
50107    }
50108    _cCustomizeNewClientForm.helpOptin = function() {
50109    	var iconMkt = '<span class="be-unsubscribe-text" onclick="GLO.UI.openHelp(this)" header="Blocked Text Marketing Messages" title="Client unsubscribed from marketing text messages">'
50110                            + '<img src="http://www.testcdn.com/image/icon/commons-emblem/hand-orange-icon-large.png">'
50111                        + '</span>';
50112    	
50113    	var iconAppt = '<span class="be-unsubscribe-text-appt" onclick="GLO.UI.openHelp(this)" header="Blocked Text Appointment Messages" title="Client unsubscribed from appointment text messages like confirmations, reminders, and follow-ups">'
50114		    				+ '<img src="http://www.testcdn.com/image/icon/knob/RemoveRed.png" style="margin-left: 4px; margin-bottom: 2px; cursor: pointer;">'
50115		    			+ '</span>';
50116    	
50117    	var msg1 = '<p>By default clients are opted-in to text reminders and text marketing</p>';
50118    	var msg2 = '<p style="margin: 20px 0;">When a client unchecks the opt-in box, only the client can re-check it '
50119    			+ '<span class="narrow-text">(i.e. if a client opts-out, a staff member cannot opt-in the client | only the client can do that)</span></p>';
50120    	var msg3 = '<p>You can tell if the client opted out of text messages if you see either of these icons on their profile ' + iconMkt + iconAppt + '</p>';
50121    	
50122    	var htm = '<div id="pop-info-text-optin">' + msg1 + msg2 + msg3 + '</div>';
50123    	var ojpop = GLO.Popup.Info.openSimple(htm, 'Text Message Opt-In', null, true);
50124    }
50125    _cCustomizeNewClientForm.helpCompleteLogin = function() {
50126    	var arrow = '<span class="arrow-right">&#10140;
50126</span>';
50127    	var EasyLogin = '<b class="narrow-text">Easy Login</b>';
50128    	
50129    	var fnAutoLink = 'GLO.Uri.gotoUri2(\'provider/manage/advanced?open=tab-help&popup=how-to-guide-online-booking&step=15\')';
50130    	var aAutoLink = '<a class="narrow-text" onclick="' + fnAutoLink + '" style="font-weight: bold; color: #139ad2;">Automatic Login Link</a>';
50131    	
50132    	var msg1 = '<p>If a client tries to create a duplicate account (using the same email or phone number)</p>';
50133    	
50134    	var list1 = '<li>For clients that have never logged in ' + arrow + ' client automatically logged into existing profile</li>';
50135    	var list2 = '<li>When ' + EasyLogin + ' is enabled ' + arrow + ' client automatically logged into existing profile</li>';
50136		var list3 = '<li>Otherwise client sees message to check their email to complete login ' + arrow + ' client immediately sent email with ' + aAutoLink + '</li>';
50137    	var msg2 = '<ul>' + list1 + list2 + list3 + '</ul>';
50138    	
50139    	var img = '<div style="text-align: center;"><img src="' + GLO.Data.cdnDirectory + 'image/faq/client/new-client/client-signup-check-email.png" style="max-width: 480px;"/></div>';
50140    	var msg3 = '<p style="margin-bottom: 24px;">Client can simply click the ' + aAutoLink + ' in the email to login</p>';
50141    	
50142    	var awesomeList = '<ul class="checkmark-list">'
50143    			+ '<li>Avoid Duplicate Client Profiles' + arrow + ' easier to manage + important for <b>Marketing!</b></li>'
50144    			+ '<li>Simple Login' + arrow + ' No Need for Username + Password</li>'
50145    		+ '</ul>';
50146    	
50147    	var htm = '<div id="pop-info-complete-login">' + awesomeList + msg1 + msg2 + img + msg3 + '</div>';
50148    	var ojpop = GLO.Popup.Info.openSimple(htm, 'Complete Login with Automatic Login Link', null, true);
50149    	ojpop.realign();
50150    	setTimeout(ojpop.realign,  500);
50151    	setTimeout(ojpop.realign, 1500);
50152    	setTimeout(ojpop.realign, 2500);
50153    }
50154    _cCustomizeNewClientForm.helpFields = function() {
50155    	var msg1 = '<p>You can setup what fields you want displayed/required when staff create a new client and when a client submits their inforamtion</p>';
50156    	var msg2 = '<p style="margin-bottom: 0; padding-bottom: 0;">This setup determines the fields on</p>';
50157    	
50158    	var web = GLO.Link.WebsiteDomain + GLO.Data.provider.urikey;
50159    	var fn1 = 'SA.App.openLinkInBrowser(\'' + web + '/login/NewUser\', true)';
50160    	var fn2 = 'SA.Menu.createClient()';
50161    	var fn3 = 'SA.App.openLinkInBrowser(\'' + web + '/RequestAppt\', true)';
50162    	
50163    	var list1 = '<li><a onclick="' + fn1 + '">New Client Form <i class="narrow-text">(client view)</i></a></li>';
50164    	var list2 = '<li><a onclick="' + fn2 + '">New Client Form <i class="narrow-text">(staff view)</i></a></li>';
50165    	var list3 = '<li><a onclick="' + fn3 + '">Request Appointment</a></li>';
50166    	var list4 = '<li>Required fields when update <b class="narrow-text">Existing Client Profile</b> <i class="narrow-text">(both client + staff)</i></li>';
50167    	var ul = '<ul>' + list1 + list2 + list3 + list4 + '</ul>';
50168    	
50169    	var aQuick = '<a onclick="GLO.ClientProfile.openSimpleAdd()">Quick Add Client popup</a>';
50170    	var hasMerchant = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 99) < 40;
50171    	
50172    	if (GLO.Info.isGold()) {
50173    		var uriSignin = location.origin + '/' + GLO.Data.provider.urikey + '/Signin';
50174    		var aSignin = '<a onclick="SA.App.openLinkInBrowser(\'' + uriSignin + '\', true)">Client Self Sign-In Screen</a>';
50175    		
50176    		if (hasMerchant) {
50177    			var footer = 'by new clients on your <b>buy gift card</b>, <b>buy membership</b>, + <b>shopping cart</b> web pages;'
50178    					+ ' it also does not affect the ' + aQuick + ' or the ' + aSignin;
50179    		} else {
50180    			var footer = 'using the ' + aQuick + ' or the ' + aSignin;
50181    		}
50182    	} else {
50183    		if (hasMerchant) {
50184    			var footer = 'by new clients on your buy gift card web page + ' + aQuick;
50185    		} else {
50186    			var footer = 'using the ' + aQuick;
50187    		}
50188    	}
50189    	
50190    	footer = '<div class="help-footer">These settings do not affect how new client profiles are created ' + footer + '</div>';
50191    	
50192    	var htm = '<div id="pop-info-new-client-fields">' + msg1 + msg2 + ul + footer + '</div>';
50193    	var ojpop = GLO.Popup.Info.openSimple(htm, 'Client Field Setup', null, true);
50194    }
50195    
50196    _cCustomizeNewClientForm.save = function() {
50197    	var jcontainer = $('#customize-form');
50198        var ftype = jcontainer.find('#New_Client_Form_cd').val();
50199        var note = UTIL.htmlEncode(DOMPurify.sanitize(jcontainer.find('.sa-editor .sa-text-editor')[0].innerHTML));
50200        var trs = jcontainer.find('#customize-form-display-fields').find('tbody > tr');
50201        
50202        var url = GLO.Link.WebsiteDomain + 'wizard/website/CustomizeNewClientForm';
50203        var jd = { "ftype": ftype, "note": note }
50204        
50205        for (var i=0; i < trs.length; i++) {
50206        	var tr = trs.eq(i);
50207        	var isHide = tr.find('.new-client-form-hide :checkbox').prop('checked');
50208        	var isDisplayClient = tr.find('.new-client-form-display-client :checkbox').prop('checked') || tr.find('.new-client-form-display-client .checkmark-icon').length;
50209        	var isDisplayStaff = tr.find('.new-client-form-display-staff :checkbox').prop('checked') || tr.find('.new-client-form-display-staff .checkmark-icon').length;
50210        	
50211        	var isRequireClient = tr.find('.new-client-form-require-client :checkbox').prop('checked') || tr.find('.new-client-form-require-client .checkmark-icon').length;
50212        	var isRequireStaff = tr.find('.new-client-form-require-staff :checkbox').prop('checked') || tr.find('.new-client-form-require-staff .checkmark-icon').length;
50213        	
50214        	if (isHide) {
50215        		var displayClientCode = 99;
50216        	} else if (isRequireClient && isRequireStaff) {
50217        		var displayClientCode = 29;
50218        	
50219        	} else if (isRequireClient) {
50220        		if (isDisplayStaff) {
50221        			var displayClientCode = 26;
50222        		} else {
50223        			var displayClientCode = 25;
50224        		}
50225        	} else if (isRequireStaff) {
50226        		if (isDisplayClient) {
50227        			var displayClientCode = 21;
50228        		} else {
50229        			var displayClientCode = 20;
50230        		}
50231        	} else if (isDisplayClient && isDisplayStaff) {
50232        		var displayClientCode = 19;
50233        	} else if (isDisplayClient) {
50234        		var displayClientCode = 15;
50235        	} else if (isDisplayStaff) {
50236        		var displayClientCode = 10;
50237        	} else {
50238        		var displayClientCode = 0;
50239        	}
50240        	
50241        	jd[trs.eq(i).attr('column')] = displayClientCode;
50242        }
50243        
50244        var jsave = jcontainer.find('.btnSave');
50245        GLO.UI.Form.beginProcessing(jsave);
50246        
50247        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
50248            .success(function(data, textStatus, jqXHR) {
50249                GLO.Popup.Success.open('Changes Saved', 'New Client Form');
50250                GLO.UI.Form.resetProcessing();
50251                jcontainer.find('.btnSave .unsaved').removeClass('unsaved');
50252            })
50253            .error(function(jqXHR, textStatus, errorThrown) {
50254            	GLO.Popup.Error.open('<div id="pop-error-customize-new-client-form"><p>Unable to Save</p></p>Please Try Again Later</p></div>', 'New Client Form');
50255            	GLO.UI.Form.resetProcessing();
50256            })
50257    }
50258	
50259	return _cCustomizeNewClientForm;
50260})();
50261
50262
50263SA.Admin = (function() {
50264    function _conAdmin() { }
50265    
50266    _conAdmin.init = function() {
50267		_conAdmin.initSearch();
50268		
50269		UI.initTableSorter( $('#provider-config-body-table') );
50270		UI.initTableSorter( $('#provider-config-message-table') );
50271		UI.initTableSorter( $('#provider-config-session-table') );
50272		UI.initTableSorter( $('#provider-config-service-group-table') );
50273		
50274		var jQueryFields = $('#sa-only-fields').find('input, select, textarea');
50275		var saveUrl = GLO.Link.Page.Provider.Home + 'manage/ConfigNotes';
50276		new UI.AutoSave(jQueryFields, saveUrl);
50277	}
50278    _conAdmin.initRecentlyCreatedProviders = function() {
50279    	_conAdmin.initSearch();
50280		
50281		var jrpt = $('#recently-created-providers');
50282        var tbl = jrpt.find('table.tablesorter')
50283        
50284        UI.initTableSorter(tbl);
50285        GLO.Report.CellSummary.initReport(jrpt, true, true);
50286    }
50287    _conAdmin.initSearch = function() {
50288    	$('#hd-parent').remove();
50289		$('#bd').css({ "margin-top": "0" });
50290		$('.shadow-content0').css({ "padding": "0" });
50291		
50292		var j = $('#provider-config');
50293		var pid = j.find('h1').attr('provider_id');			//j.find('#Provider_id').val();
50294		var urlClientLookup = GLO.Link.Object.Provider.Ajax + 'ClientAdminSearch?pid=' + pid;
50295		
50296		$('#client-admin-search').autocomplete({
50297		    source: urlClientLookup, minLength: 2,
50298		    select: function(event, ui) {
50299		        SA.Admin.openClient(ui.item);
50300		    },
50301		    open: function(){
50302		        //$(this).autocomplete('widget').css("z-index", "5900 !important");
50303		        //return false;
50304		    },
50305		});
50306		
50307		UI.initAutoComplete2($('#Staff_or_Provider_Name_vc'), GLO.Link.Object.Provider.Ajax + 'LookupProvider', SA.Admin.lookupProviderSelected);
50308    }
50309    
50310    _conAdmin.lookupProviderSelected = function(event, ui) {
50311    	new GLO.Popup.Processing('Loading ' + ui.item.label + '...');
50312    	
50313    	setTimeout(function() {
50314    		document.location = document.location.protocol + '//' + location.host + '/provider/manage/config?provider=' + ui.item.id;
50315    	}, 400);
50316    }
50317    
50318    _conAdmin.changeProviderDD = function(element) {
50319        new GLO.Popup.Processing('Loading Provider...');
50320    	
50321    	setTimeout(function() {
50322        	document.location = document.location.protocol + '//' + location.host + '/provider/manage/config?provider=' + element.value;
50323        }, 400);
50324    }
50325    
50326    _conAdmin.openClient = function(item) {
50327    	var j = $('#provider-config');
50328		var pid = j.find('h1').attr('provider_id');			//j.find('#Provider_id').val();
50329    	
50330    	var url = GLO.Link.Object.Provider.Ajax + 'ClientAdminSummary?cid=' + item.id + '&pid=' + pid;
50331        
50332        $.ajax({ type: "GET", url: url, "cache": false })
50333            .success( function(data, textStatus, jqXHR) {
50334                var jdata = $(data);
50335                var jpop = new GLO.Popup.Custom(jdata).getPopup().addClass('no-persist');
50336                
50337                jpop.find('.btnSave').remove();
50338                jpop.find('.btnCancel').css({ "float": "none", "letter-spacing": "1px" }).find('>a').text(SA.Resource.Close);
50339            })
50340            .error( function(jqXHR, textStatus, errorThrown) { 
50341                //GLO.UI.Form.resetProcessing();
50342            });
50343    }
50344    
50345    _conAdmin.changeStaffPassword = function(element) {
50346		var tr = $(element).closest('tr').addClass('highlight');
50347		var fnCancel = function() {
50348			$('#provider-config').find('#provider-config-body-table').find('tr.highlight').removeClass('highlight');
50349		}
50350		
50351		var jpop = new GLO.Popup.Prompt('<div id="pop-update-password">' + SA.Resource.EnterNewPassword + '</div>', SA.Admin.saveStaffPassword, fnCancel).getPopup().addClass('no-persist');
50352		jpop.find('textarea').css({ "height": "24px", "letter-spacing": "2px" });
50353		jpop.find('.modalClose, .btnCancel > a').click(fnCancel);
50354	}
50355	
50356	_conAdmin.saveStaffPassword = function(password) {
50357		var j = $('#provider-config');
50358		var tr = j.find('#provider-config-body-table').find('tr.highlight').removeClass('highlight').addClass('highlightPink');
50359		var sid = tr.attr('staff_id');
50360		var pid = j.find('h1').attr('provider_id');			//j.find('#Provider_id').val();
50361		var url = GLO.Link.Object.Provider.Ajax + "UpdatePassword";
50362        
50363        var jpop = $('#pop-update-password').closest('.glopop');
50364        var jbtnEnter = jpop.find('.btnYes').css({ "padding-top": "0" });
50365        GLO.UI.Form.beginProcessing(jbtnEnter);
50366        
50367        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_id": pid, "sid": sid, "password": password } })
50368            .success(function(data, textStatus, jqXHR) {
50369                tr.removeClass('highlightPink').addClass('highlightSuccess').find('.column-password').text(password);
50370                
50371                setTimeout(function() { tr.removeClass('highlightSuccess'); }, 2500);
50372                
50373                GLO.Popup.close(jpop);
50374            })
50375            .error(function(jqXHR, textStatus, errorThrown) {
50376            })
50377	}
50378	
50379	_conAdmin.changeClientPassword = function() {
50380		var jpop = new GLO.Popup.Prompt('<div id="pop-update-password">' + SA.Resource.EnterNewPassword + '</div>', SA.Admin.saveClientPassword).getPopup().addClass('no-persist');
50381		jpop.find('textarea').css({ "height": "24px", "letter-spacing": "2px", "font-size": "larger" });
50382	}
50383	
50384	_conAdmin.saveClientPassword = function(password) {
50385		var j = $('#pop-client-admin-summary');
50386		var cid = j.attr('client_id');
50387		var pid = $('#provider-config').find('h1').attr('provider_id');			//j.find('#Provider_id').val();
50388		var url = GLO.Link.Object.Provider.Ajax + "UpdatePassword";
50389        
50390        var jpop = $('#pop-update-password').closest('.glopop');
50391        var jbtnEnter = jpop.find('.btnYes').css({ "padding-top": "0" });
50392        GLO.UI.Form.beginProcessing(jbtnEnter);
50393        
50394        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: { "provider_id": pid, "cid": cid, "password": password } })
50395            .success(function(data, textStatus, jqXHR) {
50396                j.find('#admin-client-password').text(password);
50397                
50398                GLO.Popup.close(jpop);
50399            })
50400            .error(function(jqXHR, textStatus, errorThrown) {
50401            })
50402	}
50403	
50404	return _conAdmin;
50405})();
50406
50407
50408GLO.Sale = (function() {
50409    function _conSale() { }
50410    
50411    _conSale.init = function() {
50412
50413	}
50414    
50415    return _conSale;
50416})();
50417
50418
50419GLO.Sale.Keypad = (function() {
50420    function _conKeypad() { }
50421    var _includeTax = false, _hasInit = false;
50422    var _otherXml = null;
50423    
50424    _conKeypad.init = function() {
50425		var jkeyboard = $('#sale-keyboard');
50426		
50427		if (false && GLO.Info.isMobile(true)) {									//DEBUG ONLY --> !UTIL.debug &&
50428			jkeyboard.find('.number-keypad').find('span').on('touchstart', GLO.Sale.Keypad.clickKey);
50429		} else {
50430			jkeyboard.find('.number-keypad').find('span').click(GLO.Sale.Keypad.clickKey);
50431		}
50432		
50433		_initTax(jkeyboard);
50434		var amt = GLO.Uri.query('amount');
50435    	
50436    	if (!UTIL.isEmpty(amt)) {
50437    		amt = UTIL.displayMoney(amt, true, true);
50438    		
50439    		for (var i = 0; i < amt.length; i++) {
50440    			var jkey = jkeyboard.find('.number-keypad').find('span.keypad-' + amt.substr(i, 1));
50441    			
50442    			if (GLO.Info.isMobile(true)) {							//DEBUG ONLY --> !UTIL.debug &&
50443    				jkey.trigger('touchstart');
50444    			} else {
50445    				jkey.click();
50446    			}
50447    		}
50448    		
50449    		if (GLO.Uri.query('paymethod') == 10) {
50450    			_conKeypad.enterCardNumber();
50451    		} else if (UTIL.parseBool(GLO.Uri.query('createinvoice'))) {
50452    			_conKeypad.openTicket();
50453    		}
50454    	}
50455    	
50456    	//_initShortcutKeys();
50457    	
50458    	if (GLO.Info.isMobile(true)) {
50459    		new FastClick(document.body);
50460    		//if (GLO.Info.isIPhone && GLO.Info.isIosApp) { GLO.Mobile.iosNativeBridge.call("ActivateSwiper", []); }
50461    		
50462    		if (GLO.Info.isMobile()) {
50463    			$('#mp-initial-menu').find('.fa-map-marker').closest('li').remove();			//= remove "Create Appointment" from mobile menu because this page doesn't allow scrolling height.
50464    			//$('#wait-list-icon, #wait-list-icon-fixed').remove();
50465    		}
50466    		
50467    		_initEmvReader(jkeyboard);
50468    	}
50469	}
50470	
50471	function _initEmvReader(jkeyboard) {
50472		if (!UserPortal.Price.Payment.supportsEmvReader()) { return; }
50473		
50474		jkeyboard.find('#btnEnterCardNumber').click(GLO.Sale.Keypad.openTicketCredit).find('>a').text('Credit Payment');
50475	}
50476	
50477	_conKeypad.openTicketCredit = function() {
50478		GLO.Sale.Keypad.openTicket();
50479		
50480		setTimeout(function() {
50481			var jPricePop = $('#appt-price-popup').closest('.glopop');
50482			jPricePop.find('#Mobile_Payment_Method_cd').find('li[value="10"]').click();
50483		}, 900);
50484	}
50485	
50486	_conKeypad.iosActivateSwiperComplete = function(hasSwiperConnected) {					//return call from ios function "ActivateSwiper"
50487		hasSwiperConnected = UTIL.parseBool(hasSwiperConnected);
50488		
50489		if (innerHeight > 500 && hasSwiperConnected) {
50490			$('#pop-generic-header').after('<div style="letter-spacing: 1px; font-style: italic;">' + SA.Resource.SwipeCardWhenReady + '</div>');
50491		}
50492	}
50493	
50494	function _initTax(jkeyboard) {
50495		if (UTIL.coalesceFloat(GLO.inventoryTax, GLO.serviceTax, 0) === 0) {
50496			if (GLO.Info.roleType > 219) {
50497				var href = GLO.Link.WebsiteDomain + 'provider/inventory#action=inventory-options';
50498				jkeyboard.find('#btnIncludeTax').attr('id', 'btnAddTax').attr('href', href).removeAttr('onclick').find('a').text(SA.Resource.AddTax);
50499			}
50500    	}
50501    	
50502    	var includeTax = $.cookies.get("keypad-include-tax");
50503    	
50504    	if (UTIL.coalesceFloat(GLO.inventoryTax, 0) > 0 && UTIL.isEmpty(includeTax)) {
50505    		_setIncludeTax(true);
50506    	} else if (UTIL.parseBool(includeTax) && !jkeyboard.hasClass('include-tax')) {
50507    		_setIncludeTax(true);
50508    	}
50509	}
50510	
50511	function _initShortcutKeys() {
50512		if (!GLO.Info.isMobile(true)) { return; }			//swipe card on PC inserts numbers, so must disable.
50513		if (_hasInit) { return; }
50514    	_hasInit = true;
50515    	
50516		$(document).on("keydown", function(e) {
50517			if ( ((e.keyCode > 47 && e.keyCode < 58) || e.keyCode === 46 || e.keyCode === 8 || e.keyCode === 187) && !(e.ctrlKey || e.altKey)) {            //= 0-9, DEL, Backspace, '+'
50518	        	var j = $("#sale-keyboard:visible");
50519	        	
50520	        	if (j.length === 0) {
50521	        		return;
50522	        	} else {
50523	        		var jTopPop = GLO.Popup.getTopPopup();
50524	        		if (jTopPop.find('#sale-keyboard:visible').length === 0 && ($('#simplemodal-container').length > 0 || jTopPop.length > 0) ) { return; }
50525	        	}
50526	        	
50527	        	switch (e.keyCode) {
50528                    case 8: var cssKey = 'DEL'; break;
50529                    case 46: var cssKey = 'DEL'; break;
50530                    case 187: var cssKey = 'PLUS'; break;
50531                    
50532                    case 48: var cssKey = '0'; break;
50533                    case 49: var cssKey = '1'; break;
50534                    case 50: var cssKey = '2'; break;
50535                    case 51: var cssKey = '3'; break;
50536                    case 52: var cssKey = '4'; break;
50537                    case 53: var cssKey = '5'; break;
50538                    case 54: var cssKey = '6'; break;
50539                    case 55: var cssKey = '7'; break;
50540                    case 56: var cssKey = '8'; break;
50541                    case 57: var cssKey = '9'; break;
50542	        	}
50543	        	
50544	        	j.find('.number-keypad').find('span.keypad-' + cssKey).click();				//GLO.Sale.Keypad.clickKey
50545	        }
50546	    });
50547	}
50548	
50549	_conKeypad.openPOS = function() {
50550		if (GLO.Info.isMobile(true)) {
50551    		GLO.UI.animate(2);
50552    		
50553    		setTimeout(function() {
50554    			document.location = GLO.Link.WebsiteDomain + 'pos';
50555    		}, 200);
50556    	} else {
50557    		document.location = GLO.Link.WebsiteDomain + 'pos';
50558    	}
50559    	
50560    	return true;
50561	}
50562	
50563	_conKeypad.openKeypad = function(apt) {
50564		var isVisible = ($('#sale-keyboard:visible').length > 0);
50565		var isMobile = GLO.Info.isMobile(true);
50566		
50567		if (apt === 920 || ( (isMobile || isVisible) && (apt === 900 || apt === 910) ) ) {
50568        	if (isMobile) {
50569	    		GLO.UI.animate(2);
50570	    		
50571	    		setTimeout(function() {
50572	    			document.location = GLO.Link.Page.Provider.Home + 'saleKeypad';
50573	    		}, 200);
50574	    	} else {
50575	    		document.location = GLO.Link.Page.Provider.Home + 'saleKeypad';
50576	    	}
50577        	
50578        	return true;
50579        } else if (apt === 900 || apt === 910) {
50580        	GLO.Sale.Keypad.openAsPopup();
50581        	return true;
50582        } else {
50583        	return false;
50584		}
50585	}
50586	
50587	_conKeypad.mustOpenKeypad = function() {
50588		var apt = GLO.Data.Staff.allowedPaymentType;
50589		
50590		/*
50591		if (false && GLO.Info.isIosApp && (apt === 900 || apt === 910 || apt === 920)) {		//disabled to go use web view instead.
50592        	var jd = { "token": $.cookies.get('session'), "min_signature_amount": 5 };
50593        	jd = { "simplesale": jd };
50594	    	jd = [JSON.stringify(jd)];
50595        	
50596        	GLO.Mobile.iosNativeBridge.call("OpenSimpleSale", jd);
50597        	return true;
50598        } else 
50599        */
50600        
50601        if (apt === 930) {
50602        	return _conKeypad.openPOS();
50603        } else {
50604        	return _conKeypad.openKeypad(apt);
50605        }
50606	}
50607	
50608	_conKeypad.openAsPopup = function() {
50609		$("#sale-keyboard").modal();
50610		
50611		var jmodal = $("#simplemodal-container").addClass('is-keypad');
50612	    jmodal.css({ "max-height": "760px", "padding": "0" });
50613	    jmodal.find('.simplemodal-data').css({ "padding": "0" });
50614	    jmodal.find('#sale-keyboard-left, #sale-keyboard-right').remove();
50615	    
50616	    if (!GLO.Info.isMobile()) {
50617	    	jmodal.draggable({ "handle": "h2" }).find('h2').css({ "cursor": "move" });
50618	    }
50619	    
50620	    $.modal.update(720, 635);
50621	    
50622	    _conKeypad.init();
50623	}
50624	
50625	_conKeypad.clickKey = function() {
50626		var jkey = $(this);
50627		var key = jkey.text();
50628		
50629		var jtotal = $('#keyboard-sub-total');
50630		var usingSubTotal = false;
50631		
50632		if (key !== '<') {
50633			if (UTIL.coalesceMoney($('#keyboard-running-total').text().replace('$', '')) > 99999) { return; }
50634			if (UTIL.coalesceMoney(jtotal.text().replace('$', '')) > 999 && key !== '+') { return; }
50635		}
50636		
50637		if (jtotal.hasClass('hide')) {
50638			jtotal = $('#keyboard-running-total');
50639		} else if (key === '<' && parseFloat(jtotal.find('span').text().replace('$', '')) === 0) {
50640			jtotal.addClass('hide');
50641			jtotal = $('#keyboard-running-total');
50642		} else {
50643			jtotal = jtotal.find('span');
50644			usingSubTotal = true;
50645		}
50646		
50647		var total = Math.round(jtotal.text().replace('$', '') * 100);					//jtotal.text().replace('$', '').replace('.', '');
50648		if (!usingSubTotal) { total = _getPreviousTotal(total); }
50649		var isNumber = UTIL.isNumber(key);
50650		
50651		if (isNumber) {
50652			total = UTIL.coalesceMoney((total + key)/100, false, true);
50653			if (!usingSubTotal) { total += _updateTax(total); }
50654		} else if (key === '<') {
50655			total = String(total);
50656			total = UTIL.coalesceMoney(total.substring(0, (total.length - 1))/100, false, true);
50657			if (!usingSubTotal) { total += _updateTax(total); }
50658		} else if (key === '+') {
50659			_add(jkey);
50660			_animateKey(key, jkey, jtotal);
50661			return;
50662		}
50663		
50664		_setTotal(jtotal, total);
50665	}
50666	
50667	function _setTotal(jtotal, total) {
50668		total = UTIL.displayMoney(total, false, true);
50669		if (total === '') { total = '$0.00'; }
50670		jtotal.text(total);
50671	}
50672	
50673	function _getPreviousTotal(total) {
50674		if (!_includeTax) { return total; }
50675		
50676		return Math.round($('#keyboard-total-tax').find('i').text() * 100);
50677		//return $('#keyboard-total-tax').find('i').text().replace('.', '');		//total = String(Math.round(total - _getTax(total)));
50678	}
50679	
50680	function _getTax(total) {
50681		if (!_includeTax) { return 0; }
50682		
50683		//return UTIL.coalesceMoney($('#keyboard-total-tax').find('span').text());
50684		return UTIL.coalesceMoney(total * UTIL.coalesceMoney(GLO.inventoryTax, GLO.serviceTax)/100);
50685	}
50686	
50687	function _updateTax(total) {
50688		var tax = _getTax(total);
50689		_setTax(total, tax)
50690		return tax;
50691	}
50692	
50693	function _setTax(total, tax) {
50694		tax = UTIL.displayMoney(tax, true, false);
50695		total = UTIL.displayMoney(total, true, false);
50696		
50697		if (tax === '') { tax = '0.00'; }
50698		if (total === '') { total = '0.00'; }
50699		
50700		var jtax = $('#keyboard-total-tax');
50701		jtax.find('i').text(total);
50702		jtax.find('span').text(tax);
50703	}
50704	
50705	_conKeypad.includeTax = function() {
50706		_includeTax = !_includeTax;
50707		_setIncludeTax();
50708		
50709		_changeOtherTaxRate();
50710		_setIncludeTaxCookie();
50711	}
50712	
50713	_conKeypad.isIncludeTax = function() {
50714		return _includeTax;
50715	}
50716	
50717	function _setIncludeTax(mustIncludeTax) {
50718		if (mustIncludeTax) { _includeTax = true; }
50719		
50720		var jtotal = $('#keyboard-running-total');
50721		var total = UTIL.coalesceMoney(jtotal.text().replace('$', ''));
50722		var tax = UTIL.coalesceMoney(GLO.inventoryTax, GLO.serviceTax)/100;
50723		
50724		var styleLabel = ' style="display: inline-block; margin: 0; margin-top: 2px; margin-right: 10px; font-size: 108%; color: white;"';
50725		var pct = '<span style="margin-top: 4px; margin-left: 2px; font-size: 108%; color: white;">%</span>';
50726		
50727		if (GLO.Info.isMobile()) {
50728			var msg = '<div> <label for="inventory_tax_rate_pct"' + styleLabel + '>' + SA.Resource.TaxRate + '</label>'
50729						+ '<input id="inventory_tax_rate_pct" type="number" step="0.01" max="5" maxlength="5" style="width: 60px; margin-left: 2px;">' + pct
50730					+ '</div>';
50731		} else {
50732			var msg = '<div style="margin-bottom: 24px;"> <label for="inventory_tax_rate_pct"' + styleLabel + '>' + SA.Resource.PleaseEnterTaxRate + '</label>'
50733							+ '<input id="inventory_tax_rate_pct" type="text" maxlength="5" pattern="[0-9]*" onkeypress="UI.numberOnly(event)" style="width: 50px; margin-left: 2px;">' + pct
50734						+ '</div>';
50735		}
50736		
50737		if (tax == 0) {
50738			var jpop = new GLO.Popup.Prompt(msg, GLO.Sale.Keypad.saveTax).getPopup().addClass('no-persist');
50739			
50740			jpop.find('#val').remove();
50741			jpop.find('.btnYes').removeClass('btnYes').addClass('btnSave').find('a').text('Save');
50742			jpop.find('#inventory_tax_rate_pct').focus();
50743			
50744			return;
50745		}
50746		
50747		if (_includeTax) {
50748			tax = total * tax;
50749			
50750			$('#sale-keyboard').addClass('include-tax');
50751			_setTax(total, tax);
50752			total += tax;
50753		} else {
50754			var jsub = $('#keyboard-total-tax');
50755			subtotal = UTIL.coalesceMoney($('#keyboard-total-tax').find('i').text());
50756			
50757			if (subtotal > 0) {				//if has subtotal just use these values (then deal with JS floating point calculations).
50758				total = subtotal
50759				tax = UTIL.coalesceMoney(jsub.find('span').text());
50760			} else if (total > 0) {
50761				total -= tax;
50762			}
50763			
50764			$('#sale-keyboard').removeClass('include-tax');
50765		}
50766		
50767		total = UTIL.displayMoney(total, false, true);
50768		if (total === '') { total = '$0.00'; }
50769		jtotal.text(total);
50770	}
50771	
50772	function _setIncludeTaxCookie() {
50773		if (_includeTax) { var includeTax = "1"; } else { var includeTax = "0"; }
50774		
50775		//var expireDate = new Date();
50776		//expireDate = new Date(expireDate.setFullYear(expireDate.getFullYear() + 1));
50777		//$.cookies.set("keypad-include-tax", includeTax, { "expiresAt": expireDate });
50778		UTIL.setCookie("keypad-include-tax", includeTax);
50779	}
50780	
50781	_conKeypad.saveTax = function() {
50782		var jpop = $('.pop-prompt').closest('.glopop');
50783		var ptax = UTIL.coalesceMoney(jpop.find('#inventory_tax_rate_pct').val());
50784		
50785		//if (ptax == 0) { GLO.Popup.close(jpop); return; }
50786		
50787		var url = GLO.Link.Object.Provider.Ajax + 'Tax';
50788		
50789		GLO.inventoryTax = ptax;
50790    	_conKeypad.includeTax();
50791    	
50792		GLO.UI.Form.beginProcessing(jpop.find('.btnSave:visible'));
50793		//var ojProcessing = new GLO.Popup.Processing('Setting tax rate...');
50794		//ojProcessing.getPopup().find('.btnOk').remove();
50795    	
50796    	$.ajax({ type: "POST", url: url, "cache": false, data: { "inventory_tax_rate_pct": ptax } })
50797            .success(function(data, textStatus, jqXHR) {
50798                GLO.Popup.close(jpop);
50799            })
50800            .error(function(jqXHR, textStatus, errorThrown) {
50801                GLO.Popup.Error('Unable to change tax.  Please try again later.');
50802                GLO.UI.Form.resetProcessing();
50803                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
50804            });
50805	}
50806	
50807	_conKeypad.animateMove = function(startElement, endElement, pixelsDown, pixelsRight, animateTime, bDoNotMove) {				//to move left or up make # negative
50808		var wrapStartElement = startElement.contents().wrap($('<div>').css('position','absolute')).parent();
50809		if (!UTIL.isNumber(animateTime)) { animateTime = 800; }
50810		
50811		wrapStartElement.animate({ "top": pixelsDown, "left": pixelsRight }, animateTime, function() {
50812		    if (!UTIL.parseBool(bDoNotMove)) { endElement.html(wrapStartElement.html()); }
50813			wrapStartElement.remove();
50814		});
50815	}
50816	
50817	function _animateKey(key, jstart, jend) {
50818		var hgt = 50;
50819		
50820		if (key === '1' || key === '2' || key === '3') {
50821			hgt += 60;
50822		} else if (key === '4' || key === '5' || key === '6') {
50823			hgt += 150;
50824			if (!GLO.Info.isMobile()) { hgt += 30; }
50825		} else if (key === '7' || key === '8' || key === '9') {
50826			hgt += 235;
50827			if (!GLO.Info.isMobile()) { hgt += 70; }
50828		} else if (key === '<' || key === '0') {
50829			hgt += 316;
50830			if (!GLO.Info.isMobile()) { hgt += 110; }
50831		}
50832		
50833		var top = jstart.position().top;
50834		var left = jstart.position().left + jstart.outerWidth()/2 - jstart.width()/2;
50835		
50836		if (GLO.Info.isMobile()) {
50837			var fsize = "200%", margin = "20px", fwgt = "normal";
50838		} else {
50839			var fsize = "400%", margin = "0", fwgt = "bold";
50840		}
50841		
50842		var jcopy = $('<div>' + jstart.text() + '</div>').css({ "position": "absolute", "top": top, "left": left, "margin": margin, "font-size": fsize, "font-weight": fwgt, "color": "white" });
50843		jcopy = jcopy.appendTo($('.number-keypad'));
50844		_conKeypad.animateMove(jcopy, jend, -hgt, 0, 300, true);
50845	}
50846	
50847	function _animateSubtotal() {
50848		var jsub = $('#sale-keyboard-left #sale-subtotal').find('span');
50849		
50850		_conKeypad.animateMove($('#keyboard-total'), jsub, 220, -210);
50851		return;
50852		/*
50853		var jwrapTotal = $('#keyboard-total').contents().wrap($('<div>').css('position','absolute')).parent();
50854		
50855		jwrapTotal.animate({ "top": 220, "left": -210 }, 400, function() {
50856		    var jthis = $(this);
50857		    var text = UTIL.displayMoney(UTIL.coalesceMoney(jthis.text().replace('$', ''), 0) + UTIL.coalesceMoney(jsub.text().replace('$', ''), 0), false, true);
50858		    
50859		    jsub.text(text);
50860		    jwrapTotal.remove();
50861		});
50862		*/
50863	}
50864    
50865    function _add(jkey) {
50866    	var jsub = $('#keyboard-sub-total').find('span');
50867    	
50868    	var top = jkey.position().top;
50869    	var left = jkey.position().left + jkey.outerWidth()/2;
50870    	
50871    	var jstart = $('<div>' + jkey.text() + '</div>').css({ "position": "absolute", "top": top, "left": left, "font-size": "400%" });
50872    	jstart = jstart.appendTo($('.number-keypad'));
50873    	
50874    	var jend = $('#keyboard-running-total');
50875    	
50876    	if (GLO.Info.isMobile()) {
50877    		var a1right = 300;
50878    		var a2top = -330;
50879    		var a2right = -200;
50880    	} else {
50881    		var a1right = 520;
50882    		var a2top = -485;
50883    		var a2right = -530;
50884    	}
50885    	
50886    	if (UTIL.coalesceMoney(jsub.text().replace('$', ''), 0) > 0) {
50887	    	_conKeypad.animateMove(jsub, jend, 0, a1right, 500, true);
50888	    	setTimeout(GLO.Sale.Keypad.addToTotal, 400);
50889    	}
50890    	
50891    	_conKeypad.animateMove(jstart, jsub, a2top, a2right, 600, true);
50892    	setTimeout(function() { $('#keyboard-sub-total').removeClass('hide'); }, 600);
50893    }
50894    
50895    _conKeypad.addToTotal = function() {
50896    	var sub = $('#keyboard-sub-total').find('span').text().replace('$', '');
50897    	
50898    	var prev = $('#keyboard-total-tax').find('i').text().replace('$', '');
50899    	//prev = _getPreviousTotal(prev);
50900    	
50901    	var total = UTIL.coalesceMoney(UTIL.coalesceMoney(sub) + UTIL.coalesceMoney(prev));
50902    	total += _updateTax(total);
50903    	
50904    	var jtotal = $('#keyboard-running-total');
50905    	_setTotal(jtotal, total);
50906    }
50907    
50908    _conKeypad.openTicket = function(isEnterCardNumber, mobileCardData) {
50909    	var price = $('#sale-keyboard.include-tax #keyboard-total-tax').find('i');
50910        
50911        if (price.length > 0) {
50912        	price = price.text().replace('$', '');
50913        } else {
50914        	price = $('#keyboard-running-total').text().replace('$', '');
50915        }
50916        
50917        //$('#sale-keyboard .pop-generic-header').text('in OpenTicket');
50918        
50919        _conKeypad.openTicket2(isEnterCardNumber, price, mobileCardData);
50920    }
50921    
50922    _conKeypad.openTicketEasy = function(payMethod, price) {
50923    	if (GLO.Info.providerPackage == 1) {
50924    		var msg = 'To test payment:<br/>1.Create Appointment<br/>2. Press price (in upper left corner of Appointment Popup)<br/>3. Press payment method <b>Credit</b>';
50925    		GLO.Popup.Info.openSimple(msg, 'Test Payment on Appointment');
50926    	} else {
50927    		_conKeypad.openTicket2(false, price, null, payMethod);
50928    	}
50929    }
50930    _conKeypad.openTicket2 = function(isEnterCardNumber, price, mobileCardData, payMethod) {
50931    	UserPortal.Price.quit();
50932    	
50933    	if (_otherXml !== null) {
50934    		_conKeypad.openTicket3(isEnterCardNumber, price, mobileCardData, payMethod);
50935    		return;
50936    	}
50937    	
50938    	var url = GLO.Link.WebsiteDomain + 'provider/inventory/ItemOther';
50939    	var oj, ajaxRequest;
50940    	
50941    	function fnCancelOpenTicket() {
50942    		if (ajaxRequest && ajaxRequest.abort) {
50943    			ajaxRequest.abort();
50944    		}
50945    		
50946    		if (oj && oj.close) {
50947    			oj.close();
50948    		}
50949    	}
50950    	
50951    	oj = new GLO.Popup.Processing(SA.Resource.CreatingTicket + '...', fnCancelOpenTicket);
50952    	
50953    	ajaxRequest = $.ajax({ type: "GET", url: url, "cache": false })
50954            .success(function(data, textStatus, jqXHR) {
50955                oj.close();
50956                
50957                var li = $('<ul>' + data + '</ul>').find('li')
50958                
50959                if (li.length === 1) {
50960                	_otherXml = li.outerHTML();
50961                	_changeOtherTaxRate();
50962                	_conKeypad.openTicket3(isEnterCardNumber, price, mobileCardData, payMethod);
50963                } else {
50964                	GLO.Popup.Warning('Problem creating ticket.  Please try again');
50965                }
50966            }).error(function(jqXHR, textStatus, errorThrown) {
50967            	GLO.Popup.Warning('Error creating ticket.  Please try again');
50968            });
50969    }
50970    
50971    _conKeypad.openTicket3 = function(isEnterCardNumber, price, mobileCardData, payMethod) {			//warning -> must call 'UserPortal.Price.quit()' before calling this function
50972    	//$('#sale-keyboard .pop-generic-header').text('in OpenTicket3');
50973    	
50974    	UserPortal.Price.inventoryXml = $(_otherXml).attr('price_mn', price).outerHTML();
50975        UserPortal.Price.open(false, true);
50976        UserPortal.Price.isKeypad = true;
50977        
50978        var jPricePop = $('#appt-price-popup').closest('.glopop');
50979        jPricePop.find('#Is_Walkin_fl').prop('checked', true).change();			//if (isEnterCardNumber || GLO.Info.isRetail() || $('.shadow-content0 #sale-keyboard:visible').length > 0) {  }
50980    	
50981    	if (isEnterCardNumber) {
50982    		if (UTIL.coalesceMoney(price, 0) > 0) {
50983    			jPricePop.find('#Payment_Method_cd').val(10).change();
50984    			setTimeout(GLO.Sale.Keypad.openEnterCardManually, 200);
50985    		}
50986        } else if (payMethod > 0) {
50987        	jPricePop.find('#Payment_Method_cd').val(payMethod).change();
50988        }
50989        
50990        if ($('#simplemodal-container #sale-keyboard').length > 0) {
50991        	$.modal.close();
50992        }
50993        
50994        if (mobileCardData) {
50995        	UserPortal.Price.Payment.openMobileCC(jPricePop, mobileCardData);
50996        }
50997    }
50998    
50999    _conKeypad.openEnterCardManually = function(interationCount) {
51000    	var jlink = $('.glopop #enter-card-manually > a');
51001    	interationCount = UTIL.coalesceInt(interationCount, 0);
51002    	
51003    	if (jlink.length > 0) {
51004    		jlink.click();						//UserPortal.Price.Payment.openCreditCard()
51005    	} else if (interationCount < 12) {
51006    		setTimeout(function() { GLO.Sale.Keypad.openEnterCardManually(++interationCount); }, 200);
51007    	}
51008    }
51009    
51010    function _changeOtherTaxRate() {
51011    	if (_otherXml === null) { return; }
51012    	
51013    	if (_includeTax) {
51014    		taxRate = GLO.inventoryTax;
51015    	} else {
51016    		taxRate = '0.00';
51017    	}
51018    	
51019    	_otherXml = $(_otherXml).attr('tax_rate_pct', taxRate).outerHTML();
51020    }
51021    
51022    _conKeypad.enterCardNumber = function() {
51023    	if (GLO.Info.isIosApp) {
51024    		var amt = $('#keyboard-running-total').text().replace('$', '');
51025    		//alert('ShowManualCardEntryPage(' + amt + ')');
51026    		SA.App.showManualCardEntryPage(amt);				//GLO.Mobile.iosNativeBridge.call("ShowManualCardEntryPage", [amt]);
51027    	} else {
51028    		_conKeypad.openTicket(true);
51029    	}
51030    }
51031    
51032    function _processMobileSwipe(mobileCardData) {
51033    	GLO.Sale.Keypad.openTicket();
51034    	var jPricePop = $('#appt-price-popup').closest('.glopop');
51035    	UserPortal.Price.Payment.openMobileCC(jPricePop, mobileCardData); 
51036    }
51037    
51038    _conKeypad.saveSwipe = function(encrypted, mobileCardData) {
51039    	if (GLO.Info.isIosApp) {
51040			GLO.Sale.Keypad.openTicket(false, mobileCardData);			//		_processMobileSwipe(mobileCardData);
51041			return;
51042		}
51043		
51044		if (GLO.Info.providerPackage == 10) { var MIN_SIGNATURE_AMOUNT = 25; } else { var MIN_SIGNATURE_AMOUNT = 5; }
51045		
51046		var pmt = $('#keyboard-running-total').text().replace('$', '');
51047    	var tax = $('#keyboard-total-tax:visible').find('span').text().replace('$', '');
51048		var jsd = { "payment_event_cd": "9", "product_mn": pmt }
51049		
51050		if (UTIL.isNumber(tax, true)) {
51051			jsd["product_tax_mn"] = tax;
51052			jsd.product_mn = UTIL.coalesceMoney(jsd.product_mn - tax);
51053		}
51054		
51055		if (encrypted) {
51056			jsd.encrypted_card1_vc = encrypted;
51057		} else if (mobileCardData && mobileCardData.encrypted_card) {															//= no longer used since mobile swipes are processed thru iOS.
51058			jsd.encrypted_card1_vc = mobileCardData.encrypted_card;
51059			jsd.encrypted1_hex = mobileCardData.encrypted_hex;
51060		} else {
51061			jsd.encrypted_card1_vc = mobileCardData;
51062		}
51063		
51064		var url = GLO.Link.WebsiteDomain + 'payment/ProcessCreditCard';
51065		var msg = '<div class="friendly-msg2" style="height: 48px; min-width: 140px; margin-top: -8px;">'
51066					+ '<h1 class="friendly-msg" style="padding-top: 4px; padding-bottom: 0;">' + SA.Resource.ProcessingCard + '...</h1>'
51067					//+ '<div style="font-weight: bold; font-style: italic; color: #4F81BD;">' + SA.Resource.ProcessingCard + '...</div>'
51068					+ '<span class="card_in_use-48 sa-sprite" style="margin-left: -30px;">'
51069				+ '</div>';
51070		
51071		var ojProcessing = new GLO.Popup.Processing(msg);
51072		ojProcessing.getPopup().find('.pop-buttons-parent').remove();
51073		
51074		$.ajax({ type: "POST", url: url, "cache": false, data: jsd })
51075            .success(function(data, textStatus, jqXHR) {
51076                ojProcessing.close();
51077                var jdata = $(data);
51078                
51079                if (!UTIL.isEmpty(jdata.attr('error_cd'))) {
51080                    _saveCCerror(jdata, false);
51081                } else if (!UTIL.isEmpty(jdata.attr('warning_cd'))) {
51082                    _saveCCerror(jdata, true);
51083                } else if (UTIL.isEmpty(jdata.attr('payment_card_id'))) {
51084                	_saveCCerror(null, false, SA.Resource.UnableToProcessCreditCard);
51085                } else {
51086	                var smid = jdata.attr('schedule_multi_id');
51087	                
51088	                if (UTIL.isEmpty(smid)) {
51089                		_saveCCerror(null, false, SA.Resource.UnableToSaveTicket);
51090                	} else {
51091                		if (pmt >= MIN_SIGNATURE_AMOUNT && GLO.Info.isMobile(true)) { var bOpenSig = true; } else { var bOpenSig = false; }
51092                		
51093                		_conKeypad.quitSwipe();
51094                		UserPortal.Price.get(smid, bOpenSig, { "isKeypad": true });
51095                		
51096	                	if (!GLO.Info.isMobile()) { new GLO.Popup.Success(SA.Resource.PaymentSuccessfull); }
51097	                }
51098                }
51099            })
51100            .error(function(jqXHR, textStatus, errorThrown) {
51101                ojProcessing.close();
51102                GLO.Popup.Error('Unable to process card.  Please try again later.');
51103                GLO.UI.Form.resetProcessing();
51104                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
51105            });
51106    }
51107    
51108    function _saveCCerror(data, isWarning, errMessage) {
51109    	GLO.UI.Form.resetProcessing();
51110    	
51111    	if (!UTIL.isEmpty(errMessage)) {
51112        	new GLO.Popup.Error(errMessage);
51113        } else if (data && data.html) {
51114        	if (isWarning) {
51115            	new GLO.Popup.Warning(data.html());
51116            } else {
51117            	new GLO.Popup.Error(data.html());
51118            }
51119        } else {
51120        	new GLO.Popup.Error('Unable to process card at this time.  Please try again');
51121        }
51122    }
51123    
51124    _conKeypad.quitSwipe = function() {
51125    	if ($('#simplemodal-container #sale-keyboard').length > 0) {
51126        	$.modal.close();
51127        }
51128    	
51129    	if ($('#report-main:visible').length > 0) {
51130        	$('#report-main:visible').find('.btnSearch:visible>a').click()
51131        }
51132    	
51133    	_conKeypad.quit();
51134    }
51135    
51136    _conKeypad.quit = function() {
51137    	var j = $('#sale-keyboard');
51138    	j.find('#keyboard-running-total').text('$0.00');
51139    	
51140    	var jtax = j.find('#keyboard-total-tax');
51141    	jtax.find('i').text('');
51142    	jtax.find('span').text('');
51143    }
51144    
51145    _conKeypad.clear = function() {
51146    	if (GLO.Info.isIosApp || $('.shadow-content0 #sale-keyboard:visible').length > 0 || $('#sale-keyboard').closest('.glopop').length > 0) {
51147    		_conKeypad.quit();
51148    	}
51149    }
51150    
51151    return _conKeypad;
51152})();
51153
51154
51155SA.POS = (function() {					//boxtype: 'i' = product, 'pl' = pline, 'v' = vendor, 'p' = prev, 'n' = next, 'u' = unit, 'c' = category, 'ct' = category type, 't' = (old type category)
51156    function _conPos() { }
51157    _conPos.jsonPos = {};
51158    _conPos.boxArray = [];
51159    _conPos.sortType = 1;				//1 = Category, 2 = Brand.
51160    var _boxesPerPage = 56, _lastEventRefresh = new Date(), _lastApptRefreshDate = null;
51161    var _compressStaffBoxesTimeout = null;
51162    
51163    _conPos.init = function(jsonPosInput) {
51164    	GLO.Info.init();
51165    	GLO.isPOS = true;
51166    	UserPortal.Calendar.setStaffFilter();
51167    	
51168    	_conPos.inventory_json = jsonPosInput;
51169    	_conPos.sortType = _conPos.inventory_json.sort_type_cd;
51170    	
51171    	_initTicketPanel();
51172    	_initStaffScreen();
51173    	_initStaffScreenHeader();
51174    	_initOnScreenKeypad();
51175    	
51176    	_initLeftHandMode();
51177    	_boxCountChanged();
51178    	_initDisplayBoxes();
51179    	_setServiceGroupList();
51180    	
51181    	_initAutoComplete();
51182    	_initPosKeys();
51183    	_initSwitchToEditMode();
51184    	
51185    	//$('#pos-menu-button').click(SA.POS.toggleMenu);				//GLO.UI.setClick($('#pos-menu-button'), null, SA.POS.toggleMenu);
51186    	
51187    	_initMobilePOS();
51188    	_conPos.Edit.changeSortBy();
51189    	_initLoadImages();
51190    	jscolor.init();
51191    	
51192    	_initWelcomePopup();
51193    	_conPos.resize();
51194    	
51195    	window.onresize = function(event) { SA.POS.resize(event); };
51196    	
51197    	GLO.WaitList.setupRefresh(null, true);				//GLO.WaitList.monitorFrontDesk();
51198    	_initUrlActionPOS();
51199    	_initApptRefresh();
51200    	_initHeight();
51201    	_initQRCode();
51202    	
51203    	GLO.Info.setupFastClick();
51204    	
51205    	if (!GLO.Info.isMobile(true)) {
51206    		$('#pos-staff-list-client:visible').focus();
51207    	}
51208	}
51209	function _initQRCode() {
51210		var jhead1 = $('#pos-staff-list-header1');
51211		
51212		if (GLO.Data.provider.traveler_cd > 0) {
51213    		jhead1.find('#pos-staff-list-header1-qr').removeClass('hide');
51214    		UserPortal.Lookup.initMonitorQRScan();
51215    	} else {
51216    		jhead1.find('#pos-staff-list-header1-divider, #pos-staff-list-header1-qr').remove();
51217    	}
51218	}
51219	function _initTicketPanel() {
51220		if (_conPos.inventory_json.hide_ticket_panel_fl || UTIL.parseBool($.cookies.get('hide_ticket_panel_fl'))) {
51221    		$('#pos-panel-client').addClass('hideX');
51222    	}
51223	}
51224	function _initStaffScreen(isAlphabetical) {
51225		if (isAlphabetical) {
51226			var htm = '', staffList = UserPortal.getStaffDropDown().find('option');
51227			
51228			for (var i=0; i < staffList.length; i++) {
51229				var staffName = staffList.eq(i).text(), staffId = staffList.eq(i).attr('value');
51230				var isFA = UTIL.parseBool(staffList.eq(i).attr('is_first_available_fl'));
51231				var thumb = staffList.eq(i).attr('thumbnail');
51232				
51233				htm += _createStaffBox(staffName, staffId, isFA, thumb);
51234				$('#pos-staff-screen #pos-staff-list').html(htm);
51235			}
51236		} else {
51237			var staffList = GLO.staffResources;
51238			_loadStaffBoxes(staffList, true);
51239		}
51240	}
51241	function _loadStaffBoxes(arrStaff, isInit) {
51242		var arrToday = [], arrPresent = [], htmPresent = '', htmToday = '', htmFA = '', htmOff = '';
51243		
51244		for (var i=0; i < arrStaff.length; i++) {
51245    		if (UTIL.parseBool(arrStaff[i].is_first_available_fl)) {
51246    			htmFA = _createStaffBoxSetup(arrStaff[i], 'staff-first-available');
51247    		} else if (_isCurrentlyWorking(arrStaff[i])) {
51248    			arrPresent.push(arrStaff[i]);
51249    		} else {
51250    			arrToday.push(arrStaff[i]);
51251    		}
51252    	}
51253    	
51254    	htmPresent += _createStaffBoxes(arrPresent, 'staff-present');
51255    	htmToday   += _createStaffBoxes(arrToday, 'staff-today');
51256    	
51257		for (var a=0; a < GLO.staffResources.length; a++) {
51258			var hasStaff = false;
51259			
51260    		for (var i=0; i < arrStaff.length; i++) {
51261	    		if (arrStaff[i].id == GLO.staffResources[a].id) {
51262	    			hasStaff = true;
51263	    			break;
51264	    		}
51265	    	}
51266	    	
51267	    	if (!hasStaff) {
51268	    		htmOff += _createStaffBoxSetup(GLO.staffResources[a], 'staff-off');
51269	    	}
51270	    }
51271		
51272	    if (!UTIL.isEmpty(htmToday)) {
51273	    	htmPresent += '<li id="staff-working-today" class="staff-off-spacer"><b class="staff-off-curently">' + _getStaffOffLabel(null, null, htmToday) + '</b></li>' + htmToday;
51274	    	//htmFA = '';
51275	    }
51276	    
51277	    if (!UTIL.isEmpty(htmFA) || !UTIL.isEmpty(htmOff)) {
51278			htmPresent += '<li id="staff-off-today" class="staff-off-spacer"><b class="staff-off-today">' + _getStaffOffLabel(htmFA, htmOff) + '</b></li>' + htmFA + htmOff;
51279		}
51280		
51281		if (false) {			//add fake staff for testing UI layout
51282			for (var i=1; i < 21; i++) {
51283				htmPresent += '<li class="staff-today pos-staff-cell" staff_id="123" onclick="SA.POS.openStaffPreview(this)"><b class="fa fa-user staff-thumbnail"></b>'
51284						+ '<label class="pos-staff-name">Test Staff #' + i + '</label><div class="staff-normal-hours"><b>11:30 am - 8:30 pm</b></div></li>';
51285			}
51286		}
51287		
51288    	$('#pos-staff-screen #pos-staff-list').html(htmPresent);
51289	}
51290	function _isCurrentlyWorking(staffObject) {
51291		var day = new Date(new Date().toGloDate());
51292		var tmStart = staffObject.start_tm, tmEnd = staffObject.end_tm;
51293		var hasClockIn = false, hasClockOut = false;
51294		
51295		if (UTIL.isDate(staffObject.clockin_dt)) {
51296			tmStart = new Date(staffObject.clockin_dt).toGloTime();
51297			hasClockIn = true;
51298		}
51299		
51300		if (UTIL.isDate(staffObject.clockout_dt)) {
51301			tmEnd = new Date(staffObject.clockout_dt).toGloTime();
51302			hasClockOut = true
51303		}
51304		
51305		var dtStart = UTIL.joinDateAndTime(day, tmStart);
51306		var dtEnd = UTIL.joinDateAndTime(day, tmEnd);
51307		
51308		if (hasClockIn && !hasClockOut) {
51309			return true;
51310		} else if (dtStart < new Date() && dtEnd > new Date()) {
51311			var itmNow = UTIL.timeToInt(new Date().toGloTime());
51312			
51313			for (var b=0;
51313 b < staffObject.breaks.length; b++) {
51314				if (itmNow > staffObject.breaks[b].start_sr && staffObject.breaks[b].end_sr > itmNow) {
51315					staffObject.is_on_break_fl = staffObject.breaks[b].is_on_break_fl = true;
51316					return false;
51317				}
51318			}
51319			
51320			return true;
51321		} else {
51322			return false;
51323		}
51324	}
51325	function _getStaffOffLabel(htmFA, htmOff, htmToday) {
51326		if (!UTIL.isEmpty(htmFA) && !UTIL.isEmpty(htmToday)) {
51327			return 'First Available + Not Clocked-In or Scheduled Now';
51328		} else if (!UTIL.isEmpty(htmToday)) {
51329			return 'Not Clocked-In or Scheduled';
51330		}
51331		
51332		if (!UTIL.isEmpty(htmFA) && !UTIL.isEmpty(htmOff)) {
51333			return 'First Available + Off Today';
51334		} else if (!UTIL.isEmpty(htmFA)) {
51335			return 'First Available';
51336		} else if (!UTIL.isEmpty(htmOff)) {
51337			return 'Off Today';
51338		}
51339	}
51340	
51341	/* Sort By:
51342		1. clockin time
51343		2. start time
51344		3. normal calendar order
51345		4. alphabetical
51346		5. not working today
51347	*/
51348	function _sortStaffBoxes(box1, box2) {
51349		var iTime = UTIL.timeToInt(new Date().toGloTime());
51350		
51351		if (box1.has_clockin && !box2.has_clockin) {
51352			return -1;
51353		} else if (!box1.has_clockin && box2.has_clockin) {
51354			return 1;
51355		} else if (iTime > box1.end_sr && iTime > box2.end_sr) {			//staff finished for the day
51356			if (box1.end_sr == box2.end_sr) {
51357				if (box1.order < box2.order) {						//if (box1.name < box2.name) {
51358					return -1;
51359				} else {
51360					return 1;
51361				}
51362			} else if (box1.end_sr < box2.end_sr) {
51363				return -1;
51364			} else {
51365				return 1;
51366			}
51367		} else if (box1.start_sr == box2.start_sr) {
51368			if (box1.order < box2.order) {
51369				return -1;
51370			} else {
51371				return 1;
51372			}
51373		} else if (box1.start_sr < box2.start_sr) {
51374			return -1;
51375		} else {
51376			return 1;
51377		}
51378	}
51379	function _createStaffBoxes(arrStaff, cssClass) {
51380		var htm = '';
51381		arrStaff.sort(_sortStaffBoxes);
51382		
51383		for (var i=0; i < arrStaff.length; i++) {
51384			htm += _createStaffBoxSetup(arrStaff[i], cssClass);
51385		}
51386		
51387		return htm;
51388	}
51389	function _createStaffBoxSetup(staffObject, cssClass) {
51390		var staffName = staffObject.name, staffId = staffObject.id;
51391		var isFA = UTIL.parseBool(staffObject.is_first_available_fl);
51392		var thumb = staffObject.thumbnail;
51393		
51394		return _createStaffBox(staffName, staffId, isFA, thumb, cssClass, staffObject);
51395	}
51396	function _createStaffBox(staffName, staffId, isFA, thumb, cssClass, staffObject) {
51397		var styleName = '';
51398		var onClick = ' onclick="SA.POS.openStaffPreview(this)"';
51399		var cssName = 'pos-staff-name', shortStaffName = UTIL.maxString(staffName, 15, true);
51400		var htmLabel = _getLabelHtm(staffObject, isFA, cssClass);
51401		
51402		cssClass = UTIL.cleanString(cssClass) + ' pos-staff-cell';
51403		
51404		if (shortStaffName.length > 10) {
51405			cssName += ' pos-staff-name-long';
51406		}
51407		
51408		if (!UTIL.isEmpty(staffObject.color)) {
51409			styleName = ' style="background-color: rgb(' + staffObject.color + ');"';
51410			cssClass += ' pos-staff-has-color';
51411		}
51412		
51413		//var color = GLO.RunningTotal.getResourceStaffColor(staffId);
51414		var personIcon = '<b class="fa fa-user staff-thumbnail"></b>'
51415		var sname = '<label class="' + cssName + '"' + styleName + '>' + shortStaffName + '</label>';
51416		var faAttribute = '', htmAttributes = '', htmUpcoming = '', htmNow = '';
51417		
51418		if (UserPortal.staffPerformsClientService(staffId) && sname != 'Anyone') {
51419			if (UTIL.parseBool(isFA)) {
51420    			faAttribute = ' is_first_available_fl="1"';
51421    			//cssClass += ' is-first-available';
51422    		}
51423    		
51424    		if (staffObject && (staffObject.start_sr > 0 || staffObject.service_count_sr)) {
51425    			if (staffObject.is_on_break_fl) {
51426    				for (var b=0; b < staffObject.breaks.length; b++) {
51427    					if (staffObject.breaks[b].is_on_break_fl) {
51428    						var start = staffObject.breaks[b].start_tm.replace(':00', ''), end = staffObject.breaks[b].end_tm.replace(':00', '');
51429    						var label = UTIL.maxString(staffObject.breaks[b].service_vc, 15, true);
51430    						var htmService = '<div class="staff-break-name"><b>' + label + '</b></div>';
51431    						var htmHours = '<div class="staff-normal-hours staff-break-hours"><b>' + start + ' - ' + end + '</b></div>';
51432    						
51433    						htmAttributes += htmService + htmHours;
51434    						cssClass += ' is-on-break';
51435    					}
51436    				}
51437    			} else if (staffObject.start_sr > 0 && staffObject.end_sr > 0) {
51438    				var tmStart = UTIL.intToTime(staffObject.start_sr).replace(':00', ''), tmEnd = UTIL.intToTime(staffObject.end_sr).replace(':00', '');
51439    				var hasClockIn = false, hasClockOut = false, cssStart = '', cssEnd = '';
51440    				
51441    				if (UTIL.isDate(staffObject.clockin_dt)) {
51442						tmStart = new Date(staffObject.clockin_dt).toGloTime();
51443						hasClockIn = true;
51444						cssStart = 'is-clock-in';
51445					}
51446					
51447					if (UTIL.isDate(staffObject.clockout_dt)) {
51448						tmEnd = new Date(staffObject.clockout_dt).toGloTime();
51449						hasClockOut = true
51450						cssStart = 'is-clock-out';
51451					}
51452					
51453					if (hasClockIn && !hasClockOut) {
51454						cssClass += ' is-clocked-in';
51455					}
51456					
51457    				htmAttributes += '<div class="staff-normal-hours"><b><b class="' + cssStart + '">' + tmStart + '</b> - <b class="' + cssEnd + '">' + tmEnd + '</b></b></div>';
51458    			}
51459    			
51460    			htmAttributes += _staffBoxApptIcons(staffObject);
51461    		}
51462    		
51463    		if (!UTIL.isEmpty(thumb)) {
51464    			cssClass += ' has-staff-icon';
51465    			personIcon = '<img class="staff-thumbnail" src="' + GLO.Data.cdnDirectory + "upload-folder/" + thumb + '"/>';
51466    		}
51467    		
51468    		var htmClockInAndOut = _getClockInAndOut(staffObject);
51469			//if (currSID == sid) { css = ' selected'; }
51470			return '<li class="' + cssClass + '" staff_id="' + staffId + '"' + faAttribute + onClick + styleName + '>' + personIcon + sname + htmLabel + htmAttributes + htmClockInAndOut + '</li>';
51471		}
51472		
51473		return '';
51474	}
51475	
51476	function _getClockInAndOut(staffObject) {
51477		if (staffObject.clockInAndOut && staffObject.clockInAndOut.length > 0) {
51478			var tbl = '<table id="staff-prev-clock-out-list"> <thead> <tr> <th colspan="3">Clock-In/Out</th> </tr> </thead> <tbody>';
51479			
51480			for (var i=0; i < staffObject.clockInAndOut.length; i++) {
51481				var tdIn = '<td class="prev-clock-in">' + staffObject.clockInAndOut[i].clockin_dt.toGloTime() + '</td>';
51482				var tdOut = '<td class="prev-clock-out">' + staffObject.clockInAndOut[i].clockout_dt.toGloTime() + '</td>';
51483				
51484				tbl += '<tr>' + tdIn + '<td>-</td>' + tdOut + '</tr>';
51485			}
51486			
51487			return tbl + '</tbody></table>';
51488		}
51489		
51490		return '';
51491	}
51492	
51493	function _getLabelHtm(staffObject, isFA, cssClass) {
51494		if (isFA || cssClass != 'staff-present') {
51495			return '';
51496		}
51497		
51498		if (staffObject.status && staffObject.status.label) {
51499			if (staffObject.walkin_signin_sr > 0 && staffObject.status.priority > 9) {
51500				var css = 'label-status-2', title = '', label = 'SIGN-In <i>WALK-In</i>';
51501				return _conPos.getLabelHtm(css, title, 2, 2, label);
51502			}
51503			
51504			var cssClass = _getLabelCss(staffObject);
51505			var title = UTIL.cleanString(staffObject.status.event.labelDescription);
51506			var priority = staffObject.status.priority, status = staffObject.status.appt_status_cd;
51507			
51508			return _conPos.getLabelHtm(cssClass, title, priority, status, staffObject.status.label);
51509		} else {
51510			return '<b class="staff-box-label">AVAILABLE</b>';
51511		}
51512	}
51513	_conPos.getLabelHtm = function(cssClass, title, priority, status, label) {
51514		return '<b class="staff-box-label ' + cssClass + '" title="' + title + '" priority_sr="' + priority + '" appt_status_cd="' + status + '">' + label + '</b>';
51515	}
51516	function _getLabelCss(staffObject) {
51517		if (staffObject.status && staffObject.status.appt_status_cd) {
51518			var css = 'label-status-' + staffObject.status.appt_status_cd;
51519			
51520			if (staffObject.status && staffObject.status.event) {
51521				css += _getLabelSoonCss(staffObject);
51522			}
51523			
51524			return css;
51525		} else {
51526			return '';
51527		}
51528	}
51529	function _getLabelSoonCss(staffObject) {
51530		var apptStatus = staffObject.status.appt_status_cd;
51531		
51532		if (apptStatus == 21) {
51533			var endsIn = UTIL.coalesceInt( (new Date(staffObject.status.event.end) - new Date()) / (1000 * 60), 0);
51534			
51535			if (endsIn < 5) {
51536		    	return ' very-soon';
51537		    } else if (endsIn < 15) {
51538		    	return ' soon';
51539		    }
51540		} else if (apptStatus == 2) {
51541		    var signinWait = UTIL.coalesceInt( (new Date() - new Date(staffObject.status.event.signin_dt)) / (1000 * 60), 0);
51542		    
51543		    if (signinWait > 5) {
51544		    	return ' waiting';
51545		    } else if (signinWait > 15) {
51546		    	return ' very-waiting';
51547		    }
51548		} else if (apptStatus == 39) {
51549		    if (endsIn < 5) {
51550		    	return ' very-soon';
51551		    } else if (endsIn < 15) {
51552		    	return ' soon';
51553		    }
51554		} else if (apptStatus == 41) {
51555			var startsIn = UTIL.coalesceInt( (new Date(staffObject.status.event.start) - new Date()) / (1000 * 60), 0);
51556			
51557			if (startsIn < 5) {
51558		    	return ' very-soon';
51559		    } else if (startsIn < 15) {
51560		    	return ' soon';
51561		    }
51562		}
51563		
51564		return '';
51565	}
51566	
51567	_conPos.getSigninIcon = function(count) {
51568		var titleNow = UTIL.pluralLabel(count, 'client self sign-in');
51569		
51570		var htmIcon = '<span class="staff-appt-count staff-appt-signin "><b class="staff-appt-signin-count" title="' + titleNow + '">' + count + '</b></span>';
51571		htmIcon += '<b class="staff-arrow-now-in" class="arrow-right">&#10140;</b>';
51572		
51573		return htmIcon;
51574	}
51575	
51576	function _staffBoxApptIcons(staffObject) {
51577		var htmIcons = '';
51578		var signinCount = UTIL.coalesceInt(UTIL.coalesceInt(staffObject.walkin_signin_sr, 0) + UTIL.coalesceInt(staffObject.signin_count_sr, 0), 0);
51579		
51580		if (signinCount) {
51581			//var jstaff = $('#pos-staff-screen').find('.pos-staff-cell[staff_id="' + staffObject.id + '"]');
51582			//var signinCount = UTIL.coalesceInt(UTIL.coalesceInt(jstaff.attr('walkin_signin_sr'), 0) + staffObject.signin_count_sr);
51583			htmIcons += _conPos.getSigninIcon(signinCount);
51584		}
51585		
51586		if (staffObject.checkin_count_sr > 0) {
51587			var titleIn = UTIL.pluralLabel(staffObject.checkin_count_sr, 'ticket') + ' checked-in';
51588			var htmIn = '<b class="staff-appt-checkin-count" title="' + titleIn + '">' + staffObject.checkin_count_sr + '</b>';
51589			
51590			htmIcons += '<span class="staff-appt-count staff-appt-checkin">' + htmIn + '</span>';
51591			htmIcons += '<b class="staff-arrow-in-out" class="arrow-right">&#10140;</b>';
51592		}
51593		
51594		if (staffObject.checkout_count_sr > 0) {
51595			var titleOut = UTIL.pluralLabel(staffObject.checkout_count_sr, 'ticket') + ' checked-out';
51596			var htmOut = '<b class="staff-appt-checkout-count" title="' + titleOut + '">' + staffObject.checkout_count_sr + '</b>';
51597			
51598			htmIcons += '<span class="staff-appt-count staff-appt-checkout">' + htmOut + '</span>';
51599		}
51600		
51601		if (staffObject.now_count_sr > 0) {
51602			var titleNow = UTIL.pluralLabel(staffObject.now_count_sr, 'now appointment (starts within 20 minutes)');
51603			var htmNow = '<b class="staff-appt-now-count" title="' + titleNow + '">' + staffObject.now_count_sr + '</b>';
51604			
51605			htmIcons += '<span class="staff-appt-count staff-appt-now">' + htmNow + '</span>';
51606		}
51607		
51608		if (staffObject.late_count_sr > 0) {
51609			var titleLate = UTIL.pluralLabel(staffObject.late_count_sr, 'late appointment (start time more than 20 minutes after current time, but less than 90 minutes)');
51610			var htmLate = '<b class="staff-appt-late-count" title="' + titleLate + '">' + staffObject.late_count_sr + '</b>';
51611			
51612			htmIcons += '<span class="staff-appt-count staff-appt-late">' + htmLate + '</span>';
51613		}
51614		
51615		if (staffObject.upcoming_count_sr > 0) {
51616			var titleUpcoming = UTIL.pluralLabel(staffObject.upcoming_count_sr, 'upcoming appointment');
51617			var htmUpcoming = '<b class="staff-appt-upcoming-count" title="' + titleUpcoming + '">' + staffObject.upcoming_count_sr + '</b>';
51618			
51619			htmIcons += '<span class="staff-appt-count staff-appt-upcoming">' + htmUpcoming + '</span>';
51620		}
51621		
51622		if (staffObject.past_count_sr > 0) {
51623			var titlePast = UTIL.pluralLabel(staffObject.past_count_sr, 'past appointment');
51624			var htmPast = '<b class="staff-appt-past-count" title="' + titlePast + '">' + staffObject.past_count_sr + '</b>';
51625			
51626			htmIcons += '<span class="staff-appt-count staff-appt-past">' + htmPast + '</span>';
51627		}
51628		
51629		return htmIcons;
51630	}
51631	
51632	function _initStaffScreenHeader() {
51633		var jclient = $('#pos-staff-screen #pos-staff-list-client');
51634		var uriClientSearch = GLO.Link.Object.Provider.ClientSearch + '?HasApptToday=1&InventorySearch=1';
51635		var fnMultiLocation = UserPortal.importClientOpen;
51636		var fnOnSelect = SA.Ticket.addClientSelected;
51637        
51638		UI.initAutoComplete(jclient, uriClientSearch, fnMultiLocation, fnOnSelect);
51639		
51640		var jday = $('#Ticket_day');
51641		var jtime = $('#Ticket_tm');
51642		//var yearRange = GLO.UI.getYearRange(true);
51643		
51644		jday.datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
51645						, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadD
51645atepicker });			//, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1
51646		UI.timeMask('#Ticket_tm');
51647		
51648		jtime.click(function() {
51649    		var h1 = 'Appointment Time', jelement = $(this), htm = '', cssStyle = '', fnAfterSave = null;
51650    		
51651    		if ($.trim(this.value).length < 4) {
51652    			UI.setTimeMaskValue(jelement, SA.Ticket.getTime());
51653    		}
51654    		
51655    		UI.Keypad.openTime(h1, htm, jelement, fnAfterSave);
51656    	});
51657    	
51658    	if (!GLO.Info.isMobile(true)) {
51659    		jtime.attr('readonly', 'readonly');
51660    	}
51661    	
51662    	if (UTIL.isEmpty(SA.POS.inventory_json.gift_card_type_id)) {
51663    		$('#pos-quick-sell-header').remove();
51664    	}
51665	}
51666	function _initOnScreenKeypad() {
51667    	$('#pos-staff-list-client').click(function() {
51668    		var jclient = $(this);
51669    		var h1 = 'Enter Client Name or Phone Number';
51670    		var htm = null, cssStyle = null;
51671    		
51672    		var jkeypad = UI.Keypad.openKeypadCharacter(h1, htm, jclient, cssStyle).addClass('sa-keypad-name');
51673    		var jinput = jkeypad.find('input.sa-keypad').addClass('support-scan');
51674    		var fnOnSelect = SA.Ticket.addClientSelected, uriClientSearch = GLO.Link.Object.Provider.ClientSearch + '?HasApptToday=1&InventorySearch=1';
51675    		var btnAddClient = '<span id="btnAddNewClient" class="btnAdd btnLeftCorner"><a onclick="UserPortal.Create.addClientLink(false, true)">Add New Client</a></span>';
51676    		
51677    		UI.initAutoComplete(jinput, uriClientSearch, null, fnOnSelect);
51678    		jkeypad.find('.pop-buttons2').append(btnAddClient);
51679    		
51680    		if ($('#simplemodal-container:visible').length === 0) {
51681		    	jinput.bind('keydown', function(e) {
51682			        if (e.which === 13) { // ENTER
51683			            if ($('.pop-processing').closest('.glopop').length) { return; }
51684			            
51685			            SA.TicketCard.enterTicketNumber(this);
51686			        }
51687			    });
51688	    	}
51689    	});
51690    	
51691    	$('#posTime_vc').click(function() {
51692    		var h1 = 'Appointment Time', jelement = $(this), htm = '', cssStyle = '', fnAfterSave = null;
51693    		UI.Keypad.openTime(h1, htm, jelement, fnAfterSave);
51694    	});
51695    }
51696    
51697	function _initHeight() {
51698		if (innerHeight < 120 + 768 + 10) {
51699			$('#pos-container').addClass('compress-box');
51700		}
51701		
51702		/* if (innerHeight < 650) {
51703			$('#pos-container').addClass('short5');
51704			$('#pos-container').addClass('compress-box');
51705		} else if (innerHeight < 690) {
51706			$('#pos-container').addClass('short4');
51707			$('#pos-container').addClass('compress-box');
51708		} else if (innerHeight < 730) {
51709			$('#pos-container').addClass('short3');
51710			$('#pos-container').addClass('compress-box');
51711		} else if (innerHeight < 770) {
51712			$('#pos-container').addClass('short2');
51713		} else if (innerHeight < 810) {
51714			$('#pos-container').addClass('short1');
51715		} */
51716	}
51717	function _initDisplayBoxes() {
51718		if (_conPos.inventory_json.service_groups.length === 0) {
51719			$('#pos-toggle-list').remove();
51720			_conPos.displayBoxes();
51721		} else {
51722			_conPos.toggleList('services');
51723			_setLargeStaffBoxes();
51724		}
51725	}
51726	function _setLargeStaffBoxes() {
51727		var jStaffList = $('#pos-staff-list');
51728		var staffWidth = jStaffList.width();
51729		var staffHeight = innerHeight - $('#pos-product-header').height() - $('#pos-staff-list-header').height() - $('#pos-footer-inner').height() - 60;		//jStaffList.height();
51730		
51731		var staffBoxWide = parseInt(staffWidth / 240);
51732		var staffBoxTall = parseInt(staffHeight / 180);
51733		var staffBigCount = parseInt(staffBoxWide * staffBoxTall);
51734		var staffCount = jStaffList.find('.pos-staff-cell').length;
51735		
51736		if (innerWidth >= 1120 && staffBigCount >= staffCount) {
51737			$('#pos-container').addClass('big-staff-card');
51738		} else {
51739			$('#pos-container').removeClass('big-staff-card');
51740		}
51741	}
51742	function _initMobilePOS() {
51743		if (GLO.Info.isIPad) {
51744    		$(document).bind('touchmove', false);
51745    		
51746    		var pos = document.getElementById('pos-container');
51747    		new FastClick(pos);
51748    	}
51749    	
51750    	if (GLO.Info.isMobile(true)) {
51751    		$('#pos-ticket').on('focus', 'input', SA.Ticket.inputOnFocus);
51752    	}
51753	}
51754	function _initUrlActionPOS() {
51755		var open = GLO.Uri.query('open');
51756		
51757		if (GLO.Uri.query('menu') === 'open' && !$('#pos-action-menu').is(':visible')) {
51758			SA.POS.toggleActionMenu();
51759		}
51760		
51761		if (open == 'manager-reports') {
51762			SA.POS.openManagerReport();
51763		} else if (open == 'report-menu') {
51764			SA.POS.openReportMenu();
51765		} else if (open == 'manage-profile') {
51766			SA.POS.openProfile();
51767		} else if (open == 'edit-and-info') {
51768			SA.POS.Edit.openHelp();
51769		} else if (open == 'quick-guide') {
51770			SA.POS.openHelpQuickGuide();
51771		} else if (open == 'staff-summary') {
51772			$('#pos-staff-list .pos-staff-cell').click();
51773		}
51774		
51775		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
51776		
51777		if (!UTIL.isEmpty(highlight)) {
51778			setTimeout(function() {
51779				var jhigh = $('#' + highlight);
51780	    		
51781	    		if (jhigh.length) {
51782	    			UI.highlight(jhigh, 100, 9500, true);
51783	    			return true;
51784	    		}
51785    		}, 1500);
51786		}
51787	}
51788	function _initSwitchToEditMode() {
51789		if (UTIL.parseBool(GLO.Uri.query('edit'))) {		// || _conPos.inventory_json.products.length === 0
51790    		if (!UTIL.parseBool(_conPos.inventory_json.no_toggle_menu_fl)) {
51791    			_conPos.toggleActionMenu();
51792    			_conPos.Edit.changeMode();
51793    		}
51794    	}
51795    	
51796    	if (innerWidth < 860) {
51797    		$('#pos-header-edit-option-table #sort-products-row').find('label[for="edit-pos-sortby"]').text('Sort');
51798    	}
51799	}
51800    function _initLeftHandMode() {
51801    	var jpos = $('#pos-container');
51802    	
51803    	if (UTIL.parseBool(_conPos.inventory_json.left_hand_fl)) {
51804    		$('#edit-pos-left-hand-mode').prop('checked', true);
51805    		jpos.removeClass('left-ticket');				//'left-hand-mode' puts ticket on the right.
51806    	}
51807    }
51808    function _initWelcomePopup() {
51809    	return;
51810    	if (!_displayWelcomePopup()) { return; }
51811    	//if (!GLO.Info.isMobile(true)) { return; }
51812    	
51813    	var h1 = '<h1 class="friendly-msg2">Point-of-Sale System (P.O.S.)</h1>';
51814    	var p1 = '<p>The <span class="sa-brand"><i>Schedule</i><b>Anyone</b></span> P.O.S. is another way you can create tickets and invoices for product sales as well as manage your product list</p>';
51815    	var p2 = '<p style="margin-top: 20px; margin-bottom: 2px; text-align: center; text-transform: capitalize; font-weight: bold;">On this screen you can</p>';
51816    	var ul = '<ul>'
51817    				+ '<li>Select a product to add it to the ticket</li>'
51818    				+ '<li>Press View Ticket to open the ticket you have created</li>'
51819    				+ '<li>Press the menu button to navigate to another page or edit your product list</li>'
51820    			+ '</ul>';
51821    	
51822    	var jpop = new GLO.Popup.Info('<div id="pop-pos-welcome">' + h1 + '<div style="letter-spacing: 1px;">' + p1 + p2 + ul + '</div></div>').getPopup();
51823    	jpop.find('.msg').css({ "padding-top": "4px" });
51824    }
51825    function _displayWelcomePopup() {
51826    	if (UTIL.parseBool($.cookies.get('has-pos-welcome'))) { return false; }
51827    	
51828    	UTIL.setCookieWithExpire('has-pos-welcome', '1');						//$.cookies.set('has-pos-welcome', '1');
51829    	return true;
51830    }
51831    
51832    function _initLoadImages() {		//= preload images so they are faster
51833	    var preloader = $('#preload').append('<div id="preload-pos-images" style="display: none;"></div>');
51834		
51835		_initLoadImages2(preloader, SA.POS.inventory_json.products);
51836		_initLoadImages2(preloader, SA.POS.inventory_json.plines);
51837		_initLoadImages2(preloader, SA.POS.inventory_json.vendors);
51838		
51839		_initLoadImages2(preloader, SA.POS.inventory_json.types);
51840		_initLoadImages2(preloader, SA.POS.inventory_json.categories);
51841		
51842		_initLoadImages2(preloader, SA.POS.inventory_json.service_groups);
51843		_initLoadImages2(preloader, SA.POS.inventory_json.services);
51844	}
51845	
51846	function _initLoadImages2(preloader, list) {
51847		if (list) {
51848			for (var i=0; i < list.length; i++) {
51849	            
51850	            if (!UTIL.isEmpty(list[i].image_vc)) {
51851	            	var img = GLO.Data.cdnDirectory + "upload-folder/" + list[i].image_vc;
51852	            	$("<img/>").attr("src", img).appendTo(preloader);
51853	            }
51854	        }
51855        }
51856	}
51857    
51858    function _initPosKeys() {
51859    	$(document).on("keydown", function(e) {
51860	        if (e.keyCode === 72) {                  			//= h
51861	            if (e.ctrlKey || e.altKey) {					// || $(':focus:input').length === 0
51862	            	SA.POS.filterBoxesHome();
51863	            	e.preventDefault();
51864	            	return false;
51865	            }
51866	        }
51867	    });
51868    }
51869    
51870    _conPos.searchProductList = function(requestObj, responseFn) {
51871    	var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex(requestObj.term), "i");
51872      	var found = [], all = SA.POS.inventory_json.products;
51873      	
51874      	for (var f=0; f < all.length; f++) {
51875	        var item = all[f];
51876	        
51877        	if (matcher.test(item.label)) {
51878        		found.push(item);
51879        	} else if (requestObj.term.length > 4) {
51880        	 	if (matcher.test(item.upc_vc) || matcher.test(item.sku_vc)) {
51881        	 		var item2 = jQuery.extend({}, item);
51882        	 		item2.is_sku_upc_match_fl = true;
51883        	 		
51884        	 		found.push(item2);
51885        	 	}
51886        	}
51887	    }
51888      	
51889      	responseFn(found);
51890    }
51891    
51892	function _initAutoComplete() {
51893    	var jinput = $("#pos-enter-product-or-amount");
51894    	
51895    	jinput.autocomplete({
51896			source: SA.POS.searchProductList,							//SA.POS.inventory_json.products,
51897			minLength: 2,
51898	        autoFocus: true,
51899	        open: function(event, ui) {
51900            	$('.ui-autocomplete.auto-select-first-item').find('li:first').click();
51901            },
51902	        select: function( event, ui ) {
51903				SA.Ticket.addProductLine(ui.item.id);
51904				event.target.value = '';
51905				return false;
51906			}
51907		});
51908		/* .data( "ui-autocomplete" )._renderItem = function(ul, item) {
51909			var str = "<a><span style='color: #62BECB;'>" + item.label + "</span> ";
51910			if (item.size_vc && item.unit_abbreviation_vc) { str += item.size_vc + ' ' + item.unit_abbreviation_vc; }
51911			
51912			if (!UTIL.isEmpty(item.price_mn)) { str += '<i>' + UTIL.displayMoney(item.price_mn, false, true) + '</i>'; }
51913			str += "</a>";
51914			
51915			return $("<li></li>").data("ui-autocomplete-item", item).append(str).appendTo(ul);
51916		}; */
51917		
51918		jinput.data("ui-autocomplete")._renderMenu = function(ul, items) {
51919		  	var that = this;
51920		  	
51921		  	$.each(items, function(index, item) {
51922		    	that._renderItemData(ul, item);
51923		  	});
51924		  	
51925			$(ul).find("li:odd").addClass("odd");
51926			
51927			if (items.length === 1 && items[0].is_sku_upc_match_fl == 1) {
51928				$(ul).addClass('auto-select-first-item', true);
51929			}
51930		};
51931    }
51932    _conPos.toggleList = function(listType) {
51933    	var j = $('#pos-container').removeClass('staff-screen');
51934    	var jtoggle = j.find('#pos-toggle-list');
51935    	
51936    	if (listType === 'services') {
51937    		j.removeClass('products').addClass('services');
51938    		jtoggle.find('#btnDisplayProducts').removeClass('selected');
51939    		jtoggle.find('#btnDisplayServices').addClass('selected');
51940    		var svcSortType = $('#pos-header-service-sort').find('input[name = "service_sort_type_cd"]:checked');
51941    		
51942    		if (svcSortType.val() == 11) {
51943				j.addClass('service-sort-custom');
51944			}
51945    	} else {
51946    		j.removeClass('services').removeClass('service-sort-custom').addClass('products');
51947    		jtoggle.find('#btnDisplayServices').removeClass('selected');
51948    		jtoggle.find('#btnDisplayProducts').addClass('selected');
51949    	}
51950    	
51951    	_boxCountChanged();
51952    	SA.POS.filterBoxesHome();				//j.find('#pos-breadcrumb-home:visible').click();
51953    	_conPos.resize();
51954    }
51955    _conPos.compressStaffBoxes = function() {
51956    	var heightHeader = $('#pos-product-header').height();
51957    	var jscreen = $('#pos-staff-screen');
51958    	var heightScreen = jscreen.height();
51959    	var heightFooter = $('#pos-footer').height();
51960    	
51961    	if (heightHeader + heightScreen > innerHeight) {
51962    		jscreen.find('#pos-staff-list').addClass('compress');
51963    	} else {
51964    		jscreen.find('#pos-staff-list').removeClass('compress');
51965    	}
51966    	
51967    	/* if (heightHeader + heightScreen + heightFooter > innerHeight) {
51968    		$('#pos-footer').addClass('compress').addClass('float-footer');
51969    	} else {
51970    		$('#pos-footer').removeClass('float-footer');
51971    	} */
51972    }
51973    _conPos.resetPanelHeight = function(event) {
51974    	var jpanel = $('#pos-panel-client');
51975		var jscreen = $('#pos-staff-screen');
51976		
51977		var heightHeader = $('#pos-product-header').height();
51978		var heightFooter = $('#pos-footer').height();
51979		var heightPanel  = jpanel.find('table').height();
51980		
51981		var panelHeight = innerHeight - heightHeader - 10;
51982		jpanel.css({ "height": panelHeight + "px" });
51983		jpanel.find('#pos-panel-client-list').css({ "height": panelHeight + "px" });
51984		
51985		if (heightHeader + heightFooter + heightPanel > innerHeight) {
51986			var newWidth = jscreen.width();
51987			
51988			$('#pos-footer').addClass('compress').css({ "width": newWidth + "px" });
51989		} else if (jscreen.height() + 50 <= innerHeight) {
51990			$('#pos-footer').removeClass('compress').css({ "width": "" });
51991		}
51992    }
51993    _conPos.resize = function(event) {
51994    	_setPosHeight();
51995    	_setTicketHeight();
51996    	
51997    	var posTicketWidth = _getPosTicketWidth();
51998    	var posCategoryWidth = _getPosCategoryWidth();
51999    	_setPosWindowWidth(posTicketWidth, posCategoryWidth);
52000    	_setPosCategoryHeight();
52001    	
52002    	if (_boxCountChanged()) {
52003    		SA.POS.Edit.clickBreadcrumbEnd(null, null, true);
52004    		//SA.POS.displayBoxes();
52005    		//alert('innerWidth = ' + innerWidth + '; _boxesPerPage = ' + _boxesPerPage);
52006    	}
52007    	
52008    	_conPos.resetPanelHeight();
52009    	
52010    	clearTimeout(_compressStaffBoxesTimeout);
52011    	_compressStaffBoxesTimeout = setTimeout(SA.POS.compressStaffBoxes, 500);
52012    }
52013    function _setTicketHeight() {
52014    	var jticket = $('#pos-ticket');
52015    	
52016    	if (innerWidth > 632) {			//if innerWidth > 1200 (because then footer is in the middle) -> can extend ticket height (base on innerHeight)
52017    		var posHeaderHeight = $('#pos-product-header').height();
52018    		var posTicketTop = UTIL.coalesceInt(jticket.css('top').replace('px', ''));
52019    		var posTicketFooter = jticket.find('#pos-ticket-total-line').height() + jticket.find('#pos-ticket-header').height() + jticket.find('#pos-ticket-footer').height();
52020    		
52021    		var jclient = $('#pos-ticket-client');
52022    		var clientExtra = UTIL.coalesceInt(jclient.css('margin-top').replace('px', ''));
52023    		var clientHeight = jclient.height();
52024    		
52025    		var availableHeight = innerHeight - posHeaderHeight - posTicketTop - posTicketFooter - clientExtra - clientHeight - 20;
52026    		var jticket2 = jticket.find('#pos-ticket-order');
52027    		
52028    		if (availableHeight < 370) {
52029    			if (jticket2.height() < 370) {
52030    				return;
52031    			} else {
52032    				jclient.css({ "height": "" });
52033    				availableHeight = 360;
52034    			}
52035    		} else if (availableHeight > 600) {
52036    			clientHeight += availableHeight - 600;
52037    			availableHeight = 600;
52038    			
52039    			jclient.height(clientHeight);
52040    		}
52041    		
52042    		jticket2.height(availableHeight);
52043    	} else if (jticket.css('height') != '100%') {
52044    		jticket.css({ "height": "100%" });
52045    	}
52046    }
52047    function _setPosHeight() {
52048    	var jpos = $('#pos-body');
52049    	var jfooter = $('#pos-footer');
52050    	
52051    	if (innerWidth > 632) {
52052    		var posFooterHeight = 0;
52053    	} else {
52054    		var posFooterHeight = jfooter.height() + UTIL.coalesceInt(jfooter.css('padding-top').replace('px', ''));
52055    	}
52056    	
52057    	var posBodyMargin = UTIL.coalesceInt(jpos.css('margin-top').replace('px', ''));
52058    	var posBodyHeight = jpos.height();
52059    	var posHeight = posBodyMargin + posBodyHeight + posFooterHeight;
52060    	var newHeight = innerHeight - posBodyMargin - posFooterHeight;
52061    	
52062    	var ticketHeader = $('#pos-quick-link-header').height() + $('#pos-header-staff-ticket').height();
52063    	var newTicketHeight = innerHeight - ticketHeader;
52064    	
52065    	_setPosHeight2(jpos, posHeight, newHeight);
52066    	
52067    	if (newTicketHeight < 768) {
52068    		if (newHeight < 500) {
52069    			newTicketHeight = 500 + (posBodyHeight + posFooterHeight - ticketHeader);
52070    		}
52071    		
52072    		var extraToRemove = parseInt(768 - newTicketHeight) + 2;
52073			$('#pos-ticket-order').height(360 - extraToRemove/2);
52074			$('#pos-ticket-client').height(240 - extraToRemove/2);
52075    	} else {
52076    		$('#pos-ticket-order').css({ "height": "" });
52077    		$('#pos-ticket-client').css({ "height": "" });
52078    	}
52079    }
52080    function _setPosHeight2(jpos, posHeight, newHeight) {
52081    	if (innerHeight > posHeight) {
52082    		jpos.height(newHeight);
52083    	} else if (posHeight > innerHeight) {
52084    		if (newHeight < 500) {
52085    			newHeight = 500;
52086    		}
52087    		
52088    		jpos.height(newHeight);
52089    	}
52090    }
52091    function _setPosWindowWidth(posTicketWidth, posCategoryWidth) {
52092    	var jpos = $('#pos-body').removeClass('window-stretch6').removeClass('window-stretch12').removeClass('window-stretch18').removeClass('window-stretch24').removeClass('window-stretch30');
52093    	jpos.removeClass('window-stretch30').removeClass('window-stretch36').removeClass('window-stretch42').removeClass('window-stretch48');
52094    	
52095    	var boxWidth = _posGetBoxWidth(jpos);
52096    	var posWindoWidth = $('body')[0].clientWidth - posTicketWidth - posCategoryWidth;			//.clientWidth -> if html page taller than screen, clientWidth = innerWidth - scrollbar
52097    	
52098    	var boxesPerRow = parseInt(posWindoWidth / boxWidth);
52099    	var extraPerRow = parseInt(posWindoWidth - boxWidth * boxesPerRow);
52100    	var extraPerBox = parseInt(extraPerRow / boxesPerRow) - 1;				//-1 (to be safe)
52101    	
52102    	if (innerWidth >= 632 && innerWidth <= 660) {
52103    		//
52104    	} else if (extraPerBox > 48) {
52105    		jpos.addClass('window-stretch48');
52106    	} else if (extraPerBox > 42) {
52107    		jpos.addClass('window-stretch42');
52108    	} else if (extraPerBox > 36) {
52109    		jpos.addClass('window-stretch36');
52110    	
52111    	} else if (extraPerBox > 30) {
52112    		jpos.addClass('window-stretch30');
52113    	} else if (extraPerBox > 24) {
52114    		jpos.addClass('window-stretch24');
52115    	} else if (extraPerBox > 18) {
52116    		jpos.addClass('window-stretch18');
52117    	} else if (extraPerBox > 12) {
52118    		jpos.addClass('window-stretch12');
52119    	} else if (extraPerBox > 6) {
52120    		jpos.addClass('window-stretch6');
52121    	}
52122    	
52123    	jpos.find('#pos-product-window').css({ "width": posWindoWidth + "px", "margin-left": posCategoryWidth + "px" });
52124    }
52125    function _setPosCategoryHeight() {
52126    	var jlist = $('#pos-container.services #pos-service-group-list');
52127    	
52128    	if (jlist.length) {
52129    		var headerHeight = $('#pos-product-header').height() + jlist[0].offsetTop;
52130    		var listHeight = jlist.height();
52131    		
52132    		if (headerHeight + listHeight >
52132 innerHeight) {
52133    			jlist.height(innerHeight - headerHeight);
52134    		} else if (jlist[0].scrollHeight > listHeight) {
52135    			if (headerHeight + jlist[0].scrollHeight > innerHeight) {
52136    				jlist.height(innerHeight - headerHeight);
52137    			} else {
52138    				jlist.height(jlist[0].scrollHeight + 1);
52139    			}
52140    		}
52141    	}
52142    }
52143    function _getPosCategoryWidth() {
52144    	var screenWidth = innerWidth;		//$('body')[0].clientWidth;
52145    	var jlist = $('#pos-container.services #pos-service-group-list');
52146    	
52147    	if (jlist.length && screenWidth > 970) {
52148	    	if (screenWidth >= 1200) {
52149	    		return 200 + 4;
52150	    	} else if (screenWidth > 1030) {
52151	    		return 160 + 4;
52152	    	} else {
52153	    		return 140 + 2;
52154	    	}
52155    	} else {
52156    		return 0;
52157    	}
52158    }
52159    function _getPosTicketWidth() {
52160    	var screenWidth = innerWidth;		//$('body')[0].clientWidth;
52161    	
52162    	if (screenWidth >= 1680) {
52163    		return 464;
52164    	} else if (screenWidth > 1000) {
52165    		return 340;
52166    	} else if (screenWidth > 632) {
52167    		return 320;
52168    	} else {
52169    		return 0;
52170    	}
52171    }
52172    function _posGetBoxWidth(jpos) {
52173    	var jbox1 = jpos.find('.pos-product-box:visible:first');
52174    	var screenWidth = innerWidth;			//$('body')[0].clientWidth;
52175    	
52176    	if (jbox1.length) {
52177    		var style = jbox1[0].currentStyle || window.getComputedStyle(jbox1[0]);
52178    		var boxMargin = parseFloat(style.marginLeft) + parseFloat(style.marginRight);
52179    		return UTIL.coalesceInt(jbox1.outerWidth(), 166) + UTIL.coalesceInt(boxMargin, 2);
52180    	} else {
52181    		var boxWidth = 166;
52182    		
52183    		if (screenWidth > 1000) {
52184    			return boxWidth + 4;
52185    		} else {
52186    			return boxWidth + 2;
52187    		}
52188    	}
52189    }
52190    
52191    _conPos.refreshFromUser = function(isBackground) {
52192    	var seconds = parseInt((new Date() - _lastEventRefresh)/1000);
52193    	var maxRefreshSeconds = 5;
52194    	
52195    	GLO.Popup.closeIfExist($('#pop-pos-refresh').closest('.glopop'));
52196    	
52197    	if ($('#cal-refresh-icon').hasClass('simple-spin')) {
52198    		if (!isBackground) {
52199	    		var htm = '<div id="pop-cal-refresh">Currently Refreshing POS Tickets...</div>';
52200	    		GLO.Popup.Processing.open(htm, 'Refreshing P.O.S.');
52201    		}
52202    	} else if (seconds < maxRefreshSeconds) {
52203    		if (!isBackground) {
52204	    		var msg1 = 'P.O.S. Refreshed ' + UTIL.pluralLabel(seconds, 'second') + ' ago';
52205	    		var msg2 = 'Please wait ' + UTIL.pluralLabel(maxRefreshSeconds - seconds, 'second') + ' to refresh again';
52206	    		var msg3 = '<span class="btnAdd"><a onclick="location.reload()">Full Screen Refresh</a></span>';
52207	    		var htm = '<div id="pop-pos-refresh"><p>' + msg1 + '</p><p>' + msg2 + '</p><p style="margin: 24px; text-align: center;">' + msg3 + '</p></div>';
52208	    		
52209	    		GLO.Popup.Success.open(htm, 'P.O.S. Refresh');
52210    		}
52211    	} else {
52212    		GLO.Uri.removeHashKey('panel');
52213    		SA.POS.refreshEvents(true);
52214    		//GLO.WaitList.monitorInBackground();
52215    	}
52216    	
52217    	UserPortal.editPasswordRemove();
52218    }
52219    function _initApptRefresh() {
52220		setInterval(function() {
52221			SA.POS.refreshEvents();
52222		}, 45000);        //runs every 45 seconds.
52223		
52224		_conPos.refreshEvents(true);
52225	}
52226	_conPos.refreshEvents = function(override, threshold) {
52227        if (UTIL.isEmpty(threshold)) {
52228        	threshold = 15;
52229        }
52230        
52231        var dt = new Date();
52232        dt.setMinutes(dt.getMinutes() - threshold);
52233        
52234        if (override || _lastEventRefresh < dt) {
52235        	_lastEventRefresh = new Date();
52236        	_resetWalkinSignins();
52237        	
52238        	_getApptJson();
52239        	SA.TicketCard.refreshSigninList();
52240        }
52241	}
52242	function _resetWalkinSignins() {
52243		for (var i=0; i < GLO.resourceHours.length; i++) {
52244			delete GLO.resourceHours[i].walkin_signin_sr
52245		}
52246	}
52247	
52248	function _getApptJson() {
52249		var url = GLO.Link.Object.AppointmentAjax + 'GetJson?cdn=' + GLO.Data.cdnVersion + '&timezone=' + -new Date().getTimezoneOffset()/60 + '&sfilter=' + UserPortal.staffFilter;
52250		
52251		var day = new Date(new Date().toGloDate());					//toDo (later): support when user's timezone != salon timezone
52252		var startTimestamp = Math.round(+day / 1000);
52253		var endTimestamp = Math.round(+new Date(day).addDays(1) / 1000);
52254		
52255		var jrefresh = $('#cal-refresh-icon').addClass('simple-spin');
52256		
52257		$.ajax({ "type": "GET", "url": url, "cache": false, "dataType": "json", "data": { "start": startTimestamp, "end": endTimestamp } })
52258            .success(function(calEvents, textStatus, jqXHR) {
52259            	//toDo (later): support when user's timezone != salon timezone ->  for (var i=0; i< calEvents.length; i++) { normalizeEvent(calEvents[i]); }
52260            	
52261            	var arrStaff = GLO.Staff.Filter.staffWorkingOnDay(day, calEvents);
52262            	_adjustStaffObjectsForClockInAndOut(arrStaff);
52263            	_loadStaffBoxes(arrStaff);
52264            	
52265            	SA.TicketCard.loadAppointments(calEvents);
52266            	_finishLoadJson(jrefresh);
52267            	SA.TicketCard.refreshFilterPanel();
52268            	SA.TicketCard.loadExtraClockOutsOnStaffPreview();
52269            })
52270            .error(function(jqXHR, textStatus, errorThrown) {
52271            	UserPortal.Calendar.processCalendarAjaxError(arguments[0]);
52272				UTIL.Validate.processLogoutWhenNeeded();
52273            });
52274	}
52275	
52276	function _adjustStaffObjectsForClockInAndOut(arrStaff) {
52277		for (var i=0; i < arrStaff.length; i++) {
52278			if (UTIL.isDate(arrStaff[i].clockin_dt)) {
52279				arrStaff[i].has_clockin = true;
52280				arrStaff[i].clockin_tm = new Date(arrStaff[i].clockin_dt).toGloTime();
52281				arrStaff[i].start_sr = UTIL.timeToInt(arrStaff[i].clockin_tm);
52282			} else {
52283				arrStaff[i].has_clockin = false;
52284			}
52285			
52286			if (UTIL.isDate(arrStaff[i].clockout_dt)) {
52287				arrStaff[i].has_clockout = true;
52288				arrStaff[i].clockout_tm = new Date(arrStaff[i].clockout_dt).toGloTime();
52289				arrStaff[i].end_sr = UTIL.timeToInt(arrStaff[i].clockout_tm);
52290			} else {
52291				arrStaff[i].has_clockout = false;
52292			}
52293			
52294			_setMissingTime(arrStaff[i]);
52295		}
52296	}
52297	function _setMissingTime(staffObject) {							//when adjust hours (drag open/close time up or down to open a day normall not working) sometimes open or close is empty
52298		if (GLO.ScheduleSummary) {
52299			var arr = GLO.ScheduleSummary;
52300			var isValidOpen = UTIL.isValidTime(staffObject.start_tm, true);
52301			var isValidClosed = UTIL.isValidTime(staffObject.end_tm, true);
52302			
52303			if (isValidOpen && isValidClosed) {
52304				return false;
52305			}
52306			
52307			for (var i=0; i < arr.length; i++) {
52308				if (staffObject.id == arr[i].staff_id) {
52309					if (isValidOpen && !isValidClosed) {
52310						staffObject.end_tm = new Date(arr[i].close_dt).toGloTime();
52311						staffObject.end_sr = UTIL.timeToInt(staffObject.end_tm);
52312						return true;
52313					} else if (!isValidOpen && isValidClosed) {
52314						staffObject.start_tm = new Date(arr[i].open_dt).toGloTime();
52315						staffObject.start_sr = UTIL.timeToInt(staffObject.start_tm);
52316						return true;
52317					}
52318				}
52319			}
52320		}
52321	}
52322	function _finishLoadJson(jrefresh) {
52323		_lastApptRefreshDate = new Date();
52324		jrefresh.removeClass('simple-spin').attr('title', 'Last Refesh at ' + _lastApptRefreshDate.toGloTime());
52325		
52326		GLO.Popup.closeIfExist($('#pop-pos-refresh').closest('.glopop'));
52327	}
52328	
52329    function _boxCountChanged() {
52330    	var newBoxCount;
52331    	var screenWidth = innerWidth;		//$('body')[0].clientWidth;
52332    	var jcontainer = $('#pos-container');
52333    	
52334    	if (screenWidth >= 1500 && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services')) {
52335    		newBoxCount = 56;
52336    	} else if (screenWidth <= 486) {
52337    		newBoxCount = 16;
52338		} else if (screenWidth <= 632) {
52339			newBoxCount = 15;
52340		} else if (screenWidth <= 810) {
52341			newBoxCount = 8;
52342		} else if (screenWidth <= 970) {
52343			newBoxCount = 12;
52344		} else if (screenWidth <= 1200) {
52345			newBoxCount = 16;
52346		} else if (screenWidth <= 1364) {
52347			newBoxCount = 20;
52348		} else if (screenWidth <= 1530) {
52349			newBoxCount = 24;
52350		} else if (screenWidth <= 1700) {
52351			newBoxCount = 28;
52352		} else if (screenWidth <= 1900) {
52353			newBoxCount = 32;
52354		} else {
52355			newBoxCount = 36;
52356		}
52357		
52358		if (newBoxCount != _boxesPerPage) {
52359			_boxesPerPage = newBoxCount;
52360			return true;
52361		} else {
52362			return false;
52363		}
52364    }
52365    
52366    _conPos.displayBoxes = function(grandId, parentId) {
52367    	var isEdit = $('#pos-container').hasClass('edit-pos');
52368    	var products = SA.POS.inventory_json.products;
52369    	
52370    	if (_conPos.sortType === 2) {
52371	    	var vendorId = grandId;
52372	    	var productLineId = parentId;
52373	    	var vendors = SA.POS.inventory_json.vendors;
52374	    	var plines = SA.POS.inventory_json.product_lines;
52375    	} else {
52376    		var categoryId = grandId;
52377	    	var ctypeId = parentId;
52378	    	var categories = SA.POS.inventory_json.categories;
52379	    	var ctypes = SA.POS.inventory_json.types;
52380    	}
52381    	
52382    	if (productLineId) {
52383    		_conPos.filterBoxesProductLine(productLineId, isEdit);
52384    	} else if (vendorId) {
52385    		_conPos.filterBoxesVendor(vendorId, isEdit);
52386    	} else if (categoryId) {
52387    		_conPos.filterBoxesCategory(categoryId, isEdit);
52388    	} else if (ctypeId) {
52389    		_conPos.filterBoxesCategoryType(ctypeId, isEdit);
52390    	} else {
52391    		_conPos.filterBoxesHome(isEdit);
52392    	}
52393    }
52394    
52395    function _isDisplayServices() {
52396    	return $('#btnDisplayServices.selected').length;
52397    }
52398    _conPos.isDisplayServices = function() {
52399    	return _isDisplayServices();
52400    }
52401    _conPos.filterBoxesHome = function(isEdit, isSystemReset) {
52402    	if (!GLO.isPOS) { return; }
52403    	if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); }
52404    	
52405    	var css, arr = [];
52406    	
52407    	if (_isDisplayServices()) {
52408    		_displayServiceGroupBoxes(isEdit);
52409    		return;
52410    	} else if (_conPos.sortType === 2) {
52411	    	var boxtype = 'v', grand = SA.POS.inventory_json.vendors;
52412    	} else {
52413    		var boxtype = 'c', grand = SA.POS.inventory_json.categories;
52414    	}
52415    	
52416    	for (var i=0; i < grand.length; i++) {
52417    		if (isEdit || grand[i].total_product_count > 0) {
52418    			arr.push(_getBox(boxtype, grand[i], isEdit));
52419    		}
52420    	}
52421    	
52422    	if (_conPos.sortType === 2) {
52423    		var products = SA.POS.inventory_json.products;
52424    		
52425	    	for (var j=0; j < products.length; j++) {
52426	    		if (UTIL.isEmpty(products[j].vendor_id)) {
52427	    			arr.push(_getBox('i', products[j], isEdit));
52428	    		}
52429	    	}
52430    	} else {
52431    		var products = SA.POS.inventory_json.products;
52432    		
52433	    	for (var j=0; j < products.length; j++) {
52434	    		if (UTIL.isEmpty(products[j].category_id) && UTIL.isEmpty(products[j].inventory_type_id)) {
52435	    			arr.push(_getBox('i', products[j], isEdit));
52436	    		}
52437	    	}
52438    	}
52439    	
52440    	_displayBoxes(arr, null, null, isSystemReset);
52441    }
52442    
52443    _conPos.filterBoxesCategory = function(categoryId, isEdit, isFromBreadcrumb) {
52444    	var css, arr = [], products = SA.POS.inventory_json.products;
52445    	var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", categoryId);
52446		var categories = SA.POS.inventory_json.categories, ctypes = SA.POS.inventory_json.types;
52447    	
52448    	if (UTIL.isEmpty(isEdit)) { var isEdit = $('#pos-container').hasClass('edit-pos'); }
52449    	
52450    	if (!isEdit) {
52451	    	if ((category.type_count === 1 && category.product_count === category.total_product_count) || category.type_count === 0 || (category.product_count === 0 && category.type_count === 1)) {
52452				if (categories.length === 1) {												//= all products in same category/type.
52453					_displayBoxesProducts(products, isEdit);
52454					return;
52455				} else if (category.type_count === 1 && category.product_count === 0) {		//= all products in same type
52456					for (var i=0; i < ctypes.length; i++) {
52457						if (category.id === ctypes[i].category_id) {
52458							if (isEdit || ctypes[i].product_count > 0) {
52459								_conPos.filterBoxesCategoryType(ctypes[i].id);
52460								return;
52461							}
52462						}
52463					}
52464				}
52465			}
52466    	}
52467    	
52468    	for (var a=0; a < ctypes.length; a++) {
52469    		if (categoryId == ctypes[a].category_id) {
52470    			if (isEdit || ctypes[a].product_count > 0) {
52471    				arr.push(_getBox('ct', ctypes[a], isEdit));
52472    			}
52473    		}
52474    	}
52475    	
52476    	for (var b=0;
52476 b < products.length; b++) {
52477    		if (categoryId == products[b].category_id && UTIL.isEmpty(products[b].inventory_type_id)) {
52478    			arr.push(_getBox('i', products[b], isEdit));
52479    		}
52480    	}
52481    	
52482    	_displayBoxes(arr, category);
52483    }
52484    _conPos.filterBoxesVendor = function(vendorId, isEdit, isFromBreadcrumb) {
52485    	var css, arr = [], vendors = SA.POS.inventory_json.vendors, plines = SA.POS.inventory_json.product_lines, products = SA.POS.inventory_json.products;
52486    	var vendor = _conPos.getVendorObject(vendorId);
52487    	
52488    	if (UTIL.isEmpty(isEdit)) { var isEdit = $('#pos-container').hasClass('edit-pos'); }
52489    	
52490    	if ((vendor.product_line_count === 1 && vendor.product_count === vendor.total_product_count) || vendor.product_line_count === 0) {		//= all products in same product line.
52491			if (vendors.length === 1 && vendors[0].total_product_count === products.length) {						//= all products in same vendor/product line.
52492				_displayBoxesProducts(products, isEdit);
52493				return;
52494			} else if (vendor.product_line_count === 1 && vendor.product_count === 0) {
52495				for (var i=0; i < plines.length; i++) {
52496					if (vendor.id === plines[i].vendor_id) {
52497						if (isEdit || plines[i].product_count > 0) {
52498							_conPos.filterBoxesProductLine(plines[i].id, isEdit);
52499							return;
52500						}
52501					}
52502				}
52503			}
52504		}
52505    	
52506    	for (var a=0; a < plines.length; a++) {
52507    		if (vendorId == plines[a].vendor_id) {
52508    			if (isEdit || plines[a].product_count > 0) {
52509    				arr.push(_getBox('pl', plines[a], isEdit));
52510    			}
52511    		}
52512    	}
52513    	
52514    	for (var b=0; b < products.length; b++) {
52515    		if (vendorId == products[b].vendor_id && UTIL.isEmpty(products[b].product_line_id)) {
52516    			arr.push(_getBox('i', products[b], isEdit));
52517    		}
52518    	}
52519    	
52520    	_displayBoxes(arr, vendor);
52521    }
52522    _conPos.filterBoxesProductLine = function(productLineId, isEdit, isFromBreadcrumb) {
52523    	var css, arr = [], vendors = SA.POS.inventory_json.vendors, plines = SA.POS.inventory_json.product_lines, products = SA.POS.inventory_json.products;
52524    	
52525    	if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); }
52526    	
52527    	for (var i=0; i < products.length; i++) {
52528    		if (productLineId == products[i].product_line_id) {
52529    			arr.push(_getBox('i', products[i], isEdit));
52530    		}
52531    	}
52532    	
52533    	var productLine = _conPos.getPLineObject(productLineId);
52534    	var vendor = _conPos.getVendorObject(productLine.vendor_id);
52535    	
52536    	_displayBoxes(arr, vendor, productLine);
52537    }
52538    _conPos.filterBoxesCategoryType = function(ctypeId, isEdit, isFromBreadcrumb) {
52539    	var css, arr = [], categories = SA.POS.inventory_json.categories, ctypes = SA.POS.inventory_json.types, products = SA.POS.inventory_json.products;
52540    	
52541    	if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); }
52542    	
52543    	for (var i=0; i < products.length; i++) {
52544    		if (ctypeId == products[i].inventory_type_id) {
52545    			arr.push(_getBox('i', products[i], isEdit));
52546    		}
52547    	}
52548    	
52549    	var categoryType = _conPos.getObject(SA.POS.inventory_json.types, "id", ctypeId);
52550		var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", categoryType.category_id);
52551    	
52552    	_displayBoxes(arr, category, categoryType);
52553    }
52554    
52555    function _addEmptyBoxes(arr, box, expectedOrder, isEditPos) {
52556    	var order = box.order;
52557    	
52558    	if (expectedOrder != order) {
52559			for (; expectedOrder < order; expectedOrder++) {
52560				_addEmptyBox(arr, expectedOrder, isEditPos);
52561			}
52562		}
52563		
52564		return expectedOrder;
52565    }
52566    function _addEmptyBox(arr, order, isEditPos) {
52567    	if (isEditPos) {
52568    		var htmDragText = 'Drag Service Box Here';				//_getBoxDragHandle(isEditPos, true);
52569    	} else {
52570    		var htmDragText = '';
52571    	}
52572    	
52573    	var htmEmpty = '<div class="pos-product-box pos-product-box-empty" order_sr="' + order + '">' + htmDragText + '</div>';
52574		
52575		arr.push(htmEmpty);
52576    }
52577    function _getBoxDragHandle(isEditPos, isIncludeText) {
52578    	var htmDragHandle = '';
52579    	
52580    	if (isEditPos) {
52581    		htmDragHandle = '<b class="pos-box-drag"></b>';
52582    		
52583    		if (isIncludeText) {
52584    			htmDragHandle += '<div class="pos-box-drag-text"><i>Drag Service</i> <i>Box Here</i></div>';
52585    		}
52586    	}
52587    	
52588    	return htmDragHandle;
52589    }
52590    
52591    _conPos.filterServiceBoxesByStaff = function(staffId, sgid) {
52592    	var arr = [];
52593    	var jcontainer = $('#pos-container');
52594    	var isCustomServiceOrder = (innerWidth >= 1500) && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services');			//= isAddEmptyBoxes
52595		var isEdit = jcontainer.hasClass('edit-pos');
52596    	var currentOrder = 1;
52597    	
52598    	if (!UTIL.isEmpty(sgid)) {		//display services (in sg)
52599    		var jsvc = $('#allServiceOptions #crSvc' + sgid);
52600    		var sg = _conPos.getServiceGroupObject(sgid);
52601    		var boxes = SA.POS.inventory_json.services;
52602    		
52603    		for (var i=0; i < boxes.length; i++) {
52604	    		if (sgid == boxes[i].service_group_id) {
52605		    		var svcid = boxes[i].id;
52606		    		
52607		    		if (UTIL.isEmpty(staffId) || jsvc.find('option[value="' + svcid + '"]').attr('staff_ids').split(',').has(staffId)
52607) {
52608		    			var price = UserPortal.Booking.lookupService(svcid, staffId).price; 			//UserPortal.Booking.lookupServiceForStaff(svcid, staffId).price;
52609		    			var box = boxes[i];
52610		    			
52611		    			if (!UTIL.isEmpty(price) && UTIL.coalesceMoney(price) != UTIL.coalesceMoney(box.price_mn)) {
52612		    				box = jQuery.extend({}, box);
52613		    				box.price_mn = price;
52614		    			}
52615		    			
52616		    			if (isCustomServiceOrder) {
52617		    				currentOrder = _addEmptyBoxes(arr, boxes[i], currentOrder);
52618		    			}
52619		    			
52620		    			arr.push(_getBox('s', box, isEdit));
52621		    			++currentOrder;
52622	    			} else if (isCustomServiceOrder) {
52623	    				_addEmptyBox(arr, currentOrder, false);
52624	    				++currentOrder;
52625	    			}
52626	    		}
52627	    	}
52628    	} else {						//display sg
52629    		var jsg = $('#ServiceGroupOptionsClone');
52630    		var sg = null;
52631    		var boxes = SA.POS.inventory_json.service_groups;
52632    		
52633    		for (var i=0; i < boxes.length; i++) {
52634	    		sgid = boxes[i].id;
52635	    		
52636	    		if (UTIL.isEmpty(staffId) || jsg.find('option[value="' + sgid + '"]').attr('staff_ids').split(',').has(staffId)) {
52637	    			if (isCustomServiceOrder) {
52638	    				currentOrder = _addEmptyBoxes(arr, boxes[i], currentOrder);
52639	    			}
52640	    			
52641	    			arr.push(_getBox('sg', boxes[i], isEdit));
52642	    			++currentOrder;
52643	    		} else if (isCustomServiceOrder) {
52644    				_addEmptyBox(arr, i+1, false);
52645    				++currentOrder;
52646    			}
52647    			
52648    			++currentOrder;
52649	    	}
52650    	}
52651    	
52652    	_displayBoxes(arr, sg);
52653    	
52654    	if (!UTIL.isEmpty(sgid)) {
52655			jcontainer.find('#pos-service-group-list').find('.pos-type-list[service_group_id = "' + sgid + '"]').addClass('selected-service-group');
52656		}
52657    }
52658    
52659    _conPos.filterBoxesServiceGroup = function(sgid, isEdit, isFromBreadcrumb) {
52660    	var arr = [], services = SA.POS.inventory_json.services;
52661    	var sg = _conPos.getServiceGroupObject(sgid);
52662    	var staffId = $('#pos-header-staff').find('#btnSelectedStaff > a').attr('staff_id');
52663    	
52664    	if (UTIL.isEmpty(isEdit)) { isEdit = $('#pos-container').hasClass('edit-pos'); }
52665    	
52666    	if (true || !UTIL.isEmpty(staffId)) {
52667    		_conPos.filterServiceBoxesByStaff(staffId, sgid);
52668    		return;
52669    	}
52670    	
52671    	for (var i=0; i < services.length; i++) {
52672    		if (sgid == services[i].service_group_id) {
52673    			arr.push(_getBox('s', services[i], isEdit));
52674    		}
52675    	}
52676    	
52677    	_displayBoxes(arr, sg);
52678    	$('#pos-container').find('#pos-service-group-list').find('.pos-type-list[service_group_id = "' + sgid + '"]').addClass('selected-service-group');
52679    }
52680    
52681    function _displayBoxesProducts(products, isEdit) {
52682    	var css, arr = [];
52683    	
52684    	for (var i=0; i < products.length; i++) {
52685    		arr.push(_getBox('i', products[i], isEdit));
52686    	}
52687    	
52688    	_displayBoxes(arr);
52689    }
52690    
52691    function _displayServiceGroupBoxes(isEdit) {
52692    	var arr = [], currentOrder = 1;
52693    	var staffId = $('#pos-header-staff').find('#btnSelectedStaff > a').attr('staff_id');
52694    	var jcontainer = $('#pos-container');
52695    	var isCustomServiceOrder = (innerWidth >= 1500) && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services');			//= isAddEmptyBoxes
52696    	
52697    	if (true || !UTIL.isEmpty(staffId)) {
52698    		_conPos.filterServiceBoxesByStaff(staffId);
52699    		return;
52700    	}
52701    	
52702    	if (_conPos.inventory_json.service_groups.length === 1) {				// || _conPos.inventory_json.services.length <= _boxesPerPage
52703			var svc = _conPos.inventory_json.services;
52704			var boxtype = 's';
52705		} else {
52706			var svc = _conPos.inventory_json.service_groups;
52707			var boxtype = 'sg';
52708		}
52709    	
52710    	for (var i=0; i < svc.length; i++) {
52711    		if (isCustomServiceOrder) {
52712    			currentOrder = _addEmptyBoxes(arr, svc[i], currentOrder, isEdit);
52713    		}
52714    		
52715    		arr.push(_getBox(boxtype, svc[i], isEdit));
52716    		++currentOrder;
52717    	}
52718    	
52719    	_displayBoxes(arr);
52720    }
52721    
52722    function _initBoxSortOrder(jcontainer) {
52723    	if (innerWidth < 1500) {
52724    		_conPos.Edit.openHelp();
52725    		return;
52726    	}
52727    	
52728    	var jwindow = jcontainer.find('#pos-product-window');
52729    	var jTableGrid = jwindow.find('#pos-window-grid');
52730    	
52731    	jwindow.find('.pos-product-box').draggable({
52732			"snap": true, "snapTolerance": 50, "snapMode": "outer"
52733			, "grid": [124,122], "containment": jwindow
52734			, "containment": jTableGrid
52735			, handle: '.pos-box-drag'
52736			//, items: '.pos-product-box'
52737			//, cancel: 'div'
52738			
52739			/*
52740			, start: function(event, ui) {
52741				var jtd = $(ui.helper).parent();
52742				var isRevert = (jtd.find('.pos-product-box').length > 1);
52743				
52744				var jbox = $(this);
52745				jbox.draggable('option', 'revert', isRevert);
52746			}
52747			
52748			, stop: function (event, ui) {
52749				var jbox = $(this);
52750				var jtd = $(ui.helper).parent();
52751				var isRevert = (jtd.find('.pos-product-box').length > 1);
52752				var newOrder = jtd.attr('order_sr');
52753				
52754				if (!jbox.draggable('option', 'revert')) {
52755					var sgid = jbox.attr('service_group_id');
52756					var svcid = jbox.attr('service_id');
52757					
52758					//toDo: Update DB
52759					jbox.attr('order_sr', newOrder);
52760				}
52761			}
52762			*/
52763		});
52764		
52765		_initBoxDroppable(jwindow);
52766		//jwindow.find('.pos-product-box-empty').disableSelection();
52767    }
52768    function _initBoxDroppable(jwindow) {
52769    	jwindow.find('td').droppable({
52770	    	classes: {
52771	        	"ui-droppable-active": "ui-state-active",
52772	        	"ui-droppable-hover": "ui-state-hover"
52773	      	},
52774	      	/* accept: function(jDragBox) {
52775	      		if (jDragBox.hasClass('pos-product-box')) {
52776	      			var jtd = $(this);
52777	      			var jDropBox = jtd.find('.pos-product-box');		//box already in new box (i.e. box currently in dropable)
52778	      			var sgidDragBox = jDropBox.attr('service_group_id'), svcidDragBox = UTIL.coalesceInt(jDropBox.attr('service_id'));
52779	      			var thisOrder = jtd.attr('order_sr'), dragOrder = jDragBox.parent().attr('order_sr');
52780	      			
52781	      			if (jDropBox.length > 0 && thisOrder != dragOrder) {
52782	      				return false;
52783	      			} else {
52784	      				return true;
52785	      			}
52786	      		} else {
52787	      			return false;
52788	      		}
52789	      	}, */
52790		    drop: function(event, ui) {
52791		    	var tdNew = $(this);				//.addClass("ui-state-highlight");
52792		    	var jbox = $(ui.draggable);
52793		    	var tdOld = jbox.parent();
52794		    	
52795		    	var newOrder = tdNew.attr('order_sr'), oldOrder = tdOld.attr('order_sr');
52796		    	var duplicateSGID = null, duplicateSvcId = null;
52797		    	
52798		    	if (newOrder != oldOrder) {		//= box actually moved
52799		    		if (tdNew.find('.pos-product-box').length) {
52800		    			var jDuplicateBox = tdNew.find('.pos-product-box');
52801		    			
52802		    			jDuplicateBox.appendTo(tdOld);
52803			    		jDuplicateBox.css({ "inset": "" });
52804			    		jDuplicateBox.attr('order_sr', oldOrder);
52805			    		duplicateSGID = jDuplicateBox.attr('service_group_id'), duplicateSvcId = jDuplicateBox.attr('service_id');
52806		    		}
52807		    		
52808		    		jbox.appendTo(tdNew);
52809		    		jbox.css({ "inset": "" });
52810		    		jbox.attr('order_sr', newOrder);
52811		    		var sgid = jbox.attr('service_group_id'), svcid = jbox.attr('service_id');
52812		    		
52813		    		//Update DB
52814		    		if (!UTIL.isEmpty(svcid)) {
52815		    			SA.POS.getServiceObject(svcid).order = newOrder;				//SA.POS.inventory_json.service_groups[8].order
52816		    			_updateServiceOrder(sgid, svcid, newOrder);
52817		    			
52818		    			if (!UTIL.isEmpty(duplicateSvcId)) {
52819		    				SA.POS.getServiceObject(duplicateSvcId).order = oldOrder;
52820		    				_updateServiceOrder(duplicateSGID, duplicateSvcId, oldOrder)
52821		    			}
52822		    		} else {
52823		    			SA.POS.getServiceGroupObject(sgid).order = newOrder;
52824		    			_updateServiceGroupOrder();
52825		    		}
52826		    	}
52827		    }
52828		});
52829    }
52830    
52831    function _updateServiceOrder(sgid, svcid, order) {
52832    	var url = GLO.Link.Object.Provider.Ajax + 'ServiceOrder';
52833		
52834		$.ajax({ type: "POST", url: url, "cache": false, data: { "service": svcid, "servicegroup": sgid, "order": order } });
52835            //.success(function(data, textStatus, jqXHR) { })
52836            //.error(function(jqXHR, textStatus, errorThrown) { });
52837    }
52838    function _updateServiceGroupOrder() {
52839		var xml = '', h4 = $('#pos-product-window').find('.pos-product-box');
52840		
52841		for (var i=0; i < h4.length; i++) {
52842			xml += '<h4 service_group_id="' + h4.eq(i).attr('service_group_id') + '" order_sr="' + h4.eq(i).attr('order_sr') + '"/>';
52843		}
52844		
52845		xml = UTIL.htmlEncode('<div>' + xml + '</div>');
52846		var url = GLO.Link.Object.Provider.Ajax + 'ServiceGroupOrder';
52847		
52848    	$.ajax({ type: "POST", url: url, "cache": false, data: { "service_group_xml": xml } });
52849            //.success(function(data, textStatus, jqXHR) { })
52850            //.error(function(jqXHR, textStatus, errorThrown) { });
52851	}
52852	
52853    function _getBoxesHtm(arrBoxes) {
52854    	if (arrBoxes.length > _boxesPerPage) { 		//requires more button.
52855    		var htm = '';
52856    		
52857    		for (var i=0; i < (_boxesPerPage - 1); i++) {
52858    			htm += arrBoxes[i];
52859    		}
52860    		
52861    		var arrowRight = '<i class="fa fa-arrow-right fa-4x"></i> <i class="fa fa-arrow-circle-o-right fa-5x"></i> <i class="fa fa-arrow-circle-right fa-5x"></i>';
52862    		htm += '<div id="pos-box-next" box_type="n" next_item_nr="' + (_boxesPerPage - 1) + '" class="pos-product-box"><div>' + arrowRight + '</div></div>';
52863    	} else {
52864    		var htm = arrBoxes.join('');
52865    	}
52866    	
52867    	return htm;
52868    }
52869    function _displayBoxes(arrBoxes, grand, parent, isSystemReset) {
52870    	_conPos.boxArray = arrBoxes;
52871    	
52872    	var jcontainer = $('#pos-container');
52873    	var jwindow = $('#pos-product-window');
52874    	var isEditServices = jcontainer.hasClass('edit-pos') && jcontainer.hasClass('services');
52875    	
52876    	jcontainer.find('#pos-service-group-list').find('.pos-type-list.selected-service-group').removeClass('selected-service-group');
52877    	
52878    	_addBoxesToScreen(jcontainer, jwindow, arrBoxes, isEditServices);
52879    	_displayEnterProductHeader(grand, parent, isSystemReset);
52880    	_conPos.Edit.displayForIsEdit(grand, parent);
52881    }
52882    function _addBoxesToScreen(jcontainer, jwindow, arrBoxes, isEditServices) {
52883    	var isCustomServiceOrder = (innerWidth >= 1500 && jcontainer.hasClass('service-sort-custom') && jcontainer.hasClass('services'));
52884    	
52885    	if (isEditServices && isCustomServiceOrder && arrBoxes.length <= _boxesPerPage) {
52886    		_addBoxesToScreenGrid(jwindow, arrBoxes);
52887    	} else {
52888    		var htm = _getBoxesHtm(arrBoxes);
52889    		jwindow.html(htm);
52890    	}
52891    	
52892    	if (isEditServices) {
52893    		_initBoxSortOrder(jcontainer);
52894    	}
52895    	
52896    	jwindow.find('.pos-product-box').click(SA.POS.clickBox);				//GLO.UI.setClick(jwindow, '.pos-product-box', SA.POS.clickBox);
52897    }
52898    function _addBoxesToScreenGrid(jwindow, arrBoxes) {
52899    	var tbl = '<table id="pos-window-grid">';
52900    	var cellsPerRow = 8;
52901    	var htmDragText = '<div class="pos-box-drag-text"><i>Drag Service</i> <i>Box Here</i></div>';
52902    	
52903    	for (var i=0; i < 56; i++) {
52904    		if (i % cellsPerRow == 0) {
52905    			tbl += '<tr row_order_sr="' + parseInt(i/cellsPerRow + 1) + '">';
52906    		}
52907    		
52908    		tbl += '<td order_sr="' + (i + 1) + '">' + htmDragText + '</td>';
52909    		
52910    		if (i % cellsPerRow === 7) {
52911    			tbl += '</tr>';
52912    		}
52913    	}
52914    	
52915    	tbl += '</table>';
52916    	var jgrid = jwindow.html(tbl);
52917    	var jtds = jgrid.find('td');
52918    	
52919    	for (var b=0; b < arrBoxes.length; b++) {
52920    		var jbox = $(arrBoxes[b])
52921    		var index = parseInt(jbox.attr('order_sr')) - 1;
52922    		
52923    		if (!jbox.hasClass('pos-product-box-empty')) {
52924    			jtds.eq(index).html(arrBoxes[b]);
52925    		}
52926    	}
52927    }
52928    
52929    function _getBox(boxtype, jsonItem, isEditPos) {
52930    	var css = '', innerStyle = '', innerClass = '', cssClass = '', cornerCnt = '', bottomCorner = '', div = '<div box_type="' + boxtype + '" ';
52931    	
52932    	if (jsonItem["background-color"]) {
52933    		css = "background-color: rgba(" + jsonItem["background-color"] + ", 1);";
52934    		
52935    		if (jsonItem["background-color"] !== '255,255,255') {
52936    			innerClass = ' class="has-back-color"';
52937    		}
52938    	}
52939    	
52940    	if (jsonItem.color) {
52941    		var colorStyle = 'color: rgb(' + jsonItem.color + ');';
52942    		css += colorStyle;
52943    		innerStyle += colorStyle;
52944    	}
52945    	
52946    	if (jsonItem.image_vc && (_conPos.inventory_json.use_service_image_fl || !_isDisplayServices())) {
52947    		css += "background-image: url('" + GLO.Data.cdnDirectory + "upload-folder/" + jsonItem.image_vc + "');";
52948    		innerClass = ' class="has-back-img"';
52949    	}
52950    	
52951    	if (jsonItem.css_class_vc) { var cssClass = ' ' + jsonItem.css_class_vc; }
52952		
52953		if (boxtype === 's') {
52954			div += 'service_id="' + UTIL.cleanString(jsonItem.id) + '" service_group_id="' + UTIL.cleanString(jsonItem.service_group_id) + '" order_sr="' + jsonItem.order + '" ';
52955			cornerCnt = _getPriceSquare(jsonItem.price_mn);
52956		} else if (boxtype === 'sg') {
52957			div += 'service_group_id="' + UTIL.cleanString(jsonItem.id) + '" order_sr="' + jsonItem.order + '" ';
52958			cornerCnt = _getProductCountSquare(jsonItem.service_count);
52959		} else if (boxtype === 'i') {
52960			div += _getProductAttributes(jsonItem.id, jsonItem.product_line_id, jsonItem.vendor_id, jsonItem.inventory_type_id, jsonItem.category_id);
52961			cornerCnt = _getPriceSquare(jsonItem.price_mn);
52962			bottomCorner = _getProductSize(jsonItem);
52963		} else if (boxtype === 'pl') {
52964			div += _getProductAttributes(null, jsonItem.id, jsonItem.vendor_id);
52965			cornerCnt = _getProductCountSquare(jsonItem.product_count);
52966		} else if (boxtype === 'v') {
52967			div += _getProductAttributes(null, null, jsonItem.id);
52968			cornerCnt = _getProductCountSquare(jsonItem.total_product_count);
52969		} else if (boxtype === 'ct') {
52970			div += _getProductAttributes(null, null, null, jsonItem.id, jsonItem.category_id);
52971			cornerCnt = _getProductCountSquare(jsonItem.product_count);
52972		} else if (boxtype === 'c') {
52973			div += _getProductAttributes(null, null, null, null, jsonItem.id);
52974			cornerCnt = _getProductCountSquare(jsonItem.total_product_count);
52975		}
52976		
52977		var htmDragHandle = _getBoxDragHandle(isEditPos && (boxtype == 's' || boxtype == 'sg'));
52978    	var divInner = '<div' + innerClass + ' style="' + innerStyle + '">' + UTIL.coalesce(jsonItem.label, jsonItem.name) + '</div>';
52979    	return div + 'class="pos-product-box' + cssClass + '" style="' + css + '">' + htmDragHandle + cornerCnt + divInner + bottomCorner + '</div>';
52980    }
52981    function _getProductAttributes(inventoryId, productLineId, vendorId, typeId, categoryId) {
52982    	var xml = '';
52983    	
52984    	if (!UTIL.isEmpty(inventoryId)) {
52985    		xml += 'inventory_id="' + inventoryId + '" ';
52986    	}
52987    	
52988    	if (!UTIL.isEmpty(productLineId)) {
52989    		xml += 'product_line_id="' + productLineId + '" ';
52990    	}
52991    	
52992    	if (!UTIL.isEmpty(vendorId)) {
52993    		xml += 'vendor_id="' + vendorId + '" ';
52994    	}
52995    	
52996    	if (!UTIL.isEmpty(typeId)) {
52997    		xml += 'inventory_type_id="' + typeId + '" ';
52998    	}
52999    	
53000    	if (!UTIL.isEmpty(categoryId)) {
53001    		xml += 'category_id="' + categoryId + '" ';
53002    	}
53003    	
53004    	return xml;
53005    }
53006    
53007    function _getProductSize(jsonItem) {
53008    	if (!UTIL.isEmpty(jsonItem.size_vc)) {
53009    		var size = jsonItem.size_vc;
53010    		
53011    		if (!UTIL.isEmpty(jsonItem.unit_abbreviation_vc)) {
53012    			size += ' ' + jsonItem.unit_abbreviation_vc;
53013    		}
53014    		
53015    		return '<span class="product-size">' + size + '</span>';
53016    	} else {
53017    		return '';
53018    	}
53019    }
53020    function _getPriceSquare(price) {
53021    	if (UTIL.coalesceMoney(price) > 0) {
53022    		var dsign = '<span class="dollar-sign">$</span>';
53023    		return '<span class="product-price">' + dsign + UTIL.displayMoney(price, true, false, true) + '</span>';
53024    	} else {
53025    		return '';
53026    	}
53027    }
53028    function _getProductCountSquare(productCnt) {
53029    	return '<span class="product-count">' + productCnt + '</span>';
53030    }
53031    
53032    function _applyPackage(jbox) {
53033    	var inventoryId = jbox.attr('inventory_id'), typeId = UTIL.cleanString(jbox.attr('inventory_type_id')), categoryId = UTIL.cleanString(jbox.attr('category_id'));
53034    	var vendorId = UTIL.cleanString(jbox.attr('vendor_id'));
53035    	var price = UTIL.directTagOnly(jbox.find('.product-price'));
53036    	
53037    	UserPortal.Price.Package.apply(null, inventoryId, typeId, categoryId, vendorId, price);
53038    }
53039    
53040    function _setServiceGroupList(staffId) {
53041    	var jsg = $('#ServiceGroupOptionsClone');
53042		var sgList = '';
53043		var boxes = SA.POS.inventory_json.service_groups;
53044		
53045		for (var i=0; i < boxes.length; i++) {
53046    		sgid = boxes[i].id;
53047    		
53048    		if (UTIL.isEmpty(staffId) || jsg.find('option[value="' + sgid + '"]').attr('staff_ids').split(',').has(staffId)) {
53049    			var sgName = boxes[i].name;
53050    			var bgcolor = 'rgba(' + boxes[i]["background-color"] + ', 1)';
53051    			var style = ' style="background-color: ' + bgcolor + '"';
53052    			var cssTextClass = 'line-count-' + (parseInt(sgName.length / 13) + 1) + ' character-count-' + sgName.length;
53053    			var cssClass = ' class="pos-type-list ' + cssTextClass + '"';					//UTIL.cleanString(boxes[i].css_class_vc)
53054    			var onclick = ' onclick="SA.POS.selectServiceGroup(this)"';
53055    			
53056    			sgList += '<div service_group_id="' + sgid + '"' + cssClass + onclick + style + '>' + sgName + '</div>';
53057    		}
53058    	}
53059    	
53060    	$('#pos-service-group-list').html(sgList);
53061    }
53062    
53063    _conPos.selectServiceGroup = function(element) {
53064    	var jsg = $(element);
53065    	var sgid = jsg.attr('service_group_id');
53066    	_conPos.filterBoxesServiceGroup(sgid);
53067    }
53068    
53069    _conPos.addProductRowToTicket = function(inventoryId, jbox, jbarcode) {
53070    	SA.Ticket.addProductLine(inventoryId);
53071    	
53072    	if (jbox) {
53073			_applyPackage(jbox);
53074		} else {
53075			var typeId = jbarcode.attr('type_id'), categoryId = jbarcode.attr('category_id'), vendorId = jbarcode.attr('vendor_id'), price = jbarcode.attr('price_mn');
53076			UserPortal.Price.Package.apply(null, inventoryId, typeId, categoryId, vendorId, price);
53077		}
53078		
53079		SA.Ticket.ticketChanged();
53080    }
53081    
53082    _conPos.clickBox = function() {
53083    	var jbox = $(this);
53084    	var boxtype = jbox.attr('box_type');
53085    	var isEditPos = $('#pos-container').hasClass('edit-pos');
53086    	
53087    	if (boxtype === 'sg') {
53088    		var sgid = jbox.attr('service_group_id');
53089    		
53090    		if (isEditPos) {
53091    			_conPos.Edit.openServiceGroup(jbox, sgid);
53092    		} else {
53093    			_conPos.filterBoxesServiceGroup(sgid, isEditPos);
53094    		}
53095    	} else if (boxtype === 's') {
53096    		var serviceId = jbox.attr('service_id'), sgid = jbox.attr('service_group_id');
53097    		
53098    		if (isEditPos) {
53099    			_conPos.Edit.openService(jbox, serviceId);
53100    			//return GLO.Popup.Info.open('_conPos.clickBox: Edit POS Services will be enabled in March 2021', 'Edit POS');			//toDo: Edit Services
53101    		} else {
53102    			SA.Ticket.addServiceLine(serviceId, sgid);
53103    			SA.Ticket.ticketChanged();
53104    		}
53105    	} else if (boxtype === 'i') {
53106    		var inventoryId = jbox.attr('inventory_id');
53107    		
53108    		if (isEditPos) {
53109    			_conPos.Edit.openProduct(jbox, inventoryId);
53110    		} else {
53111    			_conPos.addProductRowToTicket(inventoryId, jbox);
53112    		}
53113    	} else if (boxtype === 'pl') {
53114    		var productLineId = jbox.attr('product_line_id');
53115    		_conPos.filterBoxesProductLine(productLineId, isEditPos);
53116    		
53117    		if (isEditPos) { _conPos.Edit.openBrandOrPLine(jbox, true); }					//_conPos.Edit.moveBoxForEdit(jbox);
53118    	} else if (boxtype === 'v') {
53119    		if (isEditPos) { _conPos.Edit.openBrandOrPLine(jbox); }
53120    		
53121    		var vid = jbox.attr('vendor_id');
53122    		_conPos.filterBoxesVendor(vid, isEditPos);
53123    	} else if (boxtype === 'ct') {
53124    		var id = jbox.attr('inventory_type_id');				//category_type_id
53125    		_conPos.filterBoxesCategoryType(id, isEditPos);
53126    		
53127    		if (isEditPos) { _conPos.Edit.openCategoryOrType(jbox, true); }
53128    	} else if (boxtype === 'c') {
53129    		var id = jbox.attr('category_id');
53130    		_conPos.filterBoxesCategory(id, isEditPos);
53131    		
53132    		if (isEditPos) { _conPos.Edit.openCategoryOrType(jbox); }
53133    	} else if (boxtype === 'p' || boxtype === 'n') {
53134    		var start = jbox.attr('next_item_nr');
53135    		_displayMore(start);
53136    	}
53137    }
53138    
53139    _conPos.addTicketRowComplete = function() {
53140    	$('#pos-product-header-enter #pos-enter-product-or-amount').val('');
53141    	$('#pos-product-header-enter .btnAction2').addClass('hide');
53142    }
53143    
53144    function _displayMore(startItem) {
53145    	startItem = parseInt(startItem);
53146    	var boxCnt = (_boxesPerPage - 2);
53147    	
53148    	if (startItem > 0) {				//is more/next.
53149	    	var prevItem = startItem - boxCnt;
53150	    	if (startItem < _boxesPerPage) { --prevItem; }				//=prev screen will still have "prev" button.
53151			
53152			var arrowLeft = '<i class="fa fa-arrow-left fa-4x"></i> <i class="fa fa-arrow-circle-o-left fa-5x"></i> <i class="fa fa-arrow-circle-left fa-5x"></i>';
53153			var htm = '<div  id="pos-box-prev" box_type="p" next_item_nr="' + prevItem + '" class="pos-product-box"><div>' + arrowLeft + '</div></div>';
53154		} else {							//is prev.
53155			startItem = 0;
53156			boxCnt = (_boxesPerPage - 1);
53157			var htm = '';
53158		}
53159		
53160		for (var i = startItem; i < startItem + boxCnt; i++) {
53161			if (_conPos.boxArray.length === i) { break; }
53162			htm += _conPos.boxArray[i];
53163		}
53164		
53165		if (_conPos.boxArray.length - 1 == startItem + boxCnt) {
53166			htm += _conPos.boxArray[startItem + boxCnt];
53167		} else if (_conPos.boxArray.length > startItem + boxCnt) {
53168			var arrowRight = '<i class="fa fa-arrow-right fa-4x"></i> <i class="fa fa-arrow-circle-o-right fa-5x"></i> <i class="fa fa-arrow-circle-right fa-5x"></i>';
53169			htm += '<div id="pos-box-next" box_type="n" next_item_nr="' + (startItem + boxCnt) + '" class="pos-product-box"><div>' + arrowRight + '</div></div>';
53170    	}
53171    	
53172    	var jwindow = $('#pos-product-window');
53173    	jwindow.html(htm);
53174    	jwindow.find('.pos-product-box').click(SA.POS.clickBox);				//GLO.UI.setClick(jwindow, '.pos-product-box', SA.POS.clickBox);
53175    }
53176    
53177    function _getGrandBreadCrumb(grand, jbreadcrumb) {
53178    	var isEdit = $('#pos-container').hasClass('edit-pos');
53179    	
53180    	if (_isDisplayServices()) {
53181    		jbreadcrumb.attr('service_group_id', grand.id);
53182    		return ' id="pos-breadcrumb-sg" service_group_id="' + grand.id + '" onclick="SA.POS.filterBoxesServiceGroup(' + grand.id + ', ' + isEdit + ', true)"';
53183    	} else if (_conPos.sortType === 2) {
53184    		jbreadcrumb.attr('vendor_id', grand.id);
53185    		return ' id="pos-breadcrumb-vendor" vendor_id="' + grand.id + '" onclick="SA.POS.filterBoxesVendor(' + grand.id + ', ' + isEdit + ', true)"';
53186    	} else {
53187    		jbreadcrumb.attr('category_id', grand.id);
53188    		return ' id="pos-breadcrumb-category" category_id="' + grand.id + '" onclick="SA.POS.filterBoxesCategory(' + grand.id + ', ' + isEdit + ', true)"';
53189    	}
53190    }
53191    
53192    function _getParentBreadCrumb(parent, jbreadcrumb) {
53193    	var isEdit = $('#pos-container').hasClass('edit-pos');
53194    	
53195    	if (_isDisplayServices()) {
53196    		return GLO.Popup.Warning.open('Services Have No Parent (only Grand)', 'Get Parent Breadcrumb');
53197    		
53198    		//jbreadcrumb.attr('service_group_id', parent.id);
53199    		//return ' id="pos-breadcrumb-sg" service_group_id="' + parent.id + '" onclick="SA.POS.filterBoxesServiceGroup(' + parent.id + ')"';
53200    	} else if (_conPos.sortType === 2) {
53201    		jbreadcrumb.attr('product_line_id', parent.id);
53202    		return ' id="pos-breadcrumb-pline" product_line_id="' + parent.id + '" onclick="SA.POS.filterBoxesProductLine(' + parent.id + ', ' + isEdit + ', true)"';
53203    	} else {
53204    		jbreadcrumb.attr('inventory_type_id', parent.id);
53205    		return ' id="pos-breadcrumb-category-type" inventory_type_id="' + parent.id + '" onclick="SA.POS.filterBoxesCategoryType(' + parent.id + ', ' + isEdit + ', true)"';
53206    	}
53207    }
53208    
53209    function _getAddParentBreadCrumb(arrow) {
53210    	var isEdit = $('#pos-container').hasClass('edit-pos');
53211    	
53212    	if (_isDisplayServices()) {
53213    		return '';		//return GLO.Popup.Warning.open('Services Have No Parent (only Grand)', 'Get Add Parent Breadcrumb');
53214    	} else if (_conPos.sortType === 2) {
53215    		return arrow + '<span id="pos-product-header-add-pline" onclick="SA.POS.Edit.openNewPLine()"><i class="fa fa-plus"></i> <span>' + SA.Resource.Add.toLowerCase() + ' <b>' + SA.Resource.Product.toLowerCase() + ' </b>' + SA.Resource.Line.toLowerCase() + '</span> </span>';
53216    	} else {
53217    		return arrow + '<span id="pos-product-header-add-category-type" onclick="SA.POS.Edit.openNewCategoryType()"><i class="fa fa-plus"></i> <span>' + SA.Resource.AddType.toLowerCase() + '</span> </span>';
53218    	}
53219    }
53220    
53221    function _displayEnterProductHeader(grand, parent, isSystemReset) {
53222    	var jinput = $('#pos-product-header-enter');
53223    	var jbreadcrumb = $('#pos-product-header-breadcrumb');
53224    	var jpos = $('#pos-container');
53225    	jbreadcrumb.removeAttr('vendor_id').removeAttr('category_id').removeAttr('product_line_id').removeAttr('inventory_type_id').removeAttr('service_group_id');
53226    	
53227    	if (!UTIL.isEmptyObject(grand)) {
53228    		var arrow = '<b class="breadcrumb-spacer">&#10140;</b>';
53229	    	var htm = '<span id="btnPosHome" class="btnAdd"><a id="pos-breadcrumb-home" onclick="SA.POS.filterBoxesHome()">' + SA.Resource.Home + '</a></span>' + arrow
53230	    	var pnm = '', gnm = grand.name;
53231	    	var attribute = _getGrandBreadCrumb(grand, jbreadcrumb);
53232	    	
53233	    	if (!UTIL.isEmptyObject(parent)) {
53234	    		var isEditPos = $('#pos-container').hasClass('edit-pos');
53235	    		
53236	    		if (!isEditPos && grand.type_count + grand.product_count === 1) {			//= grand only contains parent so header only needs to contain grand.
53237	    			parent = null;
53238	    		} else {
53239	    			pnm = parent.name;
53240	    		}
53241	    	}
53242	    	
53243	    	if ( (gnm.length > 20 && UTIL.cleanString(pnm).length > 10) || (gnm.length > 20 && UTIL.cleanString(pnm).length > 5) ) {
53244	    		htm += UTIL.maxStringHtml(gnm, 15, false, 'a', '', '', attribute);
53245	    	} else if (gnm.length > 15 && UTIL.cleanString(pnm).length > 15) {
53246	    		htm += UTIL.maxStringHtml(gnm, 12, false, 'a', '', '', attribute);
53247	    	} else {
53248	    		htm += UTIL.maxStringHtml(gnm, 30, false, 'a', '', '', attribute);
53249	    	}
53250    		
53251    		if (!UTIL.isEmptyObject(parent)) {
53252    			attribute = _getParentBreadCrumb(parent, jbreadcrumb);
53253    			
53254    			if (pnm.length > 20 && gnm.length > 15) {
53255		    		htm += arrow + UTIL.maxStringHtml(pnm, 15, false, 'a', '', '', attribute);
53256		    	} else if (pnm.length > 15 && gnm.length > 5) {
53257		    		htm += arrow + UTIL.maxStringHtml(pnm, 15, false, 'a', '', '', attribute);
53258		    	} else {
53259		    		htm += arrow + UTIL.maxStringHtml(pnm, 20, false, 'a', '', '', attribute);
53260		    	}
53261    		} else if ($('#pos-container').hasClass('edit-pos') && !_isDisplayServices()) {
53262    			htm += _getAddParentBreadCrumb(arrow);
53263    		}
53264    		
53265    		jpos.addClass('has-breadcrumb');
53266    		jinput.addClass('hide');
53267    		jbreadcrumb.html(htm).removeClass('hide');
53268    	} else if (jinput.hasClass('hide')) {
53269    		var fnSetBreadcrumb = function() {
53270    			jbreadcrumb.html('').addClass('hide');
53271	    		jinput.removeClass('hide');
53272	    		jpos.removeClass('has-breadcrumb');
53273    		};
53274    		
53275    		if (isSystemReset) {
53276    			fnSetBreadcrumb();
53277    		} else {
53278	    		var timeout = 10;
53279	    		if (GLO.Info.isMobile(true)) { timeout = 400; }			//= avoids user accidentally putting focus on 'Enter Product or Price' input field.
53280	    		
53281	    		setTimeout(function() {
53282		    		fnSetBreadcrumb();	
53283	    		}, timeout);
53284    		}
53285    	}
53286    }
53287    
53288    _conPos.toggleMenu = function(isClose) {
53289    	var j = $('#pos-container');
53290    	
53291    	if (j.hasClass('edit-pos')) { _conPos.Edit.changeMode(); }
53292    	
53293    	var jmenu = j.find('#pos-portal-menu');
53294    	var jpos = j.find('#pos');
53295    	
53296    	if (isClose || jmenu.is(':visible')) {
53297    		_conPos.closeMenu(jpos, jmenu);
53298    	} else {
53299    		_conPos.openMenu(jpos, jmenu);
53300    	}
53301    }
53302    
53303    _conPos.openMenu = function(jpos, jmenu) {
53304    	jpos.addClass('compress');													//toDo: add animation.
53305    	jmenu.removeClass('hide');			//.parent().removeClass('hide');		//toDo: add animation.
53306    	
53307    	$('#pos-action-menu:visible').addClass('hide');								//toDo: add animation (if exists).
53308    	
53309    	$('#pos-action-menu-button').removeClass('menu-open');
53310    	$('#pos-menu-button').addClass('menu-open');
53311	}
53312    
53313    _conPos.closeMenu = function(jpos, jmenu) {
53314    	jmenu.addClass('hide');				//.parent().addClass('hide');			//toDo: add animation.
53315    	jpos.removeClass('compress');												//toDo: add animation.
53316    	
53317    	$('#pos-menu-button').removeClass('menu-open');
53318	}
53319    
53320    _conPos.toggleActionMenu = function(isClose) {
53321    	var j = $('#pos-container');
53322    	
53323    	if (j.hasClass('edit-pos')) { _conPos.Edit.changeMode(); }
53324    	
53325    	var jmenu = j.find('#pos-action-menu');
53326    	var jpos = j.find('#pos');
53327    	
53328    	if (isClose || jmenu.is(':visible')) {
53329    		_conPos.closeActionMenu(jpos, jmenu);
53330    	} else {
53331    		_conPos.openActionMenu(jpos, jmenu);
53332    	}
53333    }
53334    
53335    _conPos.openActionMenu = function(jpos, jmenu) {
53336    	jpos.addClass('compress');													//toDo: add animation.
53337    	jmenu.removeClass('hide');		//.parent().removeClass('hide');			//toDo: add animation.
53338    	
53339    	$('#pos-portal-menu:visible').addClass('hide');								//toDo: add animation (if exists).
53340    	
53341    	$('#pos-menu-button').removeClass('menu-open');
53342    	$('#pos-action-menu-button').addClass('menu-open');
53343	}
53344    
53345    _conPos.closeActionMenu = function(jpos, jmenu) {
53346    	jmenu.addClass('hide');			//.parent().addClass('hide');				//toDo: add animation.
53347    	jpos.removeClass('compress');												//toDo: add animation.
53348    	
53349    	$('#pos-action-menu-button').removeClass('menu-open');
53350	}
53351	
53352	_conPos.logout = function() {
53353		var sname = GLO.Info.getStaffName();
53354		
53355		var fn = function() {
53356			document.location = GLO.Link.Page.LoginHome + 'logout';
53357		}
53358		
53359		new GLO.Popup.Confirm(SA.Resource.LogoutConfirm + ' ' + sname + '?', fn
53359);
53360	}
53361    
53362    _conPos.searchKeyUp = function(element) {
53363    	if (UTIL.isNumber(element.value)) {
53364    		$("#pos-product-header-enter").addClass('is-numeric');
53365    	} else {
53366    		$("#pos-product-header-enter").removeClass('is-numeric');
53367    	}
53368    }
53369    
53370    _conPos.openStaffPreview = function(staffBox) {
53371    	var ajaxRequest, jbox = $(staffBox);
53372    	var sid = jbox.attr('staff_id'), isFA = UTIL.parseBool(jbox.attr('is_first_available_fl'));
53373    	var sname = jbox.find('.pos-staff-name').text();
53374    	var thumb = jbox.find('.staff-thumbnail');
53375    	
53376    	var htmPreview = '<div id="pop-preview-staff"><p style="letter-spacing: 1px; font-weight: bold; font-size: 20px;">Looking up Tickets for ' + sname + '...</p></div>';
53377    	var url = GLO.Link.WebsiteDomain + 'pos/StaffPreview?cdn=' + GLO.Data.cdnVersion + '&staff=' + sid;
53378    	
53379    	function fnCancelOpenTicket() {
53380    		if (ajaxRequest && ajaxRequest.abort) {
53381    			ajaxRequest.abort();
53382    		}
53383    		
53384    		if (oj && oj.close) {
53385    			oj.close();
53386    		}
53387    	}
53388    	
53389    	var oj = new GLO.Popup.Processing.open(htmPreview, sname, fnCancelOpenTicket);
53390    	var jpop = oj.getPopup();
53391    	jpop.find('.btnOk').addClass('btnAdd').attr('id', 'btnNewTicketQuick').find('>a').text('New Ticket').css({ "font-size": "20px" });
53392    	
53393    	ajaxRequest = $.ajax({ type: "GET", url: url, "cache": false })
53394            .success(function(data, textStatus, jqXHR) {
53395                if ($(data).hasClass('warning')) {
53396					if (UTIL.parseBool($(data).attr('must_refresh'))) {
53397						setTimeout(function() {
53398							location.reload();
53399						}, 450);
53400					}
53401					
53402					new GLO.Popup.Warning(data);
53403					return true;
53404				} else if (oj.close()) {
53405                	_staffPreviewHtm(sid, sname, isFA, thumb, data);
53406                }
53407            }).error(function(jqXHR, textStatus, errorThrown) {
53408            	if (textStatus == 'abort' && event && event.currentTarget && event.currentTarget.id == 'btnNewTicketQuick') {
53409            		if (oj && oj.close) {
53410            			oj.close();
53411            		}
53412            		
53413            		SA.Ticket.newTicket(sid, sname, isFA);
53414            	}
53415            });
53416    }
53417    function _getClockInIcon(staffId, isFA) {
53418    	if (!isFA && $('#header-main-row-clock-out #clock-out-icon').length) {
53419    		return '<span id="clock-out-icon" class="sa-sprite" onclick="UserPortal.Edit.ClockIn.pickStaff(' + staffId + ')" title="Clock-In/Out"> <a style="color: rgb(255, 255, 255);"></a> </span>';
53420    	}
53421    }
53422    
53423    _conPos.helpQuickGuideMore = function() {
53424    	var jpop = $('#pop-help-pos-screen-quick-guide').closest('.glopop');
53425    	jpop.find('.hide-detail').removeClass('hide-detail');
53426    	jpop.find('#help-pos-screen-more').remove();
53427    }
53428    _conPos.openHelpQuickGuide = function(scrollTo) {
53429    	var arrow = '<b class="arrow-right" style="padding: 0 4px;">&#10140;</b>';
53430    	var screen = '<b class="narrow-text" style="color: #4F81BD;">POS Screen</b>';
53431    	var card = '<b class="narrow-text" style="color: #4F81BD;">Staff Card</b>';
53432    	var day = '<b class="narrow-text" style="color: #4F81BD;">Staff Summary popup</b>';
53433    	var panel = '<b class="narrow-text" style="color: #4F81BD;">Ticket Panel</b>';
53434    	var bar = '<b class="narrow-text" style="color: #4F81BD;">Ticket Status Bar</b>';
53435    	
53436    	var htmScreen = _getPosScreenHelp(arrow, screen, card, day, panel, bar);
53437    	var htmStaffCards = _getStaffCardHelp(arrow, screen, card, day, panel, bar);
53438    	var htmStaffOverview = _getStaffPopupHelp(arrow, screen, card, day, panel, bar);
53439    	
53440    	var htmPanel = _getPosClientPanelHelp(arrow, screen, card, day, panel, bar);
53441    	var htmTicket = _getTicketHelp(arrow, screen, card, day, panel, bar);
53442    	var htmColors = _getColorHelp(arrow, screen, card, day, panel, bar);
53443    	
53444    	var htm = '<div id="pop-help-pos-screen-quick-guide">' + htmScreen + htmStaffCards + htmStaffOverview + htmPanel + htmTicket + htmColors + '</div>';
53445    	var jpop = GLO.Popup.Custom.openSimple(htm, 'POS Screen Overview', null, null, null, 'wide-screen-guide').addClass('pop-pos');
53446    	GLO.Popup.Custom.singleButton(jpop, 'Close');
53447    	
53448    	//if (scrollTo) { UI.highlight(jpop.find('#' + scrollTo)); }
53449    }
53450    function _getPosScreenHelp(arrow, screen, card, day, panel, bar) {
53451    	var tina = '<i class="narrow-text">Tina</i>', eartha = '<i class="narrow-text">Eartha</i>';
53452    	var chloe = '<i class="narrow-text">Chloe</i>', ashley = '<i class="narrow-text">Ashley</i>';
53453    	var bart = '<i class="narrow-text">Bartholomew</i>', sara = '<i class="narrow-text">Sara</i>';
53454    	
53455    	var liAlways = '<li class="always-display">';
53456    	var bNarrow = '<b class="narrow-text" style="color: #4F81BD;">';
53457    	
53458    	var bSignIn = '<b class="narrow-text" style="background-color: deeppink; color: white;">Signed-In</b>';
53459    	var bNowTag = '<b class="narrow-text" style="color: white; background: linear-gradient(rgba(120, 0,200, .1), rgba(120, 0,200, .8)), linear-gradient(black, black);">';
53460    	var bNow1 = bNowTag + 'Now</b>';
53461    	var bNow2 = bNowTag + 'Now <span style="color: inherit;">(or very soon)</span></b>';
53462    	var bCheckIn = '<b class="narrow-text" style="background-color: rgba(255, 255, 0, .4);">Checked-In</b>';
53463    	var bReady = '<b class="narrow-text" style="background-color: rgb(40, 180, 255);">Ready to Pay</b>';
53464    	var bCheckOut = '<b class="narrow-text" style="background-color: #9AFF9A;">Checked-Out</b>';
53465    	var bAvailable = '<b class="narrow-text" style="background-color: rgb(0,255,0);">AVAILABLE</b>';
53466    	var bLate = '<b class="narrow-text" style="background-color: rgb(220,220,220);">Late</b>';
53467    	var bUpcoming = '<b class="narrow-text" style="background-color: purple; color: white;">Upcoming</b>';
53468    	var bPast = '<b class="narrow-text" style="background-color: rgba(200,200,200, .6);">Past</b>';
53469    	var bNoShow = '<b class="narrow-text" style="background-color: rgb(255,0,0);">No Show</b>';
53470    	var bLateCancel = '<b class="narrow-text" style="background-color: orange;">Late Cancel</b>';
53471    	
53472    	var cSignIn = '<li>At the top in pink is <i class="narrow-text">Serena Smith</i> who recently ' + bSignIn + '</li>';
53473    	var cNow = '<li><i class="narrow-text">Casa</i> + <i class="narrow-text">Silvia</i> who have an appointment ' + bNow2 + '</li>';
53474    	var cCheckIn = '<li><i class="narrow-text">Alana Cook</i> in yellow is currently ' + bCheckIn + '</li>';
53475    	var cReady = '<li>In blue <i class="narrow-text">Daniela</i> is ' + bCheckIn + ' and her ticket is ' + bReady + '</li>';
53476    	
53477    	var cLate = '<li><i class="narrow-text">Diana Mills</i> is 48 minutes ' + bLate + ' <span style="letter-spacing: 0;">(Diana might be a no-show)</span></li>';
53478    	var cUpcoming = '<li>In Purple are 4 ' + bUpcoming + ' appointments</li>';
53479    	var cPast = '<li><i class="narrow-text">Alice Moon</i> is a ' + bPast + ' appointment <span style="letter-spacing: 0; font-size: 90%;">(that was never <span>' + bCheckIn + ', ' + bCheckOut + ', or marked as ' + bNoShow + ')</li>';
53480    	var cCheckOut = '<li style="margin-bottom: 20px;">At the bottom of the ' + panel + ' are all the ' + bCheckOut + ' tickets in Green</li>';
53481    	var cNote = liAlways + panel + 'displays all tickets for current day <span>(except ' + bNoShow + ' + ' + bLateCancel + ' tickets)</span></li>';
53482    	var cAlways = liAlways + 'Press any' + bNarrow + 'Ticket Status bar</b> to open ticket</li>';
53483    	
53484    	var exampleDetail = '<i class="hide-detail">, in example image below:</i>';
53485    	var bCards = '<b class="pos-screen-quick-header">Staff Cards</b>';
53486    	
53487    	var msgCards1 = '<p style="margin-bottom: 0;">' + bCards + ' left-side of ' + screen + ' has each' + card + arrow + ' displaying staff\'s status' + exampleDetail + '</p>';
53488    	var msgCards2 = '<ul class="hide-detail" style="font-size: 110%;">'
53489    			+ '<li>' + tina + ' + ' + eartha + ' are ' + bAvailable + '</li>'
53490    			+ '<li>' + chloe + ' has an appointment ' + bNow1 + ' + ' + ashley + ' has an appointment starting ' + bNowTag + 'in 13 minutes</b></li>'
53491    			+ '<li>' + sara + ' client <b class="narrow-text" style="background-color: deeppink; color: white;">Signed-In 3 minutes ago</b></li>'
53492    			+ '<li>' + bart + ' ticket is estimated to <b class="narrow-text" style="background-color: rgba(255, 255, 0, .6);">end in 13 minutes</b></li>'
53493    			+ liAlways + 'Press a' + bNarrow + 'Staff Card</b> to open the' + bNarrow + 'Staff Summary popup</b></li>'
53494    		+ '</ul>';
53495    	
53496    	var bPanel = '<b class="pos-screen-quick-header">Ticket Panel</b>';
53497    	var msgPanel1 = '<p style="margin-bottom: 0;">' + bPanel + ' right-side of ' + screen + ' has ' + panel + arrow + 'displaying ' + bar + ' for each ticket</p>';
53498    	var msgPanelList = '<ul id="help-pos-screen-panel-list" class="hide-detail">' + cSignIn + cNow + cCheckIn + cReady + cLate + cUpcoming + cPast + cCheckOut + cNote + cAlways + '</ul>';
53499    	
53500    	var imgScreen = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/pos-screen2.png"/>';
53501    	imgScreen = '<div id="help-pos-screen-diagram">' + imgScreen + '</div>';
53502    	
53503    	var htmCards = '<div id="help-pos-screen-cards">' + msgCards1 + msgCards2 + '</div>';
53504    	var htmBars = '<div id="help-pos-screen-panel">' + msgPanel1 + msgPanelList + '</div>';
53505    	var btnMore = '<div id="help-pos-screen-more"> <span class="btnAdd"> <a onclick="SA.POS.helpQuickGuideMore()">More Info...</a> </span> </div>';
53506    	
53507    	return '<div id="help-pos-screen">' + htmCards + htmBars + btnMore + imgScreen + '</div>';
53508    }
53509    function _getStaffCardHelp(arrow, screen, card, day, panel, bar) {
53510    	var header = '<h3>POS Staff Cards</h3>';
53511    	var imgStaffCard = '<img id="pos-full-staff-card" src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-cards/full-staff-card2.png"/>';
53512	    imgStaffCard = '<div id="help-staff-card-diagram">' + imgStaffCard + '</div>';
53513    	var msg1 = '<p style="margin-bottom: 0;">Each ' + card + ' displays</p>';
53514    	
53515    	//if the staff is estimated to complete the current checked-in ticket in less than one hour (based on service time) then it will display when the the ticket is expected to be completed, otherwise displays BUSY
53516    	//Available - purple: has upcoming appointment, but has time to do another service before appointment | Available - greeen: no upcoming appointment
53517    	
53518    	var bubbleSignIn = '<span class="staff-appt-count staff-appt-signin "><b class="staff-appt-signin-count" title="1 client self sign-in">1</b></span>';
53519    	var bubbleCheckIn = '<span class="staff-appt-count staff-appt-checkin"><b class="staff-appt-checkin-count" title="2 tickets checked-in">2</b></span>';
53520    	var bubbleCheckOut = '<span class="staff-appt-count staff-appt-checkout"><b class="staff-appt-checkout-count" title="3 tickets checked-out">3</b></span>';
53521    	
53522    	var bubbleNow = '<span class="staff-appt-count staff-appt-now"><b class="staff-appt-now-count" title="1 now appointment (starts within 20 minutes)">1</b></span>';
53523    	var bubbleUpcoming = '<span class="staff-appt-count staff-appt-upcoming"><b class="staff-appt-upcoming-count" title="4 upcoming appointments">4</b></span>';
53524    	var bubbleLate = '<span class="staff-appt-count staff-appt-late"><b class="staff-appt-late-count" title="1 late appointment (start time more than 20 minutes after current time, but less than 90 minutes)">1</b></span>';
53525    	
53526    	var bubbles = bubbleSignIn + '  ' + bubbleCheckIn + '  ' + bubbleCheckOut + '  ' + bubbleNow + '  ' + bubbleUpcoming + '  ' + bubbleLate;
53527    	bubbles = '<div id="pos-staff-list"> <div class="pos-staff-cell">' + bubbles + '</div> </div>';
53528    	
53529    	var bSignIn = '<b class="narrow-text" style="background-color: deeppink; color: white;">SIGN-IN 3 minutes ago</b>';
53530    	var bNowTag = '<b class="narrow-text" style="color: white; background: linear-gradient(rgba(120, 0,200, .1), rgba(120, 0,200, .8)), linear-gradient(black, black);">';
53531    	var bAvailable = '<b class="narrow-text" style="background-color: rgb(0,255,0);">AVAILABLE</b>';
53532    	var bBusy = '<b class="narrow-text" style="background-color: rgba(255, 255, 0, .4);">BUSY</b>';
53533    	
53534    	var thumb = '<li>
53534Staff thumbnail image <span>(if uploaded)</span></li>';
53535    	var status = '<li>Status bar' + arrow + bAvailable + ', ' + bBusy + ', ' + bNowTag + 'APPT NOW</b>, ' + bNowTag + 'APPT in 13 minutes</b>, ' + bSignIn + ', etc...</li>';
53536    	var time = '<li>Time range working' + arrow + '<b>2 pm - 9 pm</b></li>';
53537    	var circle = '<li>Ticket count bubbles <span>(uses colors listed above)</span>' + arrow + bubbles + '</li>';
53538    	var list = '<ul>' + thumb + status + time + circle + '</ul>';
53539    	
53540    	var msgBreak = '<p>Staff Cards also display when a staff is about to go on break or is on break</p>';
53541    	var imgBreakSoon = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-cards/break-soon.png" style="width: 40%; max-width: 150px; margin: auto; padding-right: 40px;"/>';
53542    	var imgBreakTime = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-cards/break-time.png" style="width: 40%; max-width: 150px; margin: auto;"/>';
53543	    var htmBreak = '<div id="help-staff-card-break">' + msgBreak + '<div id="help-staff-card-break-images">' + imgBreakSoon + imgBreakTime + '</div></div>';
53544    	
53545    	return '<div id="help-pos-staff-card" style="padding-bottom: 24px; background-color: white;">' + header + imgStaffCard + msg1 + list + htmBreak + '</div>';
53546    }
53547    function _getStaffPopupHelp(arrow, screen, card, day, panel, bar) {
53548    	var header = '<h3>POS Staff Summary popup</h3>';
53549    	var img = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/staff-overview2.png" style="width: 90%; max-width: 640px; margin: auto; margin-bottom: 24px;"/>';
53550	    var imgDiv = '<div id="help-staff-preview-diagram">' + img + '</div>';
53551    	
53552    	var aProfileSvc = '<a onclick="GLO.Uri.gotoUri2(\'provider/profile/4?helloback=website\')">Profile ' + arrow + ' Service</a>';
53553    	var aResourceSetup = '<a onclick="GLO.Uri.gotoUri2(\'provider/manage/resource\', this, event, true)">resource setup</a>';
53554    	
53555    	//var msg = '<p style="padding-bottom: 0;">Press a ' + card + ' to display the ' + day + '</p>';
53556    	var msg1 = '<p>Press a ' + card + arrow + 'to open the ' + day + '</p>';
53557    	var msg2 = '<p>The service name is the service color set in ' + aProfileSvc + '</p>';
53558    	var msg3 = '<p>Displays resource name above service time, if ' + aResourceSetup + ' <i class="narrow-text">(can setup resources like pedicure chair, booth #, massage table, etc)</i></p>';
53559    	
53560    	var onSite = '(clients on premise)';
53561    	if (GLO.Data.provider.industry_cd == 1 || GLO.Data.provider.industry_cd == 8) { onSite = '(clients in salon)'; }
53562    	
53563    	var bSignin = '<b class="ticket-status pos-color-signin">Sign-In</b>';
53564		var bCheckin = '<b class="ticket-status pos-color-checkin">Checked-In</b>';
53565		var bReady = '<b class="narrow-text pos-color-ready">READY to PAY</b>';
53566		var bNow = '<b class="ticket-status pos-color-now">NOW</b>';
53567		
53568		var bLate = '<b class="ticket-status pos-color-late">LATE</b>';
53569		var bPast = '<b class="ticket-status pos-color-past">PAST</b>';
53570		var bUpcoming = '<b class="ticket-status pos-color-upcoming">UPCOMING</b>';
53571		
53572		var bCheckout = '<b class="ticket-status pos-color-checkout">Checked-Out</b>';
53573		var bNoShow = '<b class="ticket-status pos-color-no-show">No Show</b>';
53574		var bLateCancel = '<b class="ticket-status pos-color-late-cancel">Late Cancel</b>';
53575    	
53576    	var current = '<li><b>Current Tickets</b> ' + onSite + ': ' + bSignin + ', ' + bCheckin + ', ' + bReady + ', ' + bNow + '</li>';
53577    	var scheduled = '<li><b>Scheduled Tickets</b> ' + bLate + ', ' + bPast + ', ' + bUpcoming + '</li>';
53578    	var completed = '<li><b>Completed Tickets</b> ' + bCheckout + ', ' + bNoShow + ', ' + bLateCancel + '</li>';
53579    	
53580    	var listLabel = '<div id="pos-help-staff-summary-label">Displays all staff\'s tickets for the current day</div>';
53581    	var list = listLabel + '<ul>' + current + scheduled + completed + '</ul>';
53582    	
53583    	return '<div id="help-pos-staff-preview">' + header + msg1 + msg2 + msg3 + list + imgDiv + '</div>';
53584    }
53585    function _getPosClientPanelHelp(arrow, screen, card, day, panel, bar) {
53586    	var header = '<h3>POS Ticket Panel</h3>';
53587    	var img = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/client-panel2.png" style="width: 90%; max-width: 980px; margin: auto; margin-bottom: 24px;"/>';
53588	    var imgDiv = '<div id="help-pos-client-panel-diagram">
53588' + img + '</div>';
53589    	
53590    	var bNoShow = '<b class="narrow-text pos-color-no-show">No Show</b>';
53591    	var bLateCancel = '<b class="narrow-text pos-color-late-cancel">Late Cancel</b>';
53592    	var bClientBar = '<b class="narrow-text" style="color: #4F81BD;">Ticket Status bar</b>';
53593    	
53594    	var msg1 = '<p>Displays all tickets for the current day <span>(except ' + bNoShow + ' + ' + bLateCancel + ' tickets)</span></p>';
53595		var msg2 = '<p>At the top of the ' + panel + ' can filter ' + card + ' displayed</p>';
53596		var msg3 = '<p>Press any ' + bClientBar + ' to open ticket</p>';
53597    	
53598    	return '<div id="help-pos-client-panel">' + header + msg1 + msg2 + msg3 + imgDiv + '</div>';
53599    }
53600    function _getTicketHelp(arrow, screen, card, day, panel, bar) {
53601    	var header = '<h3>POS Ticket</h3>';
53602    	var msg = '<p style="padding: 24px; padding-left: 12px;">To open ticket press' + arrow + 'ticket in ' + day + ', ' + bar + ' in ' + panel + ', scan QR on ticket, or search for ticket</p>';
53603    	
53604    	var img = '<img src="' + GLO.Data.cdnDirectory + 'image/faq/pos/pos-screen/pos-ticket2.png" style=""/>';
53605	    var imgDiv = '<div id="help-pos-ticket-diagram">' + img + '</div>';
53606    	
53607    	var hIn = '<h6>Check-In</h6>';
53608    	var hOut = '<h6>Check-Out</h6>';
53609    	var hClover = '<h6>Clover Credit Card Machine</h6>';
53610    	
53611    	var in1 = '<li>Can enable auto-printing ticket at check-in' + arrow + 'then scan ticket at front desk to checkout</li>';
53612    	var in2 = '<li>With just the push of a button can assign chair or table that ticket is assigned</li>';
53613    	var in3 = '<li>Can enable client self sign-in + self-checkout</li>';
53614    	
53615    	var out1 = '<li>Checkout ticket with just 2 clicks or 1 scan</li>';
53616    	var out2 = '<li>Simply scan ticket, product, or gift card to checkout ticket</li>';
53617    	var out3 = '<li>Have group parties?' + arrow + 'Easily link or split tickets</li>';
53618    	var out4 = '<li>Support for gift cards and loyalty points</li>';
53619    	var out5 = '<li>Setup discounts <span class="narrow-text>(like afternoon happy hours, birthdays, memberships, etc)</span> + add-on fees <span class="narrow-text>(credit card convenience fees, product fees, etc)</span></li>';
53620    	var out6 = '<li>After Checkout, Appointment survey texts automatically sent to client' + arrow + 'encouraging 5 star reviews from happy clients and for un-happy clients private feedback directly to the manager </li>';
53621    	var out7 = '<li>Automatic re-marketing' + arrow + 'encouraging customers to come back more often</li>';
53622    	
53623    	var clover1 = '<li>Automate your consent form' + arrow + 'Before client checks out, can display payment / refund policy that client must agree to before checking out</li>';
53624    	var clover2 = '<li>Tip prompt on Clover device' + arrow + 'can use original ticket price (before discounts) or total ticket price (after discounts)</li>';
53625    	
53626    	var listIn = hIn + '<ul>' + in1 + in2 + in3 + '</ul>';
53627    	var listOut = hOut + '<ul>' + out1 + out2 + out3 + out4 + out5 + out6 + out7 + '</ul>';
53628    	var listClover = hClover + '<ul>' + clover1 + clover2 + '</ul>';
53629    	
53630    	return '<div id="help-pos-ticket">' + header + msg + imgDiv + listIn + listOut + listClover + '</div>';
53631    }
53632    function _getColorHelp(arrow, screen, card, day, panel, bar) {
53633    	var header = '<h3>POS Screen Colors</h3>';
53634    	var msg1 = '<p style="text-align: center; font-style: italic;">The ' + screen + ' is color coded so you can quickly identify staff and ticket status</p>';
53635    	var msg2 = '';
53636    	
53637    	var liSignin = '<li><b class="ticket-status pos-color-signin">Sign-In</b> client signed-in</li>';
53638    	var bReady = '<b class="narrow-text pos-color-ready">READY to PAY</b>';
53639    	var liIn = '<li><b class="ticket-status pos-color-checkin">Checked-In</b> appointment, includes appointments marked as ' + bReady + '</li>';
53640    	var bAvailable = arrow + 'staff set as <b class="narrow-text pos-color-checkout">AVAILABLE</b> <i class="narrow-text">(if staff does not have appointment)</i>';
53641    	var liOut = '<li style="margin-bottom: 24px;"><b class="ticket-status pos-color-checkout">Checked-Out</b> appointment, when ticket checked-out ' + bAvailable + '</li>';
53642    	
53643    	var liNow = '<li><b class="ticket-status pos-color-now">NOW</b> appointment starts within 15 minutes of current time <i class="narrow-text">(and not yet checked-in or signed-in)</i></li>';
53644    	var liLate = '<li><b class="ticket-status pos-color-late">LATE</b> appointment 15 - 60 minutes late <i class="narrow-text">
53644(and not yet marked as no-show or late-cancel)</i></li>';
53645    	var liPast = '<li><b class="ticket-status pos-color-past">PAST</b> appointment more than 1 hour late <i class="narrow-text">(and not marked as no-show or late-cancel)</i></li>';
53646    	var liUpcoming = '<li style="margin-bottom: 24px;"><b class="ticket-status pos-color-upcoming">UPCOMING</b> appointment starts more than 15 minutes in the future</li>';
53647    	
53648    	var liNoShow = '<li><b class="ticket-status pos-color-no-show">No Show</b> appointment marked as a no show</li>';
53649    	var liLateCancel = '<li><b class="ticket-status pos-color-late-cancel">Late Cancel</b> appointment marked as a late cancelation</li>';
53650    	
53651    	var listColors = '<ul id="help-pos-color-list">' + liSignin + liIn + liOut + liNow + liLate + liPast + liUpcoming + liNoShow + liLateCancel + '</ul>';
53652    	return '<div id="help-pos-colors">' + header + msg1 + msg2 + listColors + '</div>';
53653    }
53654    
53655    function _staffPreviewHtm(staffId, staffName, isFA, thumb, htm) {
53656    	var ul = $(htm).find('ul');			//.click(SA.POS.openTicketFromStaffFromPreview);
53657    	var ticketCount = ul.length;
53658    	var helpIcon = '<b class="question-icon" onclick="SA.POS.openHelpQuickGuide(\'help-pos-staff-card\')" style="position: absolute; top: 4px; left: 0; border: 2px outset white; color: white;">?</b>';
53659    	var labelTicketCount = '<b class="narrow-text" style="color: rgb(240,240,180);">' + UTIL.pluralLabel(ticketCount, 'Ticket') + '</b>';
53660    	var btnPrint = '';
53661    	
53662    	if (_allowStaffPrintCommission()) {
53663    		btnPrint = '<a id="btnPrintStaffCommissionInner" onclick="SA.POS.printTodayCommissionByStaff(this, ' + staffId + ')">Close Day</a>';
53664    		btnPrint = '<span id="btnPrintStaffCommission" class="btnAdd" title="Print Today\'s Staff Commission">' + btnPrint + '</span>';
53665    	}
53666    	
53667    	var h1 = helpIcon + '<b class="staff-preview-name">' + staffName + '</b> ' + labelTicketCount;
53668    	
53669    	/*
53670    	var btnNewTicket = '<div id="staff-preview-new"><span id="btnNewTicket" class="btnAdd" onclick="SA.Ticket.newTicket(' + staffId + ', \'' + staffName + '\', ' + isFA + ')"><a>New Ticket</a></span></div>';
53671    	var htmExistingTicket = ' to create a new ticket'
53672    	
53673    	if (ticketCount > 0) {
53674    		htmExistingTicket = ' or <b class="narrow-text" style="color: rgb(0, 160, 220);">Existing Ticket</b> <span class="narrow-text">(below)</span>';
53675    	}
53676    	
53677    	var bNewTicket = '<b class="narrow-text" style="color: rgb(0, 160, 220);">New Ticket</b> button <span class="narrow-text">(above)</span>';
53678    	var msg = '<p id="staff-preview-instruction">Press ' + bNewTicket + htmExistingTicket + '</p>';
53679    	*/
53680    	
53681    	htm = '<div id="pop-staff-preview" staff_id="' + staffId + '">' + htm + '</div>';			// + btnNewTicket + msg
53682    	
53683    	var jpop = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-pos-staff-preview');
53684    	jpop.find('h1.friendly-responsive').css({ "margin-bottom": "0" });
53685    	
53686    	if (thumb && thumb.length && thumb.outerHTML && innerWidth > 760) {
53687    		jpop.find('#staff-preview-header').append(thumb.outerHTML());
53688    	}
53689    	
53690    	GLO.Popup.Custom.singleButton(jpop, 'Close');
53691    	
53692    	var iconClockIn = _getClockInIcon(staffId, isFA);
53693    	var jbtns = jpop.find('.pop-buttons');
53694    	jbtns.append(iconClockIn);
53695    	jbtns.prepend(btnPrint);
53696    	
53697    	_addResourceIcon(jpop);
53698    	SA.TicketCard.checkIfNeedReload(jpop, staffId, ticketCount);
53699    	//toDo: ?? click main screen to close ticket ??
53700    }
53701    
53702    _conPos.openTicketFromStaffFromPreview = function(element) {
53703    	var ul = $(element)
53704    	var cname = $('.staff-preview-client-name').text();
53705    	var bkg = ul.attr('booking_nr'), smid = ul.attr('smid');
53706    	
53707    	var msg = 'Opening Ticket P' + bkg;
53708    	
53709    	if (!UTIL.isEmpty(cname)) {
53710    		msg += ' for ' + cname;
53711    	}
53712    	
53713    	var jpop = GLO.Popup.Processing.open('<div id="pop-proceing-open-ticket">' + msg + '...</div>', 'Open Ticket');
53714    	
53715		setTimeout(function() {
53716			if (GLO.Popup.closeIfExist(jpop)) {
53717				UserPortal.getTicket(smid, bkg, null, false, true);
53718			}
53719		}, 50);
53720    }
53721    
53722    function _allowStaffPrintCommission() {
53723    	if (GLO.Info.roleType < 200) {
53724    		return false;
53725    	} else if (GLO.Data.Staff.role_report_cd == 99 || GLO.Data.Staff.role_report_cd == 199 || GLO.Data.Staff.role_report_cd == 500) {
53726    		return false;
53727    	} else if (GLO.Data.provider.report.reportCanViewPrice && GLO.Data.provider.report.reportCanViewCommission && GLO.Data.provider.report.reportCanViewTip) {
53728    		return true;
53729    	}
53730    	
53731    	return false;
53732    }
53733    
53734    function _addResourceIcon(jpop) {
53735    	var jtickets = jpop.find('#staff-preview-tickets > ul');
53736    	
53737    	for (var i=0; i < jtickets.length; i++) {
53738    		var resourceId = jtickets.eq(i).attr('resource_id');
53739    		
53740    		if (!UTIL.isEmpty(resourceId)) {
53741    			var rname = UserPortal.getResourceName(resourceId);
53742    			var icon = '<span class="staff-preview-resource-icon"><span><b>' + rname + '</b></span></span>';
53743    			
53744    			jtickets.eq(i).find('.staff-preview-date-range').append(icon);
53745    		}
53746    	}
53747    }
53748    
53749    function _getSelectStaffList(element, jsonSelectStaff) {
53750    	var htmStaff = '', jthis = $(element);
53751    	
53752    	if (jthis.hasClass('pos-service-label')) {
53753    		var serviceName = jthis.find('b').text();
53754    		var jline = jthis.closest('.pos-ticket-line-item');
53755    		var sgid = jline.attr('service_group_id'), svcid = jline.attr('service_id');
53756    		var staffIds = $('#allServiceOptions #crSvc' + sgid).find('option[value="' + svcid + '"]').attr('staff_ids').split(',');
53757    		var jstaff = UserPortal.getStaffDropDown().find('option');
53758    		
53759    		jsonSelectStaff.lineId = jline.attr('id');
53760    		jsonSelectStaff.header = UTIL.coalesce(serviceName, jsonSelectStaff.header);
53761    		jsonSelectStaff.attributes = ' line_id="' + jsonSelectStaff.lineId + '"';
53762    		
53763    		for (var i=0; i < jstaff.length; i++) {
53764				if (staffIds.has(jstaff.eq(i).attr('value'))) {
53765					htmStaff += jstaff.eq(i).outerHTML();
53766				}
53767			}
53768			
53769			return $(htmStaff);
53770    	} else if (jthis.hasClass('pos-staff-label')) {
53771    		var staffId = jthis.closest('.pos-staff-line-item').attr('staff_id');
53772    		var jlines = jthis.closest('.pos-ticket-line-item[staff_id="' + staffId + '"]');
53773    		var jstaff = $(UserPortal.getStaffDropDown().outerHTML()).find('option');			//= make copy, so can remove from copy
53774    		
53775    		jsonSelectStaff.header = '<b>Change Staff</b> <i class="narrow-text>(current staff: ' + jthis.text() + ')</i>';
53776    		jsonSelectStaff.replaceStaffId = staffId;
53777    		jsonSelectStaff.attributes = ' replace_staff_id="' + staffId + '"';
53778    		
53779    		for (var a=0; a < jlines.length; a++) {
53780    			var sgid = jlines.eq(a).attr('service_group_id'), svcid = jlines.eq(a).attr('service_id');
53781    			var svcid = jlines.attr('service_id');
53782    			var staffIds = $('#allServiceOptions #crSvc' + sgid).find('option[value="' + svcid + '"]').attr('staff_ids').split(',');
53783    			
53784    			for (var b=0; b < jstaff.length; b++) {
53785	    			if (!staffIds.has(jstaff.eq(b).attr('value'))) {
53786	    				jstaff.eq(i).remove();
53787	    			}
53788	    		}
53789    		}
53790    		
53791    		if (jstaff.length) {
53792	    		for (var i=0; i < jstaff.length; i++) {
53793					htmStaff += jstaff.eq(i).outerHTML();
53794				}
53795			} else {
53796				htmStaff = '<div><p>No staff member performs all these services</p><p>Please click each service to assign staff</p></div>';
53797			}
53798			
53799			return $(htmStaff);
53800    	} else {
53801    		return UserPortal.getStaffDropDown().find('option');
53802    	}
53803    }
53804    function _getSelectStaffId(element) {
53805    	var jline = $(element).closest('div');
53806    	
53807    	if (!jline.hasClass('pos-staff-line-item') && !jline.hasClass('pos-service-line-item')) {
53808    		jline = $('#pos-header-staff').find('#btnSelectedStaff > a');
53809    	}
53810    	
53811    	return jline.attr('staff_id');
53812    }
53813    _conPos.openSelectStaff = function(event, serviceId) {
53814    	GLO.Popup.closeIfExist($('#pop-warnng-staff-required').closest('.glopop'));
53815    	
53816    	if ($('#pop-pos-select-staff').closest('.glopop').length) {
53817    		return;
53818    	}
53819    	
53820    	var ul = '<ul id="pos-staff-list">';
53821    	var jsonSelectStaff = { "attributes": "", "header": "Select Staff" };
53822    	var jstaff = _getSelectStaffList(this, jsonSelectStaff);
53823    	var currSID = _getSelectStaffId(this);
53824    	
53825    	for (var i=0; i < jstaff.length; i++) {
53826    		var sname = jstaff.eq(i).text(), sid = jstaff.eq(i).attr('value');
53827    		var role = jstaff.eq(i).attr('role');
53828    		var css = '', faAttribute = '';
53829    		
53830    		if (UserPortal.staffPerformsClientService(sid)) {
53831	    		if (UTIL.parseBool(jstaff.eq(i).attr('is_first_available_fl'))) {
53832	    			faAttribute = ' is_first_available_fl="1"';
53833	    		}
53834	    		
53835	    		if (sname != 'Anyone' && UTIL.coalesceInt(role, 100) > 99) {
53836	    			if (currSID == sid) {
53837	    				css = ' class="selected"';
53838	    			}
53839	    			
53840	    			ul += '<li' + css + ' staff_id="' + sid + '"' + faAttribute + '>' + sname + '</li>';
53841	    		}
53842    		}
53843    	}
53844    	
53845    	ul += '</ul>';
53846    	
53847    	var htm = '<div id="pop-pos-select-staff"' + jsonSelectStaff.attributes + ' service_id="' + $.trim(serviceId) + '"><div>' + ul + '</div></div>';
53848    	var jpop = GLO.Popup.Custom.openSimple(htm, jsonSelectStaff.header);
53849    	
53850    	if (!UTIL.isEmpty(jsonSelectStaff.lineId)) {
53851    		jpop.prepend('<span id="btnRemoveService">
53851<a onclick="SA.POS.removeServiceLine(\'' + jsonSelectStaff.lineId + '\')">Remove Service</a></span>');
53852    	} else if (!UTIL.isEmpty(currSID) && UTIL.isEmpty(jsonSelectStaff.replaceStaffId)) {
53853    		jpop.prepend('<span id="btnRemoveService"><a onclick="SA.POS.clearStaff()">Clear Staff</a></span>');
53854    	}
53855    	
53856    	jpop.find('h1').css({ "position": "relative", "z-index": "100" });
53857    	jpop.find('li').click(SA.POS.selectStaff);
53858    	GLO.Popup.Custom.singleButton(jpop, 'Close');
53859    	
53860    	var btnHeight = (jpop.outerHeight() - 28) + "px";
53861    	jpop.find('#btnRemoveService > a').css({ "width": btnHeight });
53862    }
53863    _conPos.selectStaff = function() {
53864    	var li = $(this);
53865    	var staffId = li.attr('staff_id'), staffName = li.text(), isFA = UTIL.parseBool(li.attr('is_first_available_fl'));
53866    	var jpop = $('#pop-pos-select-staff');
53867    	var lineId = jpop.attr('line_id'), replaceStaffId = jpop.attr('replace_staff_id'), serviceId = jpop.attr('service_id');
53868    	
53869    	if (!UTIL.isEmpty(lineId)) {
53870    		var jtix = $('#pos-ticket');
53871    		var jline = jtix.find('#' + lineId + '.pos-ticket-line-item');
53872    		
53873    		_addStaffToLine(jtix, jline, staffId, staffName);
53874    		_changeDefaultStaff(staffId, staffName, isFA);
53875    		SA.Ticket.ticketChanged();
53876    	} else if (!UTIL.isEmpty(replaceStaffId)) {
53877    		var jtix = $('#pos-ticket');
53878    		var jlines = jtix.find('.pos-service-line-item[staff_id="' + replaceStaffId + '"]');
53879    		
53880    		var rowStaff = jtix.find('#staff-row-' + replaceStaffId);
53881    		var rowStaffNew = jtix.find('#staff-row-' + staffId);
53882    		
53883    		if (rowStaffNew.length == 0) {
53884    			rowStaff.attr('id', 'staff-row-' + staffId);
53885	    		rowStaff.attr('staff_id', staffId);
53886	    		rowStaff.find('.pos-staff-label').text(staffName);
53887    		}
53888    		
53889    		for (var i=0; i < jlines.length; i++) {
53890    			var jline = jlines.eq(i);
53891    			_addStaffToLine(jtix, jline, staffId, staffName);
53892    		}
53893    		
53894    		if (rowStaffNew.length) {
53895    			rowStaff.remove();
53896    		}
53897    		
53898    		_changeDefaultStaff(staffId, staffName, isFA);
53899    		SA.Ticket.ticketChanged();
53900    	} else {
53901	    	_conPos.selectDefaultStaff(staffId, staffName, isFA);
53902    	}
53903    	
53904    	SA.Ticket.setStaffHeader();
53905    	SA.Ticket.enableOrDisableTicketScroll();
53906    	SA.Ticket.addServiceLineAfterAddStaff(serviceId);
53907    	GLO.Popup.close(jpop.closest('.glopop'));
53908    }
53909    function _changeDefaultStaff(staffId, staffName, isFA) {
53910    	var currentDefaultStaffId = $('#pos-header-staff-button #btnSelectedStaff > a').attr('staff_id');
53911    	var jsvc = $('#pos-ticket').find('.pos-service-line-item[staff_id = ' + currentDefaultStaffId + ']');
53912    	
53913    	if (jsvc.length === 0) {
53914    		_conPos.selectDefaultStaff(staffId, staffName, isFA);
53915    	}
53916    }
53917    _conPos.selectDefaultStaff = function(staffId, staffName, isFA) {
53918    	var sgid = $('#pos-product-header-breadcrumb #pos-breadcrumb-sg').attr('service_group_id');
53919    	
53920    	_conPos.setStaff(staffId, staffName, isFA, sgid);
53921    	_addStaffToServiceMissingStaff(staffId);
53922    }
53923    _conPos.setStaff = function(staffId, staffName, isFA, sgid) {
53924    	if (innerWidth < 900) {
53925    		staffName = UTIL.maxString(staffName, 12, true);
53926    	}
53927    	
53928    	$('#pos-header-staff').addClass('selected').find('#btnSelectedStaff > a').attr('staff_id', staffId).attr('is_first_available_fl', isFA).text(staffName);
53929    	_conPos.filterServiceBoxesByStaff(staffId, sgid);
53930    }
53931    
53932    function _resetServiceLineDates(jline) {
53933    	var serviceId = jline.attr('service_id');
53934    	var staffId = jline.attr('staff_id');
53935		
53936		jline.removeAttr('appt_dt');
53937		jline.removeAttr('time_vc');
53938		jline.removeAttr('end_dt');
53939		
53940    	var ojDefault = UserPortal.Booking.lookupDefault(serviceId, staffId, null, true);
53941        jline.attr('service_length_nr', ojDefault.minutes_nr);
53942        jline.attr('prep_nr', ojDefault.prep_nr, 0);
53943        jline.attr('prep_fl', ojDefault.prep_fl);
53944        
53945        jline.attr('processing_nr', ojDefault.processing_nr, 0);
53946        jline.attr('processing_fl', ojDefault.processing_fl);
53947        jline.attr('finish_out_nr', ojDefault.finish_out_nr, 0);
53948        jline.attr('finish_out_fl', ojDefault.finish_out_fl);
53949    }
53950    function _addStaffToLine(jtix, jline, sid, sname) {
53951    	//var jlabel = jline.find('.line-item-name');
53952		//jlabel.find('i').remove();
53953		//jlabel.prepend('<i>' + UTIL.maxString(sname, 10, true) + '</i>');
53954		
53955		var rowStaff = SA.Ticket.getStaffTicketLastRow(jtix, sid, jline);
53956		var replaceStaffId = jline.attr('staff_id');
53957		var isClientRequest = 0;
53958		
53959		if (UserPortal.isFirstAvailable(sid)) {
53960			jline.attr('is_first_available_fl', 1);
53961		} else {
53962			jline.removeAttr('is_first_available_fl');
53963			isClientRequest = SA.Ticket.getIsClientRequest(sid);
53964		}
53965		
53966		jline.attr('staff_id', sid);
53967		rowStaff.after(jline);
53968		_resetServiceLineDates(jline);
53969		
53970		//if previous staff only had 1 service -> remove staff row
53971			var serviceCountForStaff = jtix.find('.pos-service-line-item[staff_id="' + replaceStaffId + '"]').length;
53972			
53973			if (serviceCountForStaff === 0) {
53974				jtix.find('.pos-staff-line-item[staff_id="' + replaceStaffId + '"]').remove();
53975			}
53976    }
53977    function _addStaffToServiceMissingStaff(staffId, isIncludeFirstAvailable) {
53978    	var jtix = $('#pos-ticket');
53979    	var jlines = jtix.find('.pos-service-line-item');
53980    	var staffChangecount = 0;
53981    	var sname = UserPortal.getStaffName(staffId);
53982    	
53983    	for (var i=0; i < jlines.length; i++) {
53984    		var jline = jlines.eq(i);
53985    		var isFA = UTIL.parseBool(jline.attr('is_first_available_fl'));
53986    		
53987    		if (UTIL.isEmpty(jline.attr('staff_id')) || (isFA && isIncludeFirstAvailable)) {
53988	    		var serviceId = jline.attr('service_id');
53989	    		
53990	    		if (UserPortal.staffPerformsService(serviceId, staffId)) {
53991	    			_addStaffToLine(jtix, jline, staffId, sname);
53992	    			++staffChangecount;
53993	    		}
53994    		}
53995    	}
53996    	
53997    	if (staffChangecount > 0) {
53998    		SA.Ticket.ticketChanged();
53999    	}
54000    }
54001    _conPos.clearStaff = function() {
54002    	GLO.Popup.close($('#pop-pos-select-staff').closest('.glopop'));
54003    	$('#pos-header-staff').removeClass('selected').find('#btnSelectedStaff > a').removeAttr('staff_id').removeAttr('is_first_available_fl').text('');
54004    	SA.Ticket.enableOrDisableTicketScroll();
54005    	
54006    	var sgid = $('#pos-product-header-breadcrumb').attr('service_group_id');
54007    	
54008    	if (!UTIL.isEmpty(sgid)) {
54009    		_conPos.filterBoxesServiceGroup(sgid);
54010    	} else {
54011    		_conPos.filterBoxesHome();
54012    	}
54013    }
54014    _conPos.removeServiceLine = function(lineId) {
54015    	GLO.Popup.close($('#pop-pos-select-staff').closest('.glopop'));
54016    	$('#pos-ticket').find('#pos-ticket-order #' + lineId).find('.ticket-row-remove').click();
54017    }
54018    
54019    _conPos.getServiceGroupObject = function(sgid) {
54020    	var sg = SA.POS.inventory_json.service_groups;
54021    	sgid = parseInt(sgid);
54022    	
54023    	for (var i=0; i < sg.length; i++) {
54024    		if (sgid == sg[i].id) {
54025    			return sg[i];
54026    		}
54027    	}
54028    	
54029    	return null;
54030    }
54031    _conPos.getServiceObject = function(serviceId) {
54032    	var svc = SA.POS.inventory_json.services;
54033    	serviceId = parseInt(serviceId);
54034    	
54035    	for (var i=0; i < svc.length; i++) {
54036    		if (serviceId === svc[i].id) {
54037    			return svc[i];
54038    		}
54039    	}
54040    	
54041    	return null;
54042    }
54043    _conPos.getVendorObject = function(vendorId) {
54044    	var vendors = SA.POS.inventory_json.vendors;
54045    	vendorId = parseInt(vendorId);
54046    	
54047    	for (var i=0; i < vendors.length; i++) {
54048    		if (vendorId == vendors[i].id) {
54049    			return vendors[i];
54050    		}
54051    	}
54052    	
54053    	return null;
54054    }
54055    _conPos.getPLineObject = function(plineId) {
54056    	var plines = SA.POS.inventory_json.product_lines;
54057    	plineId = parseInt(plineId);
54058    	
54059    	for (var i=0; i < plines.length; i++) {
54060    		if (plineId == plines[i].id) {
54061    			return plines[i];
54062    		}
54063    	}
54064    	
54065    	return null;
54066    }
54067    _conPos.getProductObject = function(inventoryId) {
54068    	var products = SA.POS.inventory_json.products;
54069    	inventoryId = parseInt(inventoryId);
54070    	
54071    	for (var i=0; i < products.length; i++) {
54072    		if (inventoryId === products[i].id) {
54073    			return products[i];
54074    		}
54075    	}
54076    	
54077    	return null;
54078    }
54079    _conPos.getObject = function(jsonArray, jsonIdKey, id) {
54080    	id = parseInt(id);
54081    	
54082    	for (var i=0; i < jsonArray.length; i++) {
54083    		if (id === jsonArray[i][jsonIdKey]) {
54084    			return jsonArray[i];
54085    		}
54086    	}
54087    	
54088    	return null;
54089    }
54090    
54091    _conPos.printTodaySales = function(event, element) {
54092		GLO.Report.Sales.printByStaffFromPOS();
54093    }
54094    function _displayNoSalesTodayWarning() {
54095    	var aPayrollByDay = 'Daily Payroll Report';
54096    	
54097    	if (GLO.Info.roleType > 219) {
54098    		aPayrollByDay = '<a onclick="SA.Menu.gotoReport(event, this, \'reports/sales\')">' + aPayrollByDay + '</a>';
54099    	}
54100    	
54101    	var msg1 = '<p>No Sales Found Today</p>';
54102    	var msg2 = '<p>To print a previous days sales commission go to the ' + aPayrollByDay + '</p>';
54103    	var htm = '<div id="pop-warn-pos-no-sales">' + msg1 + msg2 + '</div>';
54104    	
54105    	GLO.Popup.Info.open(htm, 'No Sales Found Today');
54106    }
54107    _conPos.printTodayCommissionToPrinter = function(element) {								//step 4: print from popup
54108    	var jpop = $('#report-payroll-days-all-data');
54109    	var jtbl = jpop.find('#report-payroll-days');
54110    	var htm = jpop.outerHTML();
54111    	
54112    	var css = '', msg = null, fnAfterPrint = null;
54113    	var commissionTotal = UTIL.coalesceMoney(UTIL.coalesceString(jtbl.find('tfoot .payroll-column-commission').text(), jtbl.find('tbody .payroll-column-commission').text()).replace('$', ''));
54114    	var dtLastProcessed = jpop.find('#payroll-last-processed-date').text();
54115    	
54116    	if (!UTIL.isDate(dtLastProcessed)) {
54117    		msg = 'Need to process payroll to view commission amount';
54118    	} else if (UTIL.isToday(new Date(dtLastProcessed).addMinutes(-360))) {
54119    		msg = 'Need to process payroll to view commission amount';
54120    	} else if (commissionTotal === 0) {
54121    		msg = 'Commission empty, may need to checkout tickets then process payroll to view commission amount';
54122    	}
54123    	
54124    	if (msg) {
54125    		fnAfterPrint = function() {
54126    			var jpop = GLO.Report.Payroll.openProcessingPayrollPopup(true, msg, true).getPopup();
54127    		};
54128    	}
54129    	
54130    	GLO.Popup.close(jpop.closest('.glopop'));
54131    	UI.Print.print(htm, css, false, fnAfterPrint);
54132    }
54133	_conPos.printTodayCommissionDisplay = function(url) {										//step 3: display report in popup
54134    	var sfilter = GLO.Uri.getQueryStringValueFromUrl('sfilter', url);
54135    	var staffId = null;
54136    	
54137    	if (sfilter && sfilter.indexOf && sfilter.indexOf(',') === -1 && UTIL.isNumber(sfilter)) {
54138    		staffId = sfilter;
54139    	}
54140    	
54141    	var jpop = GLO.Report.Payroll.initByDayPopup(staffId);
54142    	
54143    	if (UTIL.parseBool(GLO.Uri.getQueryStringValueFromUrl('isAutoPrint', url))) {
54144    		jpop.find('#btnPrintStaffCommission > a').click();
54145    	}
54146    }
54147    _conPos.printTodayCommissionByStaffNow = function(element, staffId) {					//step 2.5:  + lookup staff + PIN
54148    	var today = new Date().toGloDate();
54149    	var url = 'report/payrollDays?sfilter=' + staffId + '&start=' + today + '&end=' + today; 		//+ '&period=current';
54150    }
54151    _conPos.printTodayCommissionByStaff = function(element, staffId, isAutoPrint) {						//step 2: enter PIN + verify PIN on server, then lookup report data
54152    	var today = new Date().toGloDate();
54153    	var url = 'report/payrollDays?sfilter=' + staffId + '&start=' + today + '&end=' + today; 		//+ '&period=current';
54154    	var sname = UserPortal.getStaffName(staffId);
54155    	var msg = 'Lookup Commission Today for ' + sname;
54156    	var header = UserPortal.getStaffName(staffId) + ' Payroll Today';
54157    	
54158    	if (isAutoPrint) {
54159			url += '&isAutoPrint=1';
54160		} else {
54161			msg = GLO.Report.Payroll.openProcessingPayrollPopup(false, msg);
54162		}
54163		
54164    	GLO.Popup.closeIfExist($('#pop-print-commission-select-staff').closest('.glopop'));
54165    	GLO.Popup.closeIfExist($('.pop-pos-staff-preview.glopop'));
54166    	GLO.Popup.closeIfExist($('.pop-pos.glopop'));
54167    	GLO.Popup.closeIfExist($('#pop-processing-payroll').closest('.glopop'));
54168    	
54169    	//SA.Menu.openRequirePIN(url, false, element, true, msg);
54170    	if (SA.Menu.isRequirePIN(url, element, event, true, header)) {
54171    		return false;
54172    	} else {
54173    		var popupId = 'report-payroll-days-full-page', fnOnload = SA.POS.printTodayCommissionDisplay;
54174    		SA.Menu.openPopupReport(element, url, header, popupId, msg, fnOnload);			//_openPopupReport(null, element, url, h1, popupId, msg, fnOnload);
54175    	}
54176    }
54177    
54178    _conPos.printTodayCommissionPopup = function() {
54179    	var jpop = $('#pop-print-commission-select-staff');
54180    	jpop.find('#print-staff-summary-info').remove();
54181    	jpop.find('.pop-header').remove();
54182    	
54183    	var htm = jpop.outerHTML();
54184    	var fnAfterPrint = null, css = null;
54185    	
54186    	GLO.Popup.close(jpop);
54187    	GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop'));
54188    	UI.Print.print(htm, css, false, fnAfterPrint);
54189    }
54190    _conPos.printTodayCommission = function(element) {										//step 1: select staff
54191    	var staffSummary = SA.TicketCard.getStaffSummary();
54192    	var arr = [];
54193    	
54194    	var jrpt = $('#pos-staff-list');
54195		var tdStaff = jrpt.find('li.pos-staff-cell[staff_id]');
54196    	
54197    	if (tdStaff.length === 0) {
54198			_displayNoSalesTodayWarning();
54199			return;
54200		}
54201		
54202		for (var i=0; i < staffSummary.length; i++) {
54203			if (staffSummary[i].service_sr > 0) {
54204				arr.push(staffSummary[i]);
54205			}
54206		}
54207		
54208		arr = UTIL.sortArray(arr, "price_mn");			//later add support for "turn_sr" (and turns column in table below)
54209		
54210		if (arr.length === 1) {
54211			_conRptSales.printByStaff2(arr[0].id);
54212		} else {
54213			var h1 = 'Print Staff Commission Today';
54214			//var h1Staff = '<h3 class="friendly-responsive" style="margin-top: 0;"><div>Select Staff</div></h3>';
54215			var btnPrintAll = '<span class="btnAdd">
54215<a onclick="SA.POS.printTodayCommissionPopup()">Print Summary</a></span>';
54216			var msg2Style = ' style="padding: 0 8px; line-height: 1.2; text-align: center"';
54217			var msg = '<p id="print-staff-summary-info" style="padding: 12px; text-align: center;">Select staff below or ' + btnPrintAll + '</p>';
54218			var msg2 = '<p' + msg2Style + '>Tickets that are <b class="narrow-text">checked-in</b>, <b class="narrow-text">checked-out</b>, or <b class="narrow-text">ready-to-pay</b></p>';
54219			
54220			var infoTicket = 'Tickets that have the status: Checked-Out, Ready To Pay, or Checked-In';
54221			var infoPrice = 'Service Price before discount and add-on fees';
54222			
54223			var thPrice = '<th class="column-print-price" title="' + infoPrice + '">Price</th>';
54224			var thTicket = '<th class="column-print-ticket" title="' + infoTicket + '" style="padding-left: 2px; padding-right: 4px;">Tickets</th>';
54225			var thService = '<th style="padding-left: 2px; padding-right: 4px;">Services</th>';
54226			var thead = '<thead> <tr> <th class="column-print-staff">Staff</th>' + thPrice + thTicket + thService + '</thead>';
54227			var htmTable = '<table class="pop-select-staff tablesorter" style="width: 100%;">' + thead + '<tbody>';
54228			
54229			for (var a=0; a < arr.length; a++) {
54230				var trClass = '', name = UTIL.coalesceString(arr[a].title, arr[a].name);
54231				var btnStaff = '<span class="btn btnSA"><a class="pop-select-staff-name" onclick="SA.POS.printTodayCommissionByStaff(this, ' + arr[a].id + ')">' + name + '</a></span>';
54232				var tdStaff = '<td class="column-print-staff" order_by="' + name + '">' + btnStaff + '</td>';
54233				
54234				var titleTicket = UTIL.pluralLabel(arr[a].ticket_sr, 'ticket') + ' with ' + UTIL.pluralLabel(arr[a].service_sr, 'service') + ' || ' + infoTicket;
54235				var tdTicket = '<td class="column-print-ticket" title="' + titleTicket + '">' + arr[a].ticket_sr + '</td>';
54236				var tdService = '<td class="column-print-service" title="' + titleTicket + '">' + arr[a].service_sr + '</td>';
54237				
54238				var price = UTIL.displayMoney(arr[a].price_mn, false, false, true);
54239				var titlePrice = price + ' || ' + infoPrice;
54240				var tdPrice = '<td class="column-print-price" title="' + titlePrice + '">' + price + '</td>';
54241				
54242				htmTable += '<tr class="' + trClass + '">' + tdStaff + tdPrice + tdTicket + tdService + '</tr>';
54243			}
54244			
54245			htmTable += '</tbody></table>';
54246			var htm = '<div id="pop-print-commission-select-staff">' + msg2 + msg + htmTable + '</div>';
54247			var jpop = GLO.Popup.Custom.openSimple(htm, h1);
54248			var jtbl = jpop.find('table.tablesorter');
54249			
54250			GLO.Popup.Custom.singleButton(jpop, 'Close');
54251			UI.initTableSorter(jtbl);
54252			GLO.Report.CellSummary.initReport(jtbl, false, true);
54253			jpop.find('.msg.scrollable-for-mac').css({ "overflow-x": "hidden" });
54254		}
54255    }
54256    _conPos.printTodayCommission_OLD = function(element) {										//step 1: select staff
54257    	var jrpt = $('#pos-staff-list');
54258		var tdStaff = jrpt.find('li.pos-staff-cell[staff_id]');
54259    	
54260		if (tdStaff.length === 0) {
54261			_displayNoSalesTodayWarning();
54262			return;
54263		}
54264		
54265		var arr = [];
54266		var sid = tdStaff.eq(0).attr('staff_id');
54267		
54268		for (var i=0; i < tdStaff.length; i++) {
54269			var sid = tdStaff.eq(i).attr('staff_id');
54270			var staffName = tdStaff.eq(i).find('.pos-staff-name').text();
54271			var ticketCheckedOutCount = UTIL.coalesceInt(tdStaff.eq(i).find('.staff-appt-checkout-count').text(), 0);
54272
54273			if (!UTIL.isEmpty(sid) && UTIL.isInObjectArray(arr, 'id', sid) === -1) {
54274				if (ticketCheckedOutCount > 0) {
54275					var sortName = '00-' + staffName;
54276				} else {
54277					var sortName = 'zz-' + staffName;
54278				}
54279				
54280				if (ticketCheckedOutCount > 0 || !UTIL.parseBool(tdStaff.eq(i).attr('is_first_available_fl'))) {
54281					arr.push({ "id": sid, "name": staffName, "ticket_out_sr": ticketCheckedOutCount, "sortname": sortName });
54282				}
54283			}
54284		}
54285		
54286		arr = UTIL.sortArray(arr, "sortname");
54287		
54288		if (arr.length === 1) {
54289			_conRptSales.printByStaff2(arr[0].id);
54290		} else {
54291			var h1 = 'Print Staff Commission Today', ul = '<ul class="pop-select-staff">';
54292			var h1Staff = '<h3 class="friendly-responsive" style="margin-top: 0;"><div>Select Staff</div></h3>';
54293			var msg = '<p style="padding: 8px 0;">Tickets that are checked-in, checked-out, or ready-to-pay</p>';
54294			
54295			for (var a=0; a < arr.length; a++) {
54296				var liClass = '', labelTicket = '';
54297				var labelStaff = '<span class="btn btnSA"><a class="pop-select-staff-name" onclick="SA.POS.printTodayCommissionByStaff(this, ' + arr[a].id + ')">' + arr[a].name + '</a></span>';
54298				
54299				if (arr[a].ticket_out_sr > 0) {
54300					labelTicket = UTIL.pluralLabel(arr[a].ticket_out_sr, 'ticket');
54301					labelTicket = '<span class="staff-appt-count staff-appt-checkout"><b class="staff-appt-checkout-count" title="' + labelTicket + ' Checked Out">' + arr[a].ticket_out_sr + '</b></span>';
54302					liClass = 'has-ticket-checked-out';
54303				} else {
54304					liClass = 'no-ticket-checked-out';
54305				}
54306				
54307				ul += '<li class="' + liClass + '">' + labelStaff + labelTicket + '</li>';
54308			}
54309			
54310			ul += '</ul>';
54311			var htm = '<div id="pop-print-commission-select-staff">' + h1Staff + msg + ul + '</div>';
54312			var jpop = GLO.Popup.Custom.openSimple(htm, h1);
54313			GLO.Popup.Custom.singleButton(jpop, 'Close');
54314		}
54315    }
54316    
54317    _conPos.openReportMenu = function() {
54318    	GLO.Popup.closeIfExist($('.pop-pos.glopop'));
54319    	
54320    	var htmIn = '<span class="most-popular-reports"> <a class="ignore-animate" onclick="SA.Menu.openReportCheckedIn(null, this)">Checked-In</a> </span>';
54321    	var htmOut = '<span class="most-popular-reports"> <a class="ignore-animate" onclick="SA.Menu.openReportCheckedOut(null, this)">Checked-Out</a> </span>';
54322    	var htmUpcoming = '<span class="most-popular-reports"> <a class="ignore-animate" onclick="SA.Menu.openReportUpcomingAppointments(null, this)">Upcoming Today</a> </span>';
54323    	var htmQuickLeft = '<div id="hd-reports-menu-quick-left">' + htmIn + htmOut + htmUpcoming + '</div>';
54324    	
54325    	var jpop = new GLO.Popup.Custom( $('#hd-reports-menu') ).getPopup().addClass('pop-header-drop-menu');
54326		var jtop = jpop.find('#hd-reports-menu-top');
54327		
54328		jtop.find('h5').replaceWith(htmQuickLeft);
54329		jtop.find('#hd-reports-menu-quick').css({ "width": "280px", "margin": "auto", "margin-bottom": "16px", "padding-left": "8px" });			//"float": "none", 
54330		
54331		var htmBrand = '<span class="sa-brand"><i>Schedule</i><b>Anyone</b></span>';
54332		var css = 'padding-top: 10px; padding-bottom: 8px; letter-spacing: 2px; font-size: 18px; background-color: white;';
54333		var h1 = '<h1 style="' + css + '">' + htmBrand + ' <span>Reports</span> </h1>';
54334		
54335		jpop.find('.pop-header').html(h1);
54336		GLO.Popup.Custom.singleButton(jpop, 'Close');
54337		
54338		var btnManagerReports = '<span class="manager-reports-link"><a onclick="SA.POS.openManagerReport()">Manager Reports</a></span>';
54339    	var btnPosHelp = '<span class="btnAdd btnPosHelp"><a onclick="SA.POS.openHelp(true)">Help</a></span>';
54340    	
54341    	jpop.find('.pop-header').css({ "position": "relative" }).append(btnManagerReports);
54342    	jpop.find('.pop-buttons-parent').append(btnPosHelp);
54343    	
54344		/* 
54345		var jbtns = jpop.find('.pop-buttons');
54346    	jbtns.find('.btnSave').remove();
54347    	jbtns.find('.btnCancel').addClass('btnOk').removeClass('btnCancel').find('a').css({ "letter-spacing": "1px" }).text(SA.Resource.Close);
54348    	*/
54349    }
54350    
54351    _conPos.openManagerReport = function() {
54352    	GLO.Popup.closeIfExist($('.pop-pos.glopop'));
54353    	GLO.Popup.closeIfExist($('.pop-header-drop-menu.glopop'));
54354    	
54355    	var htmSummary = SA.TicketCard.getCardSummary();
54356    	
54357    	var btnPrintSales = '<span id="btnPrintSales" class="btnAdd"><a onclick="SA.POS.printTodaySales(event, this)">Print Detail</a></span>';
54358    	var sales1 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/sales\')">Sales Summary</a></label> <i>Dashboard of Today\'s Sales</i></div>';
54359    	var sales2 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/saleshistory?isfullpage=1\')">Sales Detail</a></label> <i>per Service</i>' + btnPrintSales + '</div>';
54360    	var sales3 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/TicketHistory\')">Ticket History</a></label> <i>per Ticket</i></div>';
54361    	var htmSales = '<div class="pop-report-box"><h3>Sales Reports</h3>' + sales1 + sales2 + sales3 + '</div>';
54362    	
54363    	var pay1 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'payment/ReportBatch\')">Today\'s Batch</a></label> <i>Credit/Debit Payments</i></div>';
54364    	var pay2 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/saleshistory?isfullpage=1&paymethod=0\')">Payment Detail</a></label> <i>Today\'s Payments</i></div>';
54365    	var pay3 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'reports/cash\')">Ticket History</a></label> <i>Today\'s Cash Payments</i></div>';
54366    	var htmPayment = '<div class="pop-report-box"><h3>Payment Reports</h3>' + pay1 + pay2 + pay3 + '</div>';
54367    	
54368    	var aPayroll = '<a onclick="SA.Menu.gotoReport(event, this, \'reports/payroll\')">Payroll</a>';
54369    	var other4 = '', other5 = '', other6 = '';
54370    	
54371    	if (_allowStaffPrintCommission()) {
54372    		var btnPrintPayroll = '<span id="btnPrintPayroll" class="btnAdd" title="Print Today\'s Staff Commission">
54372<a onclick="SA.POS.printTodayCommission(this)">Print Summary</a></span>';
54373    	} else {
54374    		var btnPrintPayroll = '';
54375    	}
54376    	
54377    	if (innerHeight > 900) {
54378    		var aReminderView = '<a onclick="SA.Menu.gotoReport(event, this, \'provider/reminders\')">Reminder View</a>';
54379    		var aActivityView = '<a onclick="SA.Menu.gotoReport(event, this, \'provider/apptportal\')">Activity View</a>';
54380    		
54381    		other4 = '<div class="pop-pos-line pop-pos-appt-rpt"><label>' + aReminderView + '</label> <i>Reminders sent & scheduled to be sent</i></div>';
54382    		other5 = '<div class="pop-pos-line pop-pos-appt-rpt"><label>' + aActivityView + '</label> <i>Ticket update history</i></div>';
54383    		
54384    		if (SA.Data.resourceJson.length) {
54385    			var lblCal = '', aCal = '<a onclick="SA.Menu.gotoReport(event, this, \'provider/ResourceView\')">Resource Calendar</a>';
54386    			
54387    			for (var i=0; i < SA.Data.resourceJson.length; i++) {
54388    				if (i > 0) { lblCal += ', '; }
54389    				
54390    				lblCal += SA.Data.resourceJson[i].name;
54391    			}
54392    			
54393    			other6 = '<div id="pop-pos-line-resource-cal" class="pop-pos-line pop-pos-appt-rpt"><label>' + aCal + '</label> <i>' + lblCal + '</i></div>';
54394    		}
54395    	}
54396    	
54397    	var other1 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'message/ClientList\')">Client List</a></label> <i>View Clients + Send Marketing Messages</i></div>';
54398    	var other2 = '<div id="pop-mr-payroll" class="pop-pos-line"><label>' + aPayroll + '</label> <i>Automatically Calculated</i>' + btnPrintPayroll + '</div>';
54399    	var other3 = '<div class="pop-pos-line"><label><a onclick="SA.Menu.gotoReport(event, this, \'report/StaffGoal?isActiveStaffOnly=1\')">Goals</a></label> <i>Track Sales with Charts</i></div>';
54400    	var htmOther = '<div class="pop-report-box"><h3>Other Reports</h3>' + other1 + other2 + other3 + other4 + other5 + other6 + '</div>';
54401    	
54402    	var btnAllReports = '<span class="all-reports-link"><a onclick="SA.POS.openReportMenu()">All Reports</a></span>';
54403    	var btnPosHelp = '<span class="btnAdd btnPosHelp"><a onclick="SA.POS.openHelp(true)">Help</a></span>';
54404    	
54405    	var htm = '<div id="pop-manager-report">' + htmSummary + htmSales + htmPayment + htmOther + '</div>';
54406    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Manager Reports').addClass('pop-pos').attr('title', 'Owner / Manager Reports');
54407    	
54408    	jpop.find('.pop-header').css({ "position": "relative" }).append(btnAllReports);
54409    	jpop.find('.pop-buttons-parent').append(btnPosHelp);
54410    	
54411    	GLO.Popup.Custom.singleButton(jpop, 'Close');
54412    }
54413    _conPos.openTurnTracker = function() {
54414    	var uriSignin = GLO.Data.provider.urikey + '/Signin';
54415    	var btnEditSignin = '<span class="btnAdd btnGoToSignin btnGoToSigninEdit"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uriSignin + '\', this, event, true)">Edit Sign-In</a></span>';
54416    	var aSignin = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + uriSignin + '\', this, event, true)"><b>Sign-In Screen</b></a></i>';
54417    	var aSignin2 = '<i class="pop-pos-text2">' + btnEditSignin + '</i>';
54418    	var htmSignin = '<div class="pop-pos-line" id="pop-pos-signin"><label>Client Sign-In</label>' + aSignin + aSignin2 + '</div>';
54419    	
54420    	var htmTurnTracking = '<p style="text-align: center;">Advanced Turn Tracking Coming Soon in October 2026...</p>';
54421    	var btnPosHelp = '<span class="btnAdd btnPosHelp"><a onclick="SA.POS.openHelp(true)">Help</a></span>';
54422    	
54423    	var htm = '<div id="pop-turn-tracker" style="padding: 12px;">' + htmSignin + htmTurnTracking + '</div>';
54424    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Turn Tracking').addClass('pop-pos');
54425    	
54426    	jpop.find('.pop-buttons-parent').append(btnPosHelp);
54427    	GLO.Popup.Custom.singleButton(jpop, 'Close');
54428    }
54429    _conPos.openProfile = function() {
54430		var msg = '';
54431		var aBizProfile = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/2\', this, event, true)" style="border-bottom: none;">Business Profile</a>';
54432		var hBiz = '<h3>Manage Your ' + aBizProfile + '</h3>';
54433		
54434		var aSvc = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/4\', this, event, true)">Add + Edit</a></i>';
54435		var aSvc2 = '<i class="pop-pos-text2"><span class="btnAdd">
54435<a onclick="SA.POS.Edit.changeMode()" style="font-style: normal;">Edit P.O.S. Screen</a></span></i>';
54436		var htmBizSvc = '<div id="pop-pos-profile-service" class="pop-pos-line"><label>Services</label>' + aSvc + aSvc2 + '</div>';
54437		
54438		var aSigninLink = GLO.Data.provider.urikey + '/Signin';
54439		var aSigninCustomize = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + aSigninLink + '?open=help-overview&mode=edit&back=pos\', this, event, true)">Customize</a></i>';
54440		var aSigninView = '<i class="pop-pos-text2"><a class="pop-pos-profile-narrow-text" onclick="UI.openChildWindow(\'' + aSigninLink + '\', null, true)">View Sign-In Screen</a></i>';		//GLO.Uri.gotoUriWithSpinner(\'' + aSigninLink + '\', this, event, true)
54441		var htmSignin = '<div id="pop-pos-profile-signin" class="pop-pos-line"><label>Client Sign-In</label>' + aSigninCustomize + aSigninView + '</div>';
54442		
54443		var aWebManage = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'wizard/website\', this, event, true)">Manage</a></i>';
54444		var aWebView = '<i class="pop-pos-text2"><a onclick="SA.App.openLinkInBrowser(\'' + GLO.Data.provider.websiteuri + '?helloback=website\', true)">View Website</a></i>';
54445		var htmWeb = '<div id="pop-pos-profile-web" class="pop-pos-line"><label>Website</label>' + aWebManage + aWebView + '</div>';
54446		
54447		var aDiscount = '<i><a onclick="SA.Menu.gotoReport(event, this, \'provider/manage/discount\')">Discounts</a></i>';
54448		var aAddOn = '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoReport(event, this, \'provider/manage/addon\')">Add-On Fees</a></i>';
54449		var htmDiscount = '<div id="pop-pos-profile-discount" class="pop-pos-line"><label>Setup</label>' + aDiscount + aAddOn + '</div>';
54450		
54451		var aMsgOverview = '<i style="width: inherit;"><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/message?helloback=pos\', this, event, true)">Message Plan + Overview</a></i>';
54452		var htmMsg = '<div class="pop-pos-line" id="pop-pos-profile-message"><label>Email/Text</label>' + aMsgOverview + '</div>';
54453		
54454		var aAdvanced = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced\', this, event, true)">Advanced Setup</a></i>';
54455		
54456		//var aInventory = ''; '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoInventory(event, this, \'inventory\')">Product List</a></i>';
54457		var aSecurity = ''; '<i class="pop-pos-text2"><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/SetupSecurity/CompanyComputer\', this, event, true)">Security</a></i>';
54458		var htmAdvanced = '<div class="pop-pos-line" id="pop-pos-profile-advanced"><label>More Options</label>' + aAdvanced + aSecurity + '</div>';
54459		
54460		var htmBiz = '<div id="pop-pos-profile-preview-biz">' + hBiz + htmBizSvc + htmSignin + htmWeb + htmDiscount + htmMsg + htmAdvanced + '</div>';
54461		var hStaff = '<h3>Manage Staff Profiles</h3>';
54462		
54463		var titleStaff = 'Add + Edit Profile, Alerts, Role (permission), Normal Hours, Online Booking Profile';
54464		var aStaff = '<i><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?\', this, event, true)" title="' + titleStaff + '">Add + Edit</a></i>';
54465		var aProfileReport = '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoReport2(event, this, \'reports/StaffProfile\')">Profile Report</a></i>';
54466		var htmStaff1 = '<div id="pop-pos-profile-staff-service" class="pop-pos-line"><label>Staff</label>' + aStaff + aProfileReport + '</div>';
54467		
54468		var aStaffSvc = '<i><a class="pop-pos-profile-narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5?highlight=wiz5-column-staff-service\', this, event, true)">Services for each Staff</a></i>';
54469		var aCommission = '<i class="pop-pos-text2"><a onclick="SA.Menu.gotoReport(event, this, \'provider/manage/CommissionByStaffService\')">Commission</a></i>';
54470		var htmStaff2 = '<div id="pop-pos-profile-staff2" class="pop-pos-line"><label>Customize</label>' + aStaffSvc + aCommission + '</div>';
54471		
54472		//var htmStaffRpt = '<div class="pop-pos-line"><label style="letter-spacing: 0;">Staff Profile Report</label>' + aProfileReport + '</div>';
54473		var htmStaff = '<div id="pop-pos-profile-preview-staff">' + hStaff + htmStaff1 + htmStaff2 + '</div>';											// + htmStaffRpt
54474		
54475		var btnPosHelp = '<span class="btnAdd btnPosHelp">
54475<a onclick="SA.POS.openHelp(true)">Help</a></span>';						//GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced?open=tab-help\', this, event, true)
54476		
54477		if ($('#header-main-row-clock-out #clock-out-icon').length) {
54478			var iconClockIn = '<span id="clock-out-icon" class="sa-sprite" onclick="UserPortal.Edit.ClockIn.open(this)" title="Clock In and Out"> <a style="color: rgb(255, 255, 255);"></a> </span>';
54479		} else {
54480			var iconClockIn = '';
54481		}
54482		
54483		var htm = '<div id="pop-pos-profile-preview">' + htmBiz + htmStaff + '</div>';
54484		var jpop = GLO.Popup.Custom.openSimple(htm, 'Manage Profile').addClass('pop-pos');
54485		
54486		jpop.find('.pop-buttons-parent').append(btnPosHelp).find('.pop-buttons').append(iconClockIn);
54487		GLO.Popup.Custom.singleButton(jpop, 'Close');
54488    }
54489    _conPos.openHelp = function(isIncludeWebsite) {
54490    	GLO.Popup.closeIfExist($('.pop-pos.glopop'));
54491    	GLO.Popup.closeIfExist($('.pop-header-drop-menu.glopop'));
54492    	
54493    	var htmHi = '<div id="pop-pos-help-hi" style="font-weight: bold; color: #4F81BD;">Hi ' + GLO.Info.getStaffName() + '</div>';
54494    	var aEditPos = '<label><span class="btnAdd"><a onclick="SA.POS.Edit.openHelp()">Edit P.O.S.</a></span></label>';
54495    	var aFAQ = '<label><a onclick="GLO.Uri.gotoUriWithSpinner(\'help#tab=pos\', this, event, true)">Frequently Asked Questions</a></label>';
54496    	var aHowToGuides = '<label><a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/advanced?open=tab-help\', this, event, true)">How To Guides</a></label>';
54497    	var aNew = '<label><a onclick="SA.POS.openNewFeatures()">Newest Features</a></label>';
54498    	var aHelpIcon = '<b class="question-icon">?</b>';
54499    	
54500    	var htmQuickGuide = '<h5 id="pop-pos-help-quick" onclick="SA.POS.openHelpQuickGuide()">' + aHelpIcon + '<label>P.O.S. Screen Quick Guide</label></h5>';
54501    	var htmContact = '<h5 id="pop-pos-contact-sa" onclick="GLO.Log.openContactSAPopup(null, null, null, true)"> <i>Contact</i> ' + GLO.Info.getScheduleAnyoneHtm(true) + '</h5>';
54502		var htmEditPos = '<div class="pop-pos-line" id="pop-pos-help-edit">' + aEditPos + '<i>Customize the P.O.S. Screen</i></div>';
54503    	var htmFAQ = '<div class="pop-pos-line" id="pop-pos-help-faq">' + aFAQ + '<i>Quick overview of common questions</i></div>';
54504    	var htmHowToGuides = '<div class="pop-pos-line" id="pop-pos-help-how-to">' + aHowToGuides + '<i>Detailed information how everything works</i></div>';
54505		var htmNew = '<div class="pop-pos-line" id="pop-pos-help-new">' + aNew + '<i>Checkout the latest ' + GLO.Info.getScheduleAnyoneHtm() + ' features</i></div>';
54506		
54507		if (isIncludeWebsite) {
54508			var aWeb = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + GLO.Info.getScheduleAnyoneWebsite() + '\', this, event, true)">' + GLO.Info.getScheduleAnyoneHtm() + '.com</a>';
54509			var htmWeb = '<div class="pop-pos-line" id="pop-pos-help-web"><label>' + aWeb + '</label><i>Visit our website for more information</i></div>';
54510		} else {
54511			var htmWeb = '';
54512		}
54513		
54514		var htm = '<div id="pop-pos-help">' + htmHi + htmQuickGuide + htmContact + htmEditPos + htmFAQ + htmHowToGuides + htmNew + htmWeb + '</div>';
54515		var h1 = GLO.Info.getScheduleAnyoneHtm(true) + ' Help';
54516		var jpop = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-pos');
54517		
54518		jpop.find('h1').css({ "background-color": "#444" });
54519    	GLO.Popup.Custom.singleButton(jpop, 'Close');
54520    }
54521    
54522    _conPos.openNewFeatures = function() {
54523		GLO.Popup.close( $('#pop-pos-help').closest('.glopop') );
54524		
54525		var icon = $('#header-main-logo')[0];
54526		SA.Menu.openNewestFeatureHelp(icon);    	
54527    }
54528    
54529    _conPos.Edit = (function() {
54530    	function _conPosEdit() { }
54531    	var _plineDD = null;
54532    	var _DEFAULT_COLOR = 'rgb(98,190,203)', _DEFAULT_BACKGROUND_COLOR = 'rgb(255,255,255)';
54533    	var _popEditBrand = null, _popEditCategory = null, _popEditProduct = null;
54534    	
54535    	_conPosEdit.changeMode = function() {
54536	    	SA.Ticket.displayTicket();
54537	    	var j = $('#pos-container');
54538	    	var jbreadcrumb = j.find('#pos-product-header-breadcrumb');
54539	    	
54540	    	if (j.hasClass('edit-pos')) {
54541	    		j.removeClass('edit-pos');
54542	    		j.find('#pos-edit-add-buttons').addClass('hide');
54543	    		
54544	    		var parentBtn = j.find('#pos-product-header-breadcrumb').find('#pos-product-header-add-pline, #pos-product-header-add-category-type');
54545	    		
54546	    		if (parentBtn.length > 0) {
54547	    			parentBtn.remove();
54548	    			jbreadcrumb.find('b:last').remove();
54549	    		}
54550	    		
54551	    		$('#hello-bar-generic').remove();
54552	    		$('#edit-pos-button').find('a').text('Edit POS');
54553	    		$('body').removeClass('phone-has-hello-bar');
54554	    		
54555	    		SA.Ticket.clearTicket();
54556	    		var uri = GLO.Link.WebsiteDomain + 'pos';
54557	    		//if (keepEdit) { uri += '?edit=1'; }
54558	    	} else {
54559	    		j.find('#POS_Use_Service_Image_fl').prop('checked', _conPos.inventory_json.use_service_image_fl);
54560	    		
54561	    		GLO.Popup.closeIfExist($('#pop-pos-profile-preview').closest('.glopop'));
54562		    	SA.POS.toggleActionMenu(true);			//if (!$('#pos-action-menu').hasClass('hide')) {
54563		    	
54564		    	_setEditModeHideTicketPanel();
54565		    	_addHelloBar('Edit P.O.S. Screen', 'SA.POS.Edit.changeMode()');
54566	    		
54567	    		j.addClass('edit-pos');
54568	    		var uri = GLO.Link.WebsiteDomain + 'pos?edit=1';
54569	    	}
54570	    	
54571	    	window.history.replaceState("", "", uri);				//=removes '?edit=true' (if exists) from url.
54572	    	_clickBreadcrumbEnd(null, null, true);
54573	    	
54574	    	/*		//= instead just calling breadcrumbEnd, which also dis
54574plays (if is edit) or hides (if not) brands / plines with zero products.
54575	    	var vendor = null, vendorId = jbreadcrumb.attr('vendor_id');
54576	    	var productLine = null, plineId = jbreadcrumb.attr('product_line_id');
54577	    	
54578	    	if (plineId) { productLine = _conPos.getPLineObject(plineId); }
54579	    	if (vendorId) { vendor = _conPos.getVendorObject(vendorId); }
54580	    	
54581	    	_displayEnterProductHeader(vendor, productLine);
54582	    	_conPosEdit.displayForIsEdit(vendor, productLine);
54583	    	*/
54584		}
54585	    
54586	    function _setEditModeHideTicketPanel() {
54587	    	var j = $('#pos-ticket-edit-hide-panel');
54588	    	
54589	    	if (_conPos.inventory_json.hide_ticket_panel_fl) {
54590	    		j.find('#POS_Edit_Ticket_Panel_Hide').prop('checked', true);
54591	    	} else if (UTIL.parseBool($.cookies.get('hide_ticket_panel_fl'))) {
54592	    		j.find('#POS_Edit_Ticket_Panel_Hide_This_Device').prop('checked', true);
54593	    	} else {
54594	    		j.find('#POS_Edit_Ticket_Panel_Display').prop('checked', true);
54595	    	}
54596	    }
54597	    
54598	    function _addHelloBar(label, closeFnName, customClass) {
54599	    	$('#hello-bar-generic').remove();
54600	    	
54601	    	if (innerWidth < 800) {
54602	    		var saHtm = '<img class="sa-logo sa-logo-footer" src="https://www.ScheduleAnyone.com/image/marketing/logo/logo.png">';
54603	    	} else {
54604	    		var saHtm = GLO.Info.getScheduleAnyoneHtm();
54605	    	}
54606	    	
54607	    	//var closeIcon = '<span class="close-hello-bar-icon"><b onclick="' + closeFnName + '">&#10006;</b></span>';
54608	    	var closeIcon = '<a class="x-close-img sa-sprite" onclick="' + closeFnName + '" style="float: right; border-bottom: none;"></a>';
54609	    	
54610	    	var helloBar = '<div id="hello-bar-generic" class="hello-bar-container ' + $.trim(customClass) + '" style="display:none;"> <p>'
54611    					+ '<span class="hello-bar-brand hello-bar-brand-left">' + saHtm + '</b></span>'
54612    					+ '<span class="hello-bar-center">'
54613    						+ '<span class="hello-bar-label">' + label + '</span>'
54614    						+ '<span class="hello-bar-buttons">'
54615    							+ '<span class="btnQuestions btnAdd"><a onclick="SA.POS.Edit.openHelp()">Questions?</a></span>'
54616    							+ '<span class="btnContact btnAdd"><a onclick="GLO.Log.openContactSAPopup()"> Contact</a> </span>'
54617    						+ '</span>'
54618    					+ '</span>'
54619    					+ '<span class="hello-bar-brand-right">' + closeIcon + '</span>'
54620    				 + '</p> </div>';
54621    		
54622    		GLO.Info.displayHelloBarHtm(helloBar);
54623	    }
54624	    
54625	    _conPosEdit.changeSortBy = function() {
54626	    	if (_conPos.sortType === 1) {
54627	    		$('#sort-product-by-category').prop('checked', true);
54628	    		$('#pos-product-header-add-category').removeClass('hideX');
54629	    		
54630	    		$('#pos-product-header-add-vendor').addClass('hideX');
54631	    	} else if (_conPos.sortType === 2) {
54632	    		$('#sort-product-by-brand').prop('checked', true);
54633	    		$('#pos-product-header-add-vendor').removeClass('hideX');
54634	    		
54635	    		$('#pos-product-header-add-category').addClass('hideX');
54636	    	}
54637	    }
54638    	
54639    	_conPosEdit.displayForIsEdit = function(grand, parent) {
54640	    	if (!$('#pos-container').hasClass('edit-pos')) { return; }
54641	    	
54642	    	if (grand || parent) {
54643	    		$('#pos-edit-add-buttons').addClass('hide');
54644	    		
54645	    		if (_isDisplayServices()) {
54646	    			var jbox = $(_getBox('sg', grand));
54647	    			_conPos.Edit.moveBoxForEdit(jbox);
54648	    		} else if (_conPos.sortType === 2) {
54649		    		if (parent) {
54650		    			var jbox = $(_getBox('pl', parent));
54651		    			_conPos.Edit.moveBoxForEdit(jbox, true);
54652		    		} else {
54653		    			var jbox = $(_getBox('v', grand));
54654		    			_conPos.Edit.moveBoxForEdit(jbox);
54655		    		}
54656		    	} else {
54657		    		if (parent) {
54658		    			var jbox = $(_getBox('ct', parent));
54659		    			_conPos.Edit.moveBoxForEdit(jbox, true);
54660		    		} else {
54661		    			var jbox = $(_getBox('c', grand));
54662		    			_conPos.Edit.moveBoxForEdit(jbox);
54663		    		}
54664		    	}
54665	    	} else {
54666	    		$('#pos-edit-add-buttons, #pos-product-header-add-vendor, #pos-product-header-add-category').removeClass('hide');
54667	    		$('#pos-header-edit-box').html('');
54668	    	}
54669	    }
54670    	
54671    	_conPosEdit.moveBoxForEdit = function(jbox, isProductLine) {
54672	    	//alert(jbox.outerHTML());
54673	    	$('#pos-header-edit-box').html(jbox.outerHTML());
54674	    	
54675	    	var jbox = $('#pos-header-edit-box').find('.pos-product-box');
54676	    	
54677	    	if (_isDisplayServices()) {
54678	    		jbox.click(SA.POS.Edit.openServiceGroup);
54679	    	} else if (_conPos.sortType === 2) {
54680		    	if (isProductLine) {
54681		    		jbox.click(SA.POS.Edit.openPLine);				//GLO.UI.setClick(jbox, null, SA.POS.Edit.openPLine);
54682		    	} else {
54683		    		jbox.click(SA.POS.Edit.openVendor);				//GLO.UI.setClick(jbox, null, SA.POS.Edit.openVendor);
54684		    	}
54685		    } else {
54686		    	if (isProductLine) {
54687		    		jbox.click(SA.POS.Edit.openCategoryType);
54688		    	} else {
54689		    		jbox.click(SA.POS.Edit.openCategory);
54690		    	}
54691		    }
54692	    }
54693    	
54694    	_conPosEdit.leftHandMode = function(checkbox) {
54695	    	if ($(checkbox).prop('checked')) {
54696	    		var isLeft = 1;
54697	    		$('#pos-container').removeClass('left-ticket');
54698	    	} else {
54699	    		var isLeft = 0;
54700	    		$('#pos-container').addClass('left-ticket');
54701	    	}
54702	    	
54703	    	var url = GLO.Link.WebsiteDomain + 'pos/LeftHandMode';
54704	    	
54705	    	var jqxhr = $.ajax({ type: "POST", dataType: 'json', url: url, data: { "isleft": isLeft }, "cache": false })
54706	            .success(function(data, textStatus, jqXHR) {
54707	            	
54708	            })
54709		        .error(function(jqXHR, textStatus, errorThrown) {
54710		        
54711		        });
54712	    }
54713    	
54714    	_conPosEdit.openServiceGroup = function(jbox) {
54715	    	if (UTIL.isEmptyObject(jbox)) {
54716	    		jbox = $(this);
54717	    	}
54718	    	
54719	    	var sgid = jbox.attr('service_group_id');
54720	    	var sg = _conPos.getServiceGroupObject(sgid);
54721        	
54722        	var urlChangeImage = UserPortal.getProviderUri() + 'gallery/ServiceGroup/edit?helloback=pos&isedit=1&imgsize=icon#keyid=' + sgid;
54723        	var urlChangeBackground = 'provider/profile/4?sgid=' + sgid + '&edit=color&helloback=pos&isedit=1';
54724        	var aChangeBackground = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlChangeBackground + '\', this, event, true)">';
54725        	
54726        	var p = '<p class="text-over-background">';
54727        	var msg1 = p + 'P.O.S. uses color from ' + aChangeBackground + 'Profile -> Service</a></p>';
54728        	var msg2 = p + 'P.O.S. uses image from <a onclick="' + _getLinkFunction(urlChangeImage) + '">Service Gallery</a></p>';
54729        	
54730        	if (!UTIL.isEmpty(sg.image_vc)) {
54731        		var imgLabel = 'Change Image', htmChangeBackground = '';
54732        	} else {
54733        		var imgLabel = 'Upload Image';
54734        		var htmChangeBackground = '<div style="margin-top: 32px;"><span class="btnAdd">' + aChangeBackground + 'Change Color</a></span></div>';
54735        	}
54736        	
54737        	var htm = msg1 + msg2;
54738        	htm += '<div style="margin-top: 32px;"><span class="btnAdd"><a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlChangeImage + '\', this, event, true)">' + imgLabel + '</a></span></div>';
54739        	htm += htmChangeBackground;
54740        	
54741	    	var jpop = GLO.Popup.Custom.openSimple('<div id="pop-pos-edit-service-group" style="min-height: 300px; min-width: 300px;">' + htm + '</div>', sg.name);
54742	    	jpop.css({ "background-color": "rgb(" + sg["background-color"] + ")" });
54743	        GLO.Popup.Custom.singleButton(jpop, 'Close');
54744	    }
54745	    _conPosEdit.openService = function(jbox, serviceId) {
54746	    	var jbox = $(jbox);
54747	    	var sgid = jbox.attr('service_group_id');
54748	    	var svc = _conPos.getServiceObject(serviceId);
54749	    	var sg = _conPos.getServiceGroupObject(sgid);
54750	    	
54751        	var urlChangeImage = UserPortal.getProviderUri() + 'gallery/' + sg.gallery_uri_key_vc + '/edit?helloback=pos&isedit=1&imgsize=icon&gallery_id=' + sg.gallery_id + '&gallery_key_id=' + sgid + '#keyid=' + serviceId;
54752        	var urlChangeBackground = 'provider/profile/4?sgid=' + sgid + '&edit=color&helloback=pos&isedit=1';
54753        	var aChangeBackground = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlChangeBackground + '\', this, event, true)">';
54754        	
54755        	var p = '<p class="text-over-background">';
54756        	var msg1 = p + 'P.O.S. uses color from ' + aChangeBackground + 'Profile -> Service</a></p>';
54757        	
54758        	if (!UTIL.isEmpty(svc.image_vc)) {
54759        		var msg2 = p + 'P.O.S. uses image from <a onclick="' + _getLinkFunction(urlChangeImage) + '">' + sg.name + ' Gallery</a></p>';
54760        		var htm = '<div style="margin-top: 32px;"><span class="btnAdd"><a onclick="' + _getLinkFunction(urlChangeImage) + '">Change Image</a></span></div>';
54761        	} else {
54762        		if (UTIL.isEmpty(sg.gallery_id)) {
54763        			urlChangeImage = UserPortal.getProviderUri() + 'gallery/new/edit?category=sg' + sgid + '&imgsize=icon&IsHide=1&helloback=pos&isedit=1#keyid=' + serviceId;
54764        			var msg2 = p + 'Add <a onclick="' + _getLinkFunction(urlChangeImage) + '">' + sg.name + ' Gallery</a> then upload ' + svc.name + ' image to see image in your P.O.S.</p>';
54765        		} else {
54766        			var msg2 = p + 'P.O.S. uses image from <a onclick="' + _getLinkFunction(urlChangeImage) + '">' + sg.name + ' Gallery</a></p>';
54767        		}
54768        		
54769        		var htm = '<div style="margin-top: 32px;"><span class="btnAdd"><a onclick="' + _getLinkFunction(urlChangeImage) + '">Upload Image</a></span></div>';
54770        		htm += '<div style="margin-top: 32px;"><span class="btnAdd">' + aChangeBackground + 'Change Color</a></span></div>';
54771        	}
54772        	
54773        	var img = jbox.css('background-image').replace('url(', '').replace(')', '').replace(/"/g, '').replace(/'/g, '');
54774        	var htmManageImage = _getManageImageHtm(img);
54775        	
54776	    	var jpop = GLO.Popup.Custom.openSimple('<div id="pop-pos-edit-service" style="min-height: 300px; min-width: 300px;">' + msg1 + msg2 + htm + '</div>', svc.name);
54777	    	jpop.css({ "background-color": "rgb(" + sg["background-color"] + ")" });
54778	        GLO.Popup.Custom.singleButton(jpop, 'Close');
54779	    }
54780	    function _getManageImageHtm(imgUrl) {
54781	    	
54782	    	
54783	    	if (!UTIL.isEmpty(imgUrl)) {
54784	    		var jimg = $('.pos-popup-sample-box .upload-control-parent').clone();
54785	    		jimg.css({ "background-image": "url('" +  + "')"  });
54786	    		return jimg.outerHTML();
54787	    	} else {
54788	    		return $('.pos-popup-sample-box .sa-upload').outerHTML();
54789	    	}
54790	    }
54791	    function _getLinkFunction(url) {
54792	    	return 'GLO.Uri.gotoUriWithSpinner(\'' + url + '\', this, event, true)';			//, \'Service Image\'
54793	    }
54794	    
54795    	_conPosEdit.openVendor = function() {
54796	    	var jbox = $(this);
54797	    	_conPosEdit.openBrandOrPLine(jbox);
54798	    }
54799	    _conPosEdit.openPLine = function() {
54800	    	var jbox = $(this);
54801	    	_conPosEdit.openBrandOrPLine(jbox, true);
54802	    }
54803	    _conPosEdit.openNewPLine = function() {
54804	    	_conPosEdit.openBrandOrPLine(null, true);
54805	    }
54806	    
54807	    _conPosEdit.openCategory = function() {
54808    		var jbox = $(this);
54809    		_conPosEdit.openCategoryOrType(jbox);
54810    	}
54811    	_conPosEdit.openCategoryType = function() {
54812    		var jbox = $(this);
54813    		_conPosEdit.openCategoryOrType(jbox, true);
54814    	}
54815    	_conPosEdit.openNewCategoryType = function() {
54816	    	_conPosEdit.openCategoryOrType(null, true);
54817	    }
54818	    
54819	    _conPosEdit.openCategoryOrType = function(jbox, isType) {
54820	    	var fn, catId = null;
54821	    	
54822	    	if (jbox && jbox.attr) {
54823	    		catId = jbox.attr('category_id');
54824	    	}
54825	    	
54826	    	var htm = _getPopupCategoryHtm();
54827	        var jpop = GLO.Popup.Custom.openSimple(htm, 'Edit Category', SA.POS.Edit.saveCategory);
54828	        
54829	        if (isType) {
54830	        	var jdd = jpop.find('#Existing_Category_id');
54831	        	var tr = jpop.find('#ctype-input-row').removeClass('hide');
54832	        	
54833	        	_addDD(jdd, SA.POS.inventory_json.categories, SA.Resource.Category);
54834	        	jdd.find('option[value="new"]').remove();
54835	        	
54836	        	if (catId) {			//set type:
54837		        	var ctypeId = jbox.attr('inventory_type_id');
54838		        	var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", ctypeId);
54839		        	
54840		        	fn = 'SA.POS.Edit.removeCategoryType';		//if (ctype.product_count === 0) {
54841		        	
54842		        	jpop.find('h1').text(SA.Resource.EditType);
54843		        	jpop.find('#Inventory_Type_id').val(ctypeId);
54844		        	
54845		        	var jname = jpop.find('#Inventory_Type_Name_vc').val(ctype.name).keyup(SA.POS.Edit.setBoxText);
54846		        	
54847		        	if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54848	        	} else {
54849	        		catId = UTIL.cleanString($('#pos-header-edit-box .pos-product-box').attr('category_id'));
54850	        		
54851	        		jpop.find('h1').text(SA.Resource.AddType);
54852	        		jpop.find('.upload-preview').css({ "text-transform": "capitalize" });
54853	        		
54854	        		var jname = jpop.find('#Inventory_Type_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" });
54855	        		
54856	        		if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54857	        	}
54858	        	
54859	        	if (catId) {
54860		        	tr = jpop.find('#category-select-row').removeClass('hide');
54861		    		tr.find('#Existing_Category_id').val(catId);
54862		    	} else {
54863		    		jbox = null;
54864		    	}
54865	        } else {
54866	        	var tr = jpop.find('#category-input-row').removeClass('hide');
54867	    		
54868	    		if (catId) {
54869	    			var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", catId);
54870	        		
54871	        		fn = 'SA.POS.Edit.removeCategory';
54872	        		
54873	        		jpop.find('h1').text(SA.Resource.EditCategory);
54874	    			tr.find('#Category_id').val(catId);
54875	        		var jname = tr.find('#Category_Name_vc').val(category.name).keyup(SA.POS.Edit.setBoxText);
54876	        		
54877	        		if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54878	        	} else {
54879	        		jbox = null;
54880	        		jpop.find('h1').text(SA.Resource.AddCategory);
54881	        		jpop.find('.upload-preview').css({ "text-transform": "capitalize" });
54882	        		
54883	        		var jname = jpop.find('#Category_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" });
54884	        		
54885	        		if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54886	        	}
54887	    	}
54888	    	
54889	    	if (GLO.Info.isMobile()) {
54890	        	jpop.find('#Existing_Category_id').find('option:first').text('( ' + SA.Resource.SelectCategory + ' )');
54891	        }
54892	        
54893	        _openFinish(jpop, jbox, fn);
54894    	}
54895    	
54896    	function _getPopupCategoryHtm() {
54897        	if (_popEditCategory === null) {
54898        		var jpop = $('#pos-popup-category');
54899            	_popEditCategory = jpop.outerHTML();
54900            	jpop.remove();
54901            }
54902            
54903            return _popEditCategory;
54904        }
54905        function _getPopupBrandHtm() {
54906        	if (_popEditBrand === null) {
54907        		var jpop = $('#pos-popup-brand');
54908            	_popEditBrand = jpop.outerHTML();
54909            	jpop.remove();
54910            }
54911            
54912            return _popEditBrand;
54913        }
54914        function _getPopupProductHtm() {
54915        	if (_popEditProduct === null) {
54916        		var jpop = $('#pos-popup-product');
54917            	_popEditProduct = jpop.outerHTML();
54918            	jpop.remove();
54919            }
54920            
54921            return _popEditProduct;
54922        }
54923        
54924    	_conPosEdit.openBrandOrPLine = function(jbox, isPLine) {
54925	    	jbox = $(jbox);
54926	    	var fn, vendorId = jbox.attr('vendor_id');
54927	    	
54928	    	var htm = _getPopupBrandHtm();
54929	        var jpop = GLO.Popup.Custom.openSimple(htm, 'Edit', SA.POS.Edit.saveVendor);
54930	        
54931	        if (isPLine) {
54932	        	var jdd = jpop.find('#Existing_Vendor_id');
54933	        	var tr = jpop.find('#pline-input-row').removeClass('hide');
54934	        	
54935	        	_addDD(jdd, SA.POS.inventory_json.vendors, SA.Resource.Brand);
54936	        	
54937	        	if (vendorId) {			//set pline:
54938		        	var plineId = jbox.attr('product_line_id');
54939		        	var pline = _conPos.getPLineObject(plineId);
54940		        	
54941		        	fn = 'SA.POS.Edit.removePLine';
54942		        	
54943		        	jpop.find('h1').text(SA.Resource.EditProductLine);
54944		        	jpop.find('#Product_Line_id').val(plineId);
54945		        	jpop.find('#Product_Line_Name_vc').val(pline.name).keyup(SA.POS.Edit.setBoxText);
54946	        	} else {
54947	        		vendorId = UTIL.cleanString($('#pos-header-edit-box .pos-product-box').attr('vendor_id'));
54948	        		
54949	        		jpop.find('h1').text(SA.Resource.AddProductLine);
54950	        		jpop.find('.upload-preview').css({ "text-transform": "capitalize" });
54951	        		
54952	        		var jname = jpop.find('#Product_Line_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" });
54953	        		
54954	        		if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54955	        	}
54956	        	
54957	        	if (vendorId) {		//set vendor:
54958		        	tr = jpop.find('#brand-select-row').removeClass('hide');
54959		    		tr.find('#Existing_Vendor_id').val(vendorId);
54960		    	} else {
54961		    		jbox = null;
54962		    	}
54963	    	} else {
54964	    		var tr = jpop.find('#brand-input-row').removeClass('hide');
54965	    		
54966	    		if (vendorId) {
54967	    			var vendor = _conPos.getVendorObject(vendorId);
54968	        		
54969	        		fn = 'SA.POS.Edit.removeVendor';
54970	        		
54971	        		jpop.find('h1').text(SA.Resource.EditBrand);
54972	    			tr.find('#Vendor_id').val(vendorId);
54973	        		var jname = tr.find('#Vendor_Name_vc').val(vendor.name).keyup(SA.POS.Edit.setBoxText);
54974	        		
54975	        		if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54976	        	} else {
54977	        		jbox = null;
54978	        		jpop.find('h1').text(SA.Resource.AddBrand);
54979	        		jpop.find('.upload-preview').css({ "text-transform": "capitalize" });
54980	        		
54981	        		var jname = jpop.find('#Vendor_Name_vc').keyup(SA.POS.Edit.setBoxText).css({ "text-transform": "capitalize" });
54982	        		
54983	        		if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
54984	        	}
54985	    	}
54986	    	
54987	    	if (GLO.Info.isMobile()) {
54988	        	jpop.find('#Existing_Vendor_id').find('option:first').text('( ' + SA.Resource.SelectBrand + ' )');
54989	        }
54990	        
54991	        _openFinish(jpop, jbox, fn);
54992	    }
54993	    
54994	    _conPosEdit.openProduct = function(jbox, inventoryId) {
54995	    	var fn, htm = _getPopupProductHtm();
54996	        var jpop = GLO.Popup.Custom.openSimple(htm, 'Edit Product', SA.POS.Edit.saveProduct);
54997	        
54998	        var jdd = jpop.find('#Existing_Vendor_id');
54999	        _addDD(jdd, SA.POS.inventory_json.vendors, SA.Resource.Brand);
55000	        
55001	        jdd = jpop.find('#Existing_Product_Line_id');
55002	        _addPLineDD(jdd, SA.POS.inventory_json.product_lines, SA.Resource.ProductLine);
55003	        
55004	        jdd = jpop.find('#Unit_id');
55005	        _addUnitDD(jdd, SA.POS.inventory_json.units, SA.Resource.Unit);
55006	        
55007	        _addCategoryAndTypeDD(jpop);
55008	        var jbreadcrumb = $('#pos-product-header-breadcrumb');
55009	        
55010	        if (inventoryId) {
55011	        	fn = 'SA.POS.Edit.removeProduct';
55012	        	var product = _conPos.getProductObject(inventoryId);
55013	        	
55014	        	jpop.find('h1').text(SA.Resource.EditProduct);
55015	        	jpop.find('#Inventory_id').val(product.id);
55016	        	jpop.find('#Existing_Vendor_id').val(product.vendor_id);
55017	        	
55018	        	var jname = jpop.find('#Name_vc').val(product.label).keyup(SA.POS.Edit.setBoxText).focus();
55019	        	
55020	        	if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
55021	        	
55022	        	if (product.product_line_id) { jpop.find('#Existing_Product_Line_id').val(product.product_line_id); }
55023	        	if (product.size_vc) { jpop.find('#Size_dr').val(product.size_vc); }
55024	        	if (product.unit_id) { jpop.find('#Unit_id').val(product.unit_id); }
55025	        	
55026	        	if (product.inventory_type_id || product.category_id) {
55027		        	var typeId = UTIL.coalesce(product.inventory_type_id, 'c' + product.category_id);
55028		        	jpop.find('#Inventory_Type_id').val(typeId);
55029	        	}
55030	        	
55031	        	if (product.upc_vc) { jpop.find('#UPC_vc').val(product.upc_vc); }
55032	        	if (product.price_mn) { jpop.find('#Price_mn').val(UTIL.displayMoney(product.price_mn, true)); }
55033	        	
55034	        	if (product.tax_rate_pct === 0 || (UTIL.isEmpty(product.tax_rate_pct) && UTIL.coalesceMoney(GLO.inventoryTax) === 0) ) { jpop.find('#Not_Taxable_fl').prop('checked', true); }
55035	        } else {
55036	        	jpop.find('h1').text(SA.Resource.AddProduct);
55037	        	jpop.find('.upload-preview').css({ "text-transform": "capitalize" });
55038	        	
55039	        	var jname = jpop.find('#Name_vc').css({ "text-transform": "capitalize" }).keyup(SA.POS.Edit.setBoxText);
55040	        	
55041	        	if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) { jname.focus(); }
55042	        	
55043	        	if (_conPos.sortType === 2) {
55044	        		jpop.find('#Existing_Vendor_id').val();
55045	        		jpop.find('#Existing_Product_Line_id').val();
55046	        	} else {
55047	        		var typeId = jbreadcrumb.attr('inventory_type_id');
55048	        		var catId = jbreadcrumb.attr('category_id');
55049	        		
55050	        		if (typeId || catId) {
55051	        			jpop.find('#Inventory_Type_id').val(UTIL.coalesce(typeId, 'c' + catId));
55052	        		}
55053	        	}
55054	        }
55055	        
55056	        if (GLO.Info.isMobile()) {
55057	        	jpop.find('#Existing_Vendor_id').find('option:first').text('( ' + SA.Resource.SelectBrand + ' )');
55058	        	jpop.find('#Existing_Product_Line_id').find('option:first').text('( ' + SA.Resource.ProductLine + ' )');
55059	        	jpop.find('#Inventory_Type_id').find('option:first').text('( ' + SA.Resource.Category + ' / ' + SA.Resource.Type + ' )');
55060	        } else {
55061	        	//jpop.find('.pop-buttons').css({ "width": "600px", "padding-top": "20px" });
55062	        }
55063	        
55064	        jpop.find('#Existing_Product_Line_id').change();
55065	        _openFinish(jpop, jbox, fn);
55066	    }
55067	    
55068	    function _addDD(jdd, arr, label) {
55069	    	for (var i=0; i < arr.length; i++) {
55070	        	jdd.append('<option value="' + arr[i].id + '">' + arr[i].name + '</option>');
55071	        }
55072	        
55073	        jdd.append('<option value="new">(+ ' + SA.Resource.New + ' ' + label + ')</option>');
55074	    }
55075	    
55076	    function _addPLineDD(jdd, arr, label) {
55077	    	for (var i=0; i < arr.length; i++) {
55078	        	jdd.append('<option value="' + arr[i].id + '" vendor_id="' + UTIL.cleanString(arr[i].vendor_id) + '">' + arr[i].name + '</option>');
55079	        }
55080	        
55081	        jdd.append('<option value="new">(+ ' + SA.Resource.New + ' ' + label + ')</option>');
55082	    }
55083	    
55084	    function _addUnitDD(jdd, arr, label) {
55085	    	for (var i=0; i < arr.length; i++) {
55086	        	jdd.append('<option value="' + arr[i].id + '" title="' + arr[i].name + '">' + arr[i].abbreviation_vc + '</option>');
55087	        }
55088	        
55089	        jdd.append('<option value="new">(+ ' + SA.Resource.New + ' ' + label + ')</option>');
55090	    }
55091	    
55092	    function _addCategoryAndTypeDD(jpop) {
55093	    	var categories = SA.POS.inventory_json.categories;
55094	    	var types = SA.POS.inventory_json.types;
55095	    	
55096	    	jdd = jpop.find('#Inventory_Type_id');
55097	    	
55098	    	for (var i=0; i < categories.length; i++) {
55099	    		jdd.append('<option value="c' + categories[i].id + '">' + categories[i].name + '</option>');
55100	    		
55101	        	for (var j=0; j < types.length; j++) {
55102	        		if (categories[i].id === types[j].category_id) {
55103	        			jdd.append('<option value="' + types[j].id + '">' + categories[i].name + ' / ' + types[j].name + '</option>');
55104	        		}
55105	        	}
55106	        }
55107	        
55108	        jdd.append('<option value="new">(+ ' + SA.Resource.NewCategoryType + ' )</option>');
55109	    }
55110	    
55111	    _conPosEdit.setBoxText = function() {
55112	    	$('.pos-popup-sample-box .pos-product-box > div').text(this.value);
55113	    }
55114	    
55115	    function _openFinish(jpop, jbox, deleteFunction) {
55116	    	if (jbox) {
55117	    		jpop.find('.pos-product-box > div').text(jbox.find('div').text());
55118	    	} else {
55119	    		jpop.find('.pos-product-box > div').text('');
55120	    	}
55121	    	
55122	    	_openFinish_setBox(jbox);
55123	    	_openFinish_buttons(jpop, deleteFunction);
55124	    	_openFinish_fileUpload(jpop, jbox);
55125	    	
55126	    	var jsave = jpop.find('.btnSave a').css({ "border": "3px solid transparent", "letter-spacing": "2px" });
55127	    	jpop.find('input, select, textarea').on('change', function() { jsave.css({ "border": "3px solid Red" }); });
55128	    	jpop.find('h1').css({ "letter-spacing": "2px" });
55129	    	
55130	    	jpop.find('.modalClose, .btnCancel, .btnSave').click(function() {
55131	    		$('#jscolor-picker-close-button:visible').mousedown();
55132	    	});
55133	    }
55134	    
55135	    function _openFinish_setBox(jbox) {
55136	    	var jColorPicker = new jscolor.color(document.getElementById('pos-background-color'), {});
55137	    	var style = '', backColor = _DEFAULT_BACKGROUND_COLOR, textColor = _DEFAULT_COLOR;
55138	    	
55139	    	if (jbox) {
55140	    		var style = UTIL.cleanString(jbox.attr('style'));
55141	    		
55142	    		if (style.indexOf('background-color:') !== -1) {
55143	    			backColor = jbox.css("background-color");
55144	    		}
55145	    	}
55146	    	
55147	        jColorPicker.fromString(UI.rgbToHex(backColor));
55148	        jColorPicker = new jscolor.color(document.getElementById('pos-text-color'), {});
55149			
55150			if (style.indexOf('color:') !== -1) {
55151				jColorPicker.fromString(UI.rgbToHex(jbox.css("color")));
55152			} else {
55153				jColorPicker.fromString(UI.rgbToHex(_DEFAULT_COLOR));
55154			}
55155	    }
55156	    
55157	    function _openFinish_buttons(jpop, deleteFunction) {
55158	    	var mtop = "60px";
55159	    	
55160	    	if (jpop.find('#pos-popup-product').length === 1) { width = "24px"; }
55161	    	
55162	    	var jbtns = jpop.find('.pop-buttons').addClass('basic-mobile-buttons').css({ "margin-top": mtop });
55163	    	jbtns.find('.btnCancel').css({ "position": "absolute", "left": "8px", "margin-right": "" });
55164	    	
55165	    	cssStyle = 'position: absolute; right: 8px; display: inline-block; margin-left: inherit; margin-right: inherit;';
55166    		
55167    		jbtns.find('.btnSave').css({ "display": "inline-block", "min-width": "64px", "position": "relative", "right": "inherit", "margin": "0", "text-align": "center" });
55168        	jbtns.append('<span class="btnDelete hide" style="' + cssStyle + '"> <a onclick="' + deleteFunction + '()">' + SA.Resource.Delete + '</a> </span>');
55169	    	
55170	    	if (deleteFunction) {
55171	    		jbtns.find('.btnDelete').removeClass('hide');
55172	    	}
55173	    }
55174	    
55175	    function _openFinish_fileUpload(jpop, jbox) {
55176	    	SA.Uploader.init(jpop, SA.POS.Edit.imageUploadComplete);
55177			var jpreview = jpop.find('.upload-preview');
55178			
55179			if (jbox) { var img = UTIL.cleanString(jbox.css("background-image")); } else { var img = ''; }
55180			
55181			if (img != '' && img !== 'none') {
55182				var imgUrl = img;
55183				
55184				if (imgUrl.indexOf('url(') === 0) {
55185					imgUrl = imgUrl.substring(5, imgUrl.length - 2);
55186				}
55187				
55188				var arr = imgUrl.split('/');				//var arr = img.substring(4, img.length-1).split('/');
55189				var nm = arr[arr.length-1];
55190				
55191				jpreview.css({ "background-image": img });
55192				jpop.find('.pos-popup-box').addClass('edit-image');
55193				jpop.find('.sa-upload').attr('file_name_vc', nm);
55194			} else {
55195				jpreview.css({ "background-image": "" });
55196				jpop.find('.pos-popup-box').removeClass('edit-image');
55197				jpop.find('.sa-upload').attr('file_name_vc', '');
55198			}
55199	    }
55200	    
55201	    _conPosEdit.editImageUpdateUI = function(fileName, imgid) {
55202	    	var jupload = $('.pos-popup-box');
55203	    	_conPosEdit.imageUploadComplete(jupload, fileName, imgid);
55204	    }
55205	    
55206	    _conPosEdit.hideEditImage = function() {
55207	    	$('#pos-container').removeClass('hide');
55208	    	
55209	    	var jpop = $('.pos-popup-box').closest('.glopop.hideX').removeClass('hideX');
55210			var popID = jpop.attr('id').substring(6);								//= glopop0
55211			$('#pop-overlay' + popID).removeClass('hideX');
55212	    }
55213	    
55214	    _conPosEdit.displayEditImage = function() {
55215			$('#pos-container').addClass('hide');
55216			SA.Uploader.Crop.back();
55217			
55218			var jpop = $('.pos-popup-box').closest('.glopop').addClass('hideX');
55219			var popID = jpop.attr('id').substring(6);								//= glopop0
55220			$('#pop-overlay' + popID).addClass('hideX');
55221			
55222			var src = GLO.Data.cdnDirectory + "upload-folder/" + jpop.find('.sa-upload').attr('file_name_vc');
55223	        var jtarget = $('#crop-image').removeClass('hide');
55224	        
55225	        setTimeout(function() {
55226	            //$('body').append('<img src="' + src + '" onload="loadAndScaleImage(this)"/>');
55227	
55228	            jtarget = jtarget.find('img').attr('src', src);
55229	            GLO.Image.Crop.init(0, jtarget);
55230	        }, 200);
55231		}
55232		
55233		_conPosEdit.removeImage = function() {
55234	    	var css = 'width: 90%; height: 40px; margin-left: 11px; line-height: 150%;';
55235	    	var htm = '<div> <h1 class="friendly-msg2">' + SA.Resource.DeleteImage + '?</h1> <div class="friendly-msg2">' + SA.Resource.DeleteImageConfirm + '?</div> </div>';
55236	    	new GLO.Popup.Confirm(htm, SA.POS.Edit.removeImageConfirmed);
55237	    }
55238	    
55239	    _conPosEdit.removeImageConfirmed = function() {
55240			var jpop = $('.pos-popup-box').closest('.glopop');
55241			var jbox, jd = {};
55242			
55243			if (jpop.find('#pos-popup-brand').length === 1) {
55244				jd.product_line_id = jpop.find('#Product_Line_id').val();
55245				jd.vendor_id = jpop.find('#Vendor_id').val();
55246				
55247				if (!UTIL.isEmpty(jd.product_line_id)) {
55248					jbox = _conPos.getPLineObject(jd.product_line_id);
55249				} else {
55250					jbox = _conPos.getVendorObject(jd.vendor_id);
55251				}
55252			} else if (jpop.find('#pos-popup-category').length === 1) {
55253				jd.type_id = jpop.find('#Inventory_Type_id').val();
55254				jd.category_id = jpop.find('#Category_id').val();
55255				
55256				if (!UTIL.isEmpty(jd.type_id)) {
55257					jbox = _conPos.getObject(SA.POS.inventory_json.types, "id", jd.type_id);
55258				} else {
55259					jbox = _conPos.getObject(SA.POS.inventory_json.categories, "id", jd.category_id);
55260				}
55261			} else if (jpop.find('#pos-popup-product').length === 1) {
55262				jd.inventory_id = jpop.find('#Inventory_id').val();
55263				jbox = _conPos.getProductObject(jd.inventory_id);
55264			}
55265			
55266			var url = GLO.Link.WebsiteDomain + 'pos/RemoveImage';
55267			var jpop = $('.pos-popup-box').closest('.glopop');
55268			var jbtn = jpop.find('.btnImageRemove');
55269			
55270			GLO.UI.Form.beginProcessing(jbtn);
55271			
55272			$.ajax({ "type": "POST", "url": url, "cache": false, data: jd })
55273                .success(function(data, textStatus, jqXHR) {
55274                    GLO.UI.Form.resetProcessing(jbtn);
55275                    _removeImageSuccess(jpop, jbox);
55276                }).error(function(jqXHR, textStatus, errorThrown) {
55277                    GLO.UI.Form.resetProcessing(jbtn);
55278                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55279                });
55280		}
55281		
55282		function _removeImageSuccess(jpop, jbox) {
55283			jpop.find('.upload-preview').css({ "background-image": "" });
55284			jpop.find('.btnSave > a').css({ "border": "3px solid transparent" });
55285			
55286			jpop.find('.upload-control-parent').addClass('hide');
55287			jpop.find('.sa-upload').removeClass('hide').removeAttr('file_name_vc');
55288			
55289			jbox.image_vc = '';
55290			
55291			//_conPosEdit.imageUploadComplete(jpop, '', jbox.id);
55292			_clickBreadcrumbEnd(null, null, true);
55293			
55294			jpop.find('.pos-popup-box').removeClass('edit-image');
55295		}
55296		
55297		_conPosEdit.openNewPopup = function(label, boxType, element, parentId) {
55298	    	var selector = '.glopop #' + element.id;
55299	    	element.value = '';
55300	    	
55301	    	var htm = $('<div id="pos-add-new-popup" box_type="' + boxType + '" selector="' + selector + '" parent_id="' + UTIL.cleanString(parentId) + '" style="margin-bottom: 16px; text-align: center;">'
55302	    		+ '<h1>' + label + '</h1> <input type="text" id="add_new_vc" style="width: 200px;"/> </div>');
55303	    	
55304	    	var jpop = new GLO.Popup.Custom(htm, function() { SA.POS.Edit.saveAdd(selector, boxType, parentId); }).getPopup().addClass('no-persist');
55305			var jbtns = jpop.find('.pop-buttons').addClass('pop-buttons2');
55306	    }
55307	    
55308	    _conPosEdit.changeVendor = function(element) {
55309	    	if (element.value === 'new') {
55310	    		_conPosEdit.openNewPopup(SA.Resource.AddNewBrand, 'v', element);
55311	    		$('#pos-popup-product #Existing_Product_Line_id').val('');
55312	    	} else {
55313	    		var jpl = $('#pos-popup-product #Existing_Product_Line_id');
55314	    		
55315	    		if (_plineDD === null) { _plineDD = $(jpl.outerHTML()); }
55316	    		
55317	    		if (element.value === '') {
55318	    			var newDD = _plineDD.outerHTML();
55319	    		} else {
55320	    			var plOptions = _plineDD.find('option[vendor_id="' + element.value + '"]');
55321	    			var newDD = _plineDD.find('option:first').outerHTML();
55322	    			var vid = parseInt(element.value);
55323	    			
55324	    			for (var i=0; i < plOptions.length; i++) {
55325		    			if (vid === parseInt(plOptions.eq(i).attr('vendor_id'))) {
55326		    				newDD += plOptions.eq(i).outerHTML();
55327		    			}
55328		    		}
55329		    		
55330		    		newDD += _plineDD.find('option:last').outerHTML();
55331	    		}
55332	    		
55333	    		jpl.html(newDD);
55334	    	}
55335	    }
55336    	
55337    	_conPosEdit.changePLine = function(element) {
55338    		var jbrand = $('#pos-popup-product #Existing_Vendor_id');
55339    		
55340    		if (element.value === 'new') {
55341	    		if (!UTIL.isEmpty(jbrand.val())) {
55342	    			var brandName = jbrand.find('option:selected').text();
55343	    			var brandId = jbrand.val();
55344	    			
55345	    			_conPosEdit.openNewPopup(SA.Resource.New + ' ' + brandName + ' ' + SA.Resource.ProductLine, 'pl', element, brandId);
55346	    		} else {
55347	    			new GLO.Popup.Warning(SA.Resource.PleaseSelectBrandMessage, function() { jbrand.focus(); });
55348	    			element.value = '';
55349	    		}
55350	    	} else {
55351	    		var plid = element.value;
55352	    		jbrand.val(jbrand.val()).change();
55353	    		element.value = plid;
55354	    	}
55355	    }
55356    	
55357    	_conPosEdit.changeUnit = function(element) {
55358	    	if (element.value === 'new') {
55359	    		_conPosEdit.openNewPopup(SA.Resource.AddNewUnit, 'u', element);
55360	    		
55361	    		var jpop = $('#pos-add-new-popup').closest('.glopop');
55362				var jnm = jpop.find('#add_new_vc');
55363				
55364				jnm.before('<div style="margin-bottom: 20px;"> <label for="Abbreviation_vc">' + SA.Resource.Abbreviation + '</label> <input type="text" id="Abbreviation_vc" style="width: 80px;" maxlength="5"></select> </div>');
55365	    	}
55366	    }
55367    	
55368    	_conPosEdit.changeCategoryType = function(element) {
55369	    	if (element.value === 'new') {
55370	    		var jpop = $('#pos-add-new-popup').closest('.glopop');
55371	    		GLO.Popup.close(jpop);
55372	    		
55373	    		jpop = $('#pos-popup-product').closest('.glopop');
55374	    		element = jpop.find('#Inventory_Type_id')[0];
55375	    		
55376	    		_conPosEdit.openNewPopup(SA.Resource.AddNewCategoryType, 'ct', element);
55377	    		
55378	    		var categories = SA.POS.inventory_json.categories;
55379	    		var catDD = '<select id="Type_Category_id" class="glopop-first" onchange="SA.POS.Edit.changeCategory(this)" style="width: 200px;">';
55380	    		
55381	    		for (var i=0; i < categories.length; i++) {
55382	    			catDD += '<option value="' + categories[i].id + '">' + categories[i].name + '</option>';
55383	    		}
55384	    		
55385	    		catDD += '<option value="new">(+ ' + SA.Resource.NewCategory + ')</option> </categories>';
55386	    		
55387	    		var jAddNewPop = $('#pos-add-new-popup').closest('.glopop');
55388		    	jAddNewPop.find('#add_new_vc').replaceWith('<div id="new-type-row"> <label for="add_new_vc">' + SA.Resource.Type + '</label>' + jAddNewPop.find('#add_new_vc').removeClass('glopop-first').outerHTML() + '</div>');
55389		    	jAddNewPop.find('#new-type-row').before('<div style="margin-bottom: 20px;"> <label for="Type_Category_id">' + SA.Resource.Category + '</label>' + catDD + '</div>');
55390		    	
55391		    	if (!GLO.Info.isIPad && !GLO.Mobile.isTablet) {
55392		    		jAddNewPop.find('#Type_Category_id').focus();
55393		    	}
55394		    	
55395		    	jAddNewPop.find('label').css({ "display": "inline-block", "width": "80px", "text-align": "center" });
55396	    	}
55397	    }
55398	    
55399	    _conPosEdit.changeCategory = function(element) {
55400	    	if (element.value === 'new') {
55401		    	var jAddNewPop = $('#pos-add-new-popup').closest('.glopop');
55402		    	jAddNewPop.find('#Type_Category_id').replaceWith('<input type="text" id="Type_Category_id" class="glopop-first" style="width: 200px;">');
55403	    	}
55404	    }
55405	    
55406    	_conPosEdit.changeBackgroundColor = function(thisElement) {
55407			document.getElementById('pos-background-color').color.showPicker();
55408			
55409			if (event.x && event.y) {
55410				$('#jscolor-picker-box').css({ "top": (event.y - 20), "left": (event.x - 20) });
55411			}
55412		}
55413		
55414		_conPosEdit.changeTextColor = function(thisElement) {
55415			document.getElementById('pos-text-color').color.showPicker();
55416			
55417			if (event.x && event.y) {
55418				$('#jscolor-picker-box').css({ "top": (event.y - 50), "left": (event.x - 20) });
55419			}
55420		}
55421		
55422		_conPosEdit.removeCategory = function() {
55423			var jpop = $('#pos-popup-category').closest('.glopop');
55424			var catId = jpop.find('#Category_id').val();
55425			var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", catId);
55426	    	
55427	    	if (category.type_count !== 0) {
55428	    		var msg = '<div class="friendly-msg2">Please remove the ' + category.type_count + ' types associated with this category<br/>(or move them to a different category)</div>';
55429	    		new GLO.Popup.Warning(msg);
55430	    		return;
55431	        } else if (category.total_product_count !== 0) {
55432	        	var msg = '<div class="friendly-msg2">Please remove the ' + category.product_count + ' products associated with this category<br/>(or change the product\'s type)</div>';
55433	        	new GLO.Popup.Warning(msg);
55434	        	return;
55435	        }
55436			
55437			var url = GLO.Link.WebsiteDomain + 'pos/RemoveCategory';
55438			var jsave = jpop.find('.btnSave');
55439			GLO.UI.Form.beginProcessing(jsave);
55440			
55441			$.ajax({ "type": "POST", "url": url, "cache": false, data: { "category_id": catId } })
55442                .success(function(data, textStatus, jqXHR) {
55443                    GLO.UI.Form.resetProcessing(jsave);
55444                    GLO.Popup.close(jpop);
55445                    
55446                    _removeSuccessful('c', catId);
55447                }).error(function(jqXHR, textStatus, errorThrown) {
55448                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55449                });
55450		}
55451		
55452		_conPosEdit.removeCategoryType = function() {
55453			var jpop = $('#pos-popup-category').closest('.glopop');
55454			var ctid = jpop.find('#Inventory_Type_id').val();
55455			var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", ctid);
55456			
55457			if (ctype.product_count > 0) {
55458				new GLO.Popup.Warning('Please remove the ' + ctype.product_count + ' products associated with this type (or change the products type)');
55459				return;
55460			}
55461			
55462			var url = GLO.Link.WebsiteDomain + 'pos/RemoveCategoryType';
55463			var jsave = jpop.find('.btnSave');
55464			GLO.UI.Form.beginProcessing(jsave);
55465			
55466			$.ajax({ "type": "POST", "url": url, "cache": false, data: { "inventory_type_id": ctid } })
55467                .success(function(data, textStatus, jqXHR) {
55468                    GLO.UI.Form.resetProcessing(jsave);
55469                    GLO.Popup.close(jpop);
55470                    
55471                    _removeSuccessful('ct', ctid);
55472                }).error(function(jqXHR, textStatus, errorThrown) {
55473                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55474                });
55475		}
55476		
55477		_conPosEdit.removeVendor = function() {
55478			var jpop = $('#pos-popup-brand').closest('.glopop');
55479			var vid = jpop.find('#Vendor_id').val();
55480			var vendor = _conPos.getVendorObject(vid);
55481			
55482			if (vendor.product_line_count !== 0) {
55483	    		var msg = '<div class="friendly-msg2">
55483Please remove the ' + vendor.product_line_count + ' product lines associated with this brand<br/>(or move them to a different brand)</div>';
55484	    		new GLO.Popup.Warning(msg);
55485	    		return;
55486	        } else if (vendor.total_product_count !== 0) {
55487	        	var msg = '<div class="friendly-msg2">Please remove the ' + vendor.total_product_count + ' products associated with this brand<br/>(or change the product\'s brand)</div>';
55488	        	new GLO.Popup.Warning(msg);
55489	        	return;
55490	        }
55491			
55492			var url = GLO.Link.WebsiteDomain + 'pos/RemoveVendor';
55493			var jsave = jpop.find('.btnSave');
55494			GLO.UI.Form.beginProcessing(jsave);
55495			
55496			$.ajax({ "type": "POST", "url": url, "cache": false, data: { "vendor_id": vid } })
55497                .success(function(data, textStatus, jqXHR) {
55498                    GLO.UI.Form.resetProcessing(jsave);
55499                    GLO.Popup.close(jpop);
55500                    
55501                    _removeSuccessful('v', vid);
55502                }).error(function(jqXHR, textStatus, errorThrown) {
55503                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55504                });
55505		}
55506		
55507		_conPosEdit.removePLine = function() {
55508			var jpop = $('#pos-popup-brand').closest('.glopop');
55509			var plid = jpop.find('#Product_Line_id').val();
55510			var pline = _conPos.getPLineObject(plid);
55511			
55512			if (pline.product_count !== 0) {
55513				var msg = '<div class="friendly-msg2">Please remove the ' + pline.product_count + ' products associated with this product line<br/>(or move them to a different product line)</div>';
55514	    		new GLO.Popup.Warning(msg);
55515	    		return;
55516			}
55517			
55518			var url = GLO.Link.WebsiteDomain + 'pos/RemovePLine';
55519			var jsave = jpop.find('.btnSave');
55520			GLO.UI.Form.beginProcessing(jsave);
55521			
55522			$.ajax({ "type": "POST", "url": url, "cache": false, data: { "product_line_id": plid } })
55523                .success(function(data, textStatus, jqXHR) {
55524                    GLO.UI.Form.resetProcessing(jsave);
55525                    GLO.Popup.close(jpop);
55526                    
55527                    _removeSuccessful('pl', plid);
55528                }).error(function(jqXHR, textStatus, errorThrown) {
55529                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55530                });
55531		}
55532		
55533		_conPosEdit.removeProduct = function() {
55534			var url = GLO.Link.WebsiteDomain + 'pos/RemoveProduct';
55535			var jpop = $('#pos-popup-product').closest('.glopop');
55536			var iid = jpop.find('#Inventory_id').val();
55537			
55538			var jsave = jpop.find('.btnSave');
55539			GLO.UI.Form.beginProcessing(jsave);
55540			
55541			$.ajax({ "type": "POST", "url": url, "cache": false, data: { "inventory_id": iid } })
55542                .success(function(data, textStatus, jqXHR) {
55543                    GLO.UI.Form.resetProcessing(jsave);
55544                    GLO.Popup.close(jpop);
55545                    
55546                    _removeSuccessful('i', iid);
55547                }).error(function(jqXHR, textStatus, errorThrown) {
55548                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55549                });
55550		}
55551		
55552		function _removeSuccessful(boxtype, id) {
55553			if (boxtype === 'i') {
55554				var jcrumb = $('#pos-product-header-breadcrumb');
55555				var vid = jcrumb.attr('vendor_id');
55556				var plid = jcrumb.attr('product_line_id');
55557				var products = SA.POS.inventory_json.products;
55558				
55559				for (var i=0; i < products.length; i++) {
55560		    		if (id == products[i].id) {
55561		    			if (products[i].vendor_id) {
55562			    			var vendor = _conPos.getVendorObject(products[i].vendor_id);
55563			    			--vendor.total_product_count;
55564			    			
55565			    			if (products[i].product_line_id) {
55566			    				--_conPos.getPLineObject(products[i].product_line_id).product_count;
55567			    			} else {
55568			    				--vendor.product_count;
55569			    			}
55570		    			}
55571		    			
55572		    			if (products[i].category_id) {
55573		    				var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", products[i].category_id);
55574							--category.total_product_count;
55575							
55576							if (products[i].inventory_type_id) {
55577		    					var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", products[i].inventory_type_id);
55578								--ctype.product_count;
55579							} else {
55580								--category.product_count;
55581							}
55582						}
55583		    			
55584		    			products.splice(i, 1);
55585						break;
55586		    		}
55587		    	}
55588				
55589				_clickBreadcrumbEnd(vid, plid, true);
55590			} else if (boxtype === 'pl') {
55591				var vid, plines = SA.POS.inventory_json.product_lines;
55592		    	
55593		    	for (var i=0; i < plines.length; i++) {
55594		    		if (id == plines[i].id) {
55595		    			vid = plines[i].vendor_id;
55596		    			plines.splice(i, 1);
55597		    			
55598		    			--_conPos.getVendorObject(vid).product_line_count;
55599						break;
55600		    		}
55601		    	}
55602				
55603				_clickBreadcrumbEnd(vid, null, true);
55604			} else if (boxtype === 'v') {
55605				var vendors = SA.POS.inventory_json.vendors;
55606		    	
55607		    	for (var i=0; i < vendors.length; i++) {
55608		    		if (id == vendors[i].id) {
55609		    			vendors.splice(i, 1);
55610						break;
55611		    		}
55612		    	}
55613				
55614				_clickBreadcrumbEnd(null, null, true);
55615			} else if (boxtype === 'ct') {
55616				var catid, ctypes = SA.POS.inventory_json.types;
55617		    	
55618		    	for (var i=0; i < ctypes.length; i++) {
55619		    		if (id == ctypes[i].id) {
55620		    			catid = ctypes[i].category_id;
55621		    			ctypes.splice(i, 1);
55622		    			
55623		    			--_conPos.getObject(SA.POS.inventory_json.categories, "id", catid).type_count;
55624						break;
55625		    		}
55626		    	}
55627				
55628				_clickBreadcrumbEnd(catid, null, true);
55629			} else if (boxtype === 'c') {
55630				var categories = SA.POS.inventory_json.categories;
55631		    	
55632		    	for (var i=0; i < categories.length; i++) {
55633		    		if (id == categories[i].id) {
55634		    			categories.splice(i, 1);
55635						break;
55636		    		}
55637		    	}
55638				
55639				_clickBreadcrumbEnd(null, null, true);
55640			}
55641		}
55642		
55643		_conPosEdit.saveAdd = function(selector, boxtype, parentId) {
55644			var jpop = $('#pos-add-new-popup').closest('.glopop');
55645			var nm = jpop.find('#add_new_vc').val();
55646			var jdata = { "box_type": boxtype, "name_vc": nm, "parent_id": parentId };
55647			
55648			if (UTIL.isEmpty(nm)) {
55649				new GLO.Popup.Warning(SA.Resource.CannotBeBlank, function(){ jpop.find('#add_new_vc').focus(); });
55650				return;
55651			}
55652			
55653			if (boxtype === 'ct') {
55654				var category = jpop.find('#Type_Category_id').val();
55655				
55656				if (UTIL.isEmpty(category)) {
55657					new GLO.Popup.Warning(SA.Resource.PleaseEnterValue, function(){ jpop.find('#Type_Category_id').focus(); });
55658					return;
55659				} else if (!UTIL.isNumber(category)) {													//= new category name, not existing category.
55660					jdata = { "box_type": boxtype, "name_vc": nm, "type_category_name_vc": category };
55661					parentId = undefined;
55662				}
55663			} else if (boxtype === 'u') {
55664				jdata.abbreviation_vc = jpop.find('#Abbreviation_vc').val();
55665			}
55666			
55667			var url = GLO.Link.WebsiteDomain + 'pos/SaveAdd';
55668			var jsave = jpop.find('.btnSave');
55669			GLO.UI.Form.beginProcessing(jsave);
55670			
55671			$.ajax({ "type": "POST", "url": url, "cache": false, data: jdata })
55672                .success(function(data, textStatus, jqXHR) {
55673                    GLO.UI.Form.resetProcessing(jsave);
55674                    GLO.Popup.close(jpop);
55675                    
55676                    _saveAddSuccessful(boxtype, data, selector);
55677                }).error(function(jqXHR, textStatus, errorThrown) {
55678                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55679                });
55680		}
55681		
55682		function _saveAddSuccessful(boxtype, data, selector) {
55683			var jdata = $(data);
55684			var id = parseInt(jdata.attr('id'));
55685			var nm = jdata.attr('name');
55686            var jdd = $(selector);
55687            
55688            if (boxtype === 'v') {
55689				SA.POS.inventory_json.vendors.push({ "id": id, "name": nm, "background-color": "", "color": "", "image_vc": "", "product_line_count": 0, "product_count": 0, "total_product_count": 0 });
55690				
55691				jdd.find('option[value="new"]').before('<option value="' + id + '">' + nm + '</option>');
55692				
55693				_clickBreadcrumbEnd(id, null, true);
55694			} else if (boxtype === 'pl') {
55695				var vid = parseInt(jdata.attr('parent_id'));
55696				var opt = '<option value="' + id + '" vendor_id="' + vid + '">' + nm + '</option>';
55697				
55698				++_conPos.getVendorObject(vid).product_line_count;
55699				SA.POS.inventory_json.product_lines.push({ "id": id, "name": nm, "vend
55699or_id": vid, "background-color": "", "color": "", "image_vc": "", "product_count": 0 });
55700				
55701				jdd.find('option[value="new"]').before(opt);
55702				_plineDD.append(opt);
55703				
55704				_clickBreadcrumbEnd(vid, id, true);
55705			} else if (boxtype === 'u') {
55706				var abbreviation = jdata.attr('abbreviation_vc');
55707				SA.POS.inventory_json.units.push({ "id": id, "name": nm, "abbreviation_vc": abbreviation });
55708				
55709				jdd.find('option[value="new"]').before('<option value="' + id + '" title="' + nm + '">' + abbreviation + '</option>');
55710			} else if (boxtype === 'ct') {
55711				var typeCategoryId = parseInt(jdata.attr('parent_id'));
55712				var typeCategoryName = UTIL.cleanString(jdata.attr('type_category_name_vc'));
55713				
55714				if (typeCategoryName === '') {
55715					typeCategoryName = _conPos.getObject(SA.POS.inventory_json.categories, "id", typeCategoryId).name;
55716				} else {
55717					SA.POS.inventory_json.categories.push({ "id": typeCategoryId, "name": typeCategoryName });
55718				}
55719				
55720				SA.POS.inventory_json.types.push({ "id": id, "name": nm, "category_id": typeCategoryId });
55721				
55722				jdd.find('option[value="new"]').before('<option value="' + id + '">' + typeCategoryName + ' / ' + nm + '</option>');
55723				jdd.find('option[value="' + id + '"]').prop('selected', 'selected');
55724			}
55725            
55726            jdd.val(id).change();
55727		}
55728		
55729		_conPosEdit.saveVendor = function() {
55730			var jpop = $('#pos-popup-brand').closest('.glopop');
55731			var vnm = jpop.find('#Vendor_Name_vc:visible');
55732			
55733			if (vnm.length > 0) {
55734				var vid = jpop.find('#Vendor_id').val();
55735				var jd = { "boxtype": "v", "vendor_id": vid, "vendor_name_vc": vnm.val() };
55736			} else {
55737				var vid = jpop.find('#Existing_Vendor_id').val();
55738				var plid = jpop.find('#Product_Line_id').val();
55739				var plnm = jpop.find('#Product_Line_Name_vc').val();
55740				
55741				var jd = { "boxtype": "pl", "vendor_id": vid, "product_line_id": plid, "product_line_name_vc": plnm };
55742			}
55743			
55744			var jbox = jpop.find('.pos-popup-sample-box .pos-product-box');
55745			jd.background_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("background-color")).replace('rgb(', '').replace(')', ''), ' ', '');		//jpop.find('#pos-background-color').val();
55746			jd.text_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("color")).replace('rgb(', '').replace(')', ''), ' ', '');						//jpop.find('#pos-text-color').val();
55747			jd.file_name_vc = UTIL.cleanString(jpop.find('.sa-upload').attr('file_name_vc'));
55748			
55749			if ('rgb(' + jd.text_color_vc + ')' === _DEFAULT_COLOR) { jd.text_color_vc = ''; }
55750			if ('rgb(' + jd.background_color_vc + ')' === _DEFAULT_BACKGROUND_COLOR) { jd.background_color_vc = ''; }
55751			
55752			var url = GLO.Link.WebsiteDomain + 'pos/Vendor';
55753			var jsave = jpop.find('.btnSave');
55754			GLO.UI.Form.beginProcessing(jsave);
55755			
55756			$.ajax({ "type": "POST", "url": url, "cache": false, data: jd })
55757                .success(function(data, textStatus, jqXHR) {
55758                    GLO.UI.Form.resetProcessing(jsave);
55759                    GLO.Popup.close(jpop);
55760                    
55761                    _saveVendorSuccessful(jd, data);
55762                }).error(function(jqXHR, textStatus, errorThrown) {
55763                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55764                });
55765		}
55766		
55767		_conPosEdit.saveCategory = function() {
55768			var jpop = $('#pos-popup-category').closest('.glopop');
55769			var catnm = jpop.find('#Category_Name_vc:visible');
55770			
55771			if (catnm.length > 0) {
55772				var catid = jpop.find('#Category_id').val();
55773				var jd = { "boxtype": "c", "category_id": catid, "category_name_vc": catnm.val() };
55774			} else {
55775				var catid = jpop.find('#Existing_Category_id').val();
55776				var ctid = jpop.find('#Inventory_Type_id').val();
55777				var ctnm = jpop.find('#Inventory_Type_Name_vc').val();
55778				
55779				var jd = { "boxtype": "ct", "category_id": catid, "inventory_type_id": ctid, "type_name_vc": ctnm };
55780			}
55781			
55782			var jbox = jpop.find('.pos-popup-sample-box .pos-product-box');
55783			jd.background_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("background-color")).replace('rgb(', '').replace(')', ''), ' ', '');		//jpop.find('#pos-background-color').val();
55784			jd.text_color_vc = UTIL.replaceAll(UTIL.cleanString(jbox.css("color")).replace('rgb(', '').replace(')', ''), ' ', '');						//jpop.find('#pos-text-color').val();
55785			jd.file_name_vc = UTIL.cleanString(jpop.find('.sa-upload').attr('file_name_vc'));
55786			
55787			if ('rgb(' + jd.text_color_vc + ')' === _DEFAULT_COLOR) { jd.text_color_vc = ''; }
55788			if ('rgb(' + jd.background_color_vc + ')' === _DEFAULT_BACKGROUND_COLOR) { jd.background_color_vc = ''; }
55789			
55790			var url = GLO.Link.WebsiteDomain + 'pos/Category';
55791			var jsave = jpop.find('.btnSave');
55792			GLO.UI.Form.beginProcessing(jsave);
55793			
55794			$.ajax({ "type": "POST", "url": url, "cache": false, data: jd })
55795                .success(function(data, textStatus, jqXHR) {
55796                    GLO.UI.Form.resetProcessing(jsave);
55797                    GLO.Popup.close(jpop);
55798                    
55799                    _saveCategorySuccessful(jd, data);
55800                }).error(function(jqXHR, textStatus, errorThrown) {
55801                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55802                });
55803		}
55804		
55805		_conPosEdit.saveProduct = function() {
55806			var jpop = $('#pos-popup-product').closest('.glopop');
55807			
55808			var id = UTIL.cleanString(jpop.find('#Inventory_id').val());
55809			var nm = jpop.find('#Name_vc').val();
55810			var vid = UTIL.cleanString(jpop.find('#Existing_Vendor_id').val());
55811			var plid = UTIL.cleanString(jpop.find('#Existing_Product_Line_id').val());
55812			
55813			var price = UTIL.cleanString(jpop.find('#Price_mn').val());
55814			var size = UTIL.cleanString(jpop.find('#Size_dr').val());
55815			var unit = UTIL.cleanString(jpop.find('#Unit_id').val());
55816			
55817			var typeCategory = UTIL.cleanString(jpop.find('#Inventory_Type_id').val());		//var category = jpop.find('#Inventory_Type_id').find('option:selected').attr('category_id');
55818			var upc = UTIL.cleanString(jpop.find('#UPC_vc').val());
55819			var imgFileName = UTIL.cleanString(jpop.find('.sa-upload').attr('file_name_vc'));
55820			
55821			if (!UTIL.isEmpty(typeCategory) && typeCategory.substring(0, 1) === 'c') {
55822				var categoryId = typeCategory.substring(1);
55823				typeCategory = '';
55824			} else {
55825				var categoryId = '';
55826			}
55827			
55828			if (UTIL.isEmpty(nm)) {
55829				new GLO.Popup.Warning(SA.Resource.PleaseEnterProductName, function() { jpop.find('#Name_vc').focus(); });
55830				return;
55831			}
55832			
55833			var jinput = { "inventory_id": id, "name_vc": nm, "vendor_id": vid, "product_line_id": plid, "price_mn": price
55834							, "size_dr": size, "unit_id": unit, "inventory_type_id": typeCategory, "category_id": categoryId
55835							, "upc_vc": upc, "image_vc": imgFileName };
55836			
55837			if (jpop.find('#Not_Taxable_fl').prop('checked')) { jinput.not_taxable_fl = 1; }
55838			
55839			var url = GLO.Link.WebsiteDomain + 'pos/Product';
55840			var jsave = jpop.find('.btnSave');
55841			GLO.UI.Form.beginProcessing(jsave);
55842			
55843			$.ajax({ "type": "POST", "url": url, "cache": false, data: jinput })
55844                .success(function(data, textStatus, jqXHR) {
55845                    GLO.UI.Form.resetProcessing(jsave);
55846                    GLO.Popup.close(jpop);
55847                    
55848                    var jout = $(data);
55849					
55850                    if (UTIL.isNumber(jinput.inventory_id)) {
55851                    	_updateProductSuccessful(jinput, jout);
55852                    } else {
55853                    	_insertProductSuccessful(jinput, jout);
55854                    }
55855                }).error(function(jqXHR, textStatus, errorThrown) {
55856                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
55857                });
55858		}
55859		
55860		function _updateProduct_VendorChanged(product, oldVendorId, newVendorId, oldPLineId, newPLineId) {
55861			if (UTIL.coalesceInt(oldVendorId, -1) === UTIL.coalesceInt(newVendorId, -1)) { return; }
55862			
55863			product.vendor_id = UTIL.cleanString(newVendorId);
55864			var vendor = _conPos.getVendorObject(newVendorId);
55865			
55866			if (vendor) {
55867				++vendor.total_product_count;
55868				
55869				if (UTIL.isEmpty(newPLineId)) { ++vendor.product_count; }
55870			}
55871			
55872			if (_conPos.sortType === 2) {
55873				if (vendor) {
55874					product["background-color"] = UTIL.cleanString(vendor["background-color"]);
55875					product.color = UTIL.cleanString(vendor.color);
55876				} else {
55877					product["background-color"] = product.color = '';
55878				}
55879			}
55880			
55881			var oldVendor = _conPos.getVendorObject(oldVendorId);
55882			
55883			if (oldVendor) {
55884				--oldVendor.total_product_count;
55885				
55886				if (!UTIL.isEmpty(oldPLineId)) {
55887					//--_conPos.getPLineObject(oldPLineId).product_count;					//handled by _updateProduct_PLineChanged()
55888				} else {
55889					--oldVendor.product_count;
55890				}
55891			}
55892		}
55893		
55894		function _updateProduct_PLineChanged(product, newVendorId, oldPLineId, newPlineId) {
55895			if (UTIL.coalesceInt(oldPLineId, -1) === UTIL.coalesceInt(newPlineId, -1)) { return; }
55896			
55897			product.product_line_id = UTIL.cleanString(newPlineId);
55898			
55899			if (newPlineId) {
55900				var pline = _conPos.getPLineObject(newPlineId);
55901				++pline.product_count;
55902				
55903				if (_conPos.sortType === 2) {
55904					var vendor = _conPos.getVendorObject(newVendorId);
55905					
55906					product["background-color"] = UTIL.cleanString(UTIL.coalesce(pline["background-color"], vendor["background-color"]));
55907					product.color = UTIL.cleanString(UTIL.coalesce(pline.color, vendor.color));
55908				}
55909			}
55910			
55911			if (!UTIL.isEmpty(oldPLineId)) {
55912				var pline = _conPos.getPLineObject(oldPLineId);
55913				--pline.product_count;
55914			}
55915		}
55916		
55917		function _updateProduct_CategoryChanged(product, oldCategoryId, newCategoryId, oldTypeId, newTypeId) {
55918			if (UTIL.isEmpty(newCategoryId) && newTypeId) { newCategoryId = _conPos.getObject(SA.POS.inventory_json.types, "id", newTypeId).category_id; }
55919			
55920			if (UTIL.coalesceInt(oldCategoryId, -1) === UTIL.coalesceInt(newCategoryId, -1)) { return; }
55921			
55922			if (newCategoryId) {
55923				var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", newCategoryId);
55924				++category.total_product_count;
55925				
55926				if (UTIL.isEmpty(newTypeId)) { ++category.product_count; }
55927				
55928				product.category_id = newCategoryId;
55929				
55930				if (_conPos.sortType === 1) {
55931					product["background-color"] = UTIL.cleanString(category["background-color"]);
55932					product.color = UTIL.cleanString(category.color);
55933				}
55934			} else {
55935				product.category_id = '';
55936				
55937				if (_conPos.sortType === 1) { product["background-color"] = product.color = ''; }
55938			}
55939			
55940			if (oldCategoryId) {
55941				var oldCategory = _conPos.getObject(SA.POS.inventory_json.categories, "id", oldCategoryId);
55942				--oldCategory.total_product_count;
55943				
55944				if (!UTIL.isEmpty(oldTypeId)) {
55945					--_conPos.getObject(SA.POS.inventory_json.types, "id", oldTypeId).product_count;
55946				} else {
55947					--oldCategory.product_count;
55948				}
55949			}
55950		}
55951		
55952		function _updateProduct_CategoryTypeChanged(product, newCategoryId, oldTypeId, newT
55952ypeId) {
55953			if (UTIL.coalesceInt(oldTypeId, -1) === UTIL.coalesceInt(newTypeId, -1)) { return; }
55954			
55955			product.inventory_type_id = UTIL.cleanString(newTypeId);
55956			
55957			if (newTypeId) {
55958				var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", newTypeId);
55959				++ctype.product_count;
55960				
55961				product.type_name_vc = UTIL.cleanString(ctype.name);
55962				
55963				if (_conPos.sortType === 1) {
55964					var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", newCategoryId);
55965					
55966					product["background-color"] = UTIL.cleanString(UTIL.coalesce(ctype["background-color"], category["background-color"]));
55967					product.color = UTIL.cleanString(UTIL.coalesce(ctype.color, category.color));
55968				}
55969			} else {
55970				product.type_name_vc = '';
55971			}
55972			
55973			if (!UTIL.isEmpty(oldTypeId)) {
55974				var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", oldTypeId);
55975				--ctype.product_count;
55976			}
55977		}
55978		
55979		function _updateProductSuccessful(jinput, jout) {
55980			var inventoryId = parseInt(jout.attr('id'));
55981			var product = _conPos.getProductObject(inventoryId);
55982			
55983			product.label = jinput.name_vc;
55984			product.image_vc = UTIL.cleanString(jinput.image_vc);
55985			
55986			if (UTIL.parseBool(jinput.not_taxable_fl)) { product.tax_rate_pct = 0; } else { delete product.tax_rate_pct; }
55987			
55988			_updateProduct_VendorChanged(product, product.vendor_id, jinput.vendor_id, product.product_line_id, jinput.product_line_id);
55989			_updateProduct_PLineChanged(product, jinput.vendor_id, product.product_line_id, jinput.product_line_id);
55990			
55991			_updateProduct_CategoryChanged(product, product.category_id, jinput.category_id, product.inventory_type_id, jinput.inventory_type_id);
55992			_updateProduct_CategoryTypeChanged(product, jinput.category_id, product.inventory_type_id, jinput.inventory_type_id);
55993			
55994			product.upc_vc = UTIL.cleanString(jinput.upc_vc);
55995			product.size_vc = UTIL.cleanString(jinput.size_dr);
55996			product.price_mn = UTIL.displayMoney(UTIL.cleanString(jinput.price_mn), true);
55997			product.unit_id = UTIL.cleanString(jinput.unit_id);
55998			product.css_class_vc = jout.attr('css_class');
55999			
56000			if (_conPos.sortType === 2) {							//add box to UI (if matches current filter)
56001				_clickBreadcrumbEnd(product.vendor_id, product.product_line_id, true);
56002			} else {
56003				_clickBreadcrumbEnd(product.category_id, product.inventory_type_id, true);
56004			}
56005		}
56006		
56007		function _insertProductSuccessful(jinput, jout) {
56008			var plid = UTIL.cleanString(jinput.product_line_id);
56009			var inventoryId = parseInt(jout.attr('id'));
56010			
56011			var json = { "id": inventoryId, "label": jout.attr('name'), "css_class_vc": jout.attr('css_class') };
56012			
56013			if (jinput.vendor_id) {
56014				json.vendor_id = parseInt(jinput.vendor_id);
56015				
56016				var vendor = _conPos.getVendorObject(jinput.vendor_id);
56017				++vendor.total_product_count;
56018				
56019				if (vendor["background-color"]) { json["background-color"] = vendor["background-color"]; }
56020				if (vendor.color) { json.color = vendor.color; }
56021				
56022				if (jinput.product_line_id) {
56023					json.product_line_id = plid;
56024					var pline = _conPos.getPLineObject(plid);
56025					
56026					json["background-color"] = pline["background-color"];
56027					if (jinput.color) { json.color = pline.color; }
56028					
56029					++pline.product_count;
56030				} else {
56031					++vendor.product_count;
56032				}
56033			}
56034			
56035			if (jinput.upc_vc) { json.upc_vc = jinput.upc_vc; }
56036			if (jinput.size_dr) { json.size_vc = jinput.size_dr; }
56037			if (jinput.price_mn) { json.price_mn = UTIL.displayMoney(jinput.price_mn, true); }
56038			if (jinput.unit_id) { json.unit_id = jinput.unit_id; }
56039			
56040			if (UTIL.isNumber(jinput.inventory_type_id)) {
56041				json.inventory_type_id = parseInt(jinput.inventory_type_id);
56042				json.category_id = '';
56043				
56044				var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", json.inventory_type_id);
56045				++ctype.product_count;
56046				++_conPos.getObject(SA.POS.inventory_json.categories, "id", ctype.category_id).total_product_count;
56047			} else if (UTIL.isNumber(jinput.category_id)) {
56048				json.inventory_type_id = '';
56049				json.category_id = parseInt(jinput.category_id);
56050				
56051				var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", json.category_id);
56052				++category.product_count;
56053				++category.total_product_count;
56054			} else {
56055				json.inventory_type_id = json.category_id = '';
56056			}
56057			
56058			if (jinput.image_vc) { json.image_vc = jinput.image_vc; }
56059			if (UTIL.parseBool(jinput.not_taxable_fl)) { json.tax_rate_pct = 0; } else { delete json.tax_rate_pct; }
56060			
56061			SA.POS.inventory_json.products.push(json);
56062			
56063			if (_conPos.sortType === 2) {							//add box to UI (if matches current filter)
56064				_clickBreadcrumbEnd(json.vendor_id, plid, true);
56065			} else {
56066				_clickBreadcrumbEnd(json.category_id, json.inventory_type_id, true);
56067			}
56068		}
56069		
56070		function _saveVendorSuccessful(jsonIn, dataOut) {			//applies to saving vendors + plines.
56071			var j = $(dataOut);
56072			var vid = parseInt(j.attr('vendor_id'));
56073			
56074			if (jsonIn.boxtype === 'v') {
56075				if (UTIL.isEmpty(jsonIn.vendor_id)) {				//= is add.
56076					var vendor = { "id": vid, "product_line_count": 0, "product_count": 0, "total_product_count": 0 };
56077					SA.POS.inventory_json.vendors.push(vendor);
56078				} else {
56079					var vendor = _conPos.getVendorObject(vid);
56080				}
56081				
56082				_checkColorChange(vendor.color, jsonIn.text_color_vc, vendor["background-color"], jsonIn.background_color_vc);
56083				
56084				vendor.name = j.attr('vendor_name_vc');
56085				vendor["background-color"] = jsonIn.background_color_vc;
56086				vendor.color = jsonIn.text_color_vc;
56087				vendor.image_vc = jsonIn.file_name_vc;
56088				vendor.css_class_vc = j.attr('css_class');
56089			} else {
56090				if (UTIL.isEmpty(jsonIn.product_line_id)) {
56091					var pline = { "id": parseInt(j.attr('product_line_id')), "product_count": 0 };
56092					SA.POS.inventory_json.product_lines.push(pline);
56093				} else {
56094					var pline = _conPos.getPLineObject(j.attr('product_line_id'));
56095				}
56096				
56097				_checkPLineChangedVendor(jsonIn.product_line_id, pline.product_line_id, pline.vendor_id, vid);
56098				
56099				pline.name = j.attr('product_line_name_vc');
56100				pline.vendor_id = vid;
56101				
56102				_checkColorChange(pline.color, jsonIn.text_color_vc, pline["background-color"], jsonIn.background_color_vc);
56103				
56104				pline["background-color"] = jsonIn.background_color_vc;
56105				pline.color = jsonIn.text_color_vc;
56106				pline.image_vc = jsonIn.file_name_vc;
56107				pline.css_class_vc = j.attr('css_class');
56108			}
56109			
56110			_clickBreadcrumbEnd(null, null, true);				//add box to UI (if matches current filter)
56111		}
56112		
56113		function _saveCategorySuccessful(jsonIn, dataOut) {			//applies to saving category + category-type.
56114			var j = $(dataOut);
56115			var catid = parseInt(j.attr('category_id'));
56116			
56117			if (jsonIn.boxtype === 'c') {
56118				if (UTIL.isEmpty(jsonIn.category_id)) {				//= is add.
56119					var category = { "id": catid, "type_count": 0, "product_count": 0, "total_product_count": 0 };
56120					SA.POS.inventory_json.categories.push(category);
56121				} else {
56122					var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", catid);
56123				}
56124				
56125				_checkColorChange(category.color, jsonIn.text_color_vc, category["background-color"], jsonIn.background_color_vc);
56126				
56127				category.name = j.attr('category_name_vc');
56128				category["background-color"] = jsonIn.background_color_vc;
56129				category.color = jsonIn.text_color_vc;
56130				category.image_vc = jsonIn.file_name_vc;
56131				category.css_class_vc = j.attr('css_class');
56132			} else {
56133				if (UTIL.isEmpty(jsonIn.inventory_type_id)) {
56134					var ctype = { "id": parseInt(j.attr('inventory_type_id')), "product_count": 0 };
56135					SA.POS.inventory_json.types.push(ctype);
56136				} else {
56137					var ctype = _conPos.getObject(SA.POS.inventory_json.types, "id", j.attr('inventory_type_id'));
56138				}
56139				
56140				_checkTypeChangedCategory(jsonIn.inventory_type_id, ctype.id, jsonIn.category_id, catid);
56141				
56142				ctype.name = j.attr('type_name_vc');
56143				ctype.category_id = catid;
56144				
56145				_checkColorChange(ctype.color, jsonIn.text_color_vc, ctype["background-color"], jsonIn.background_color_vc);
56146				
56147				ctype["background-color"] = jsonIn.background_color_vc;
56148				ctype.color = jsonIn.text_color_vc;
56149				ctype.image_vc = jsonIn.file_name_vc;
56150				ctype.css_class_vc = j.attr('css_class');
56151			}
56152			
56153			_clickBreadcrumbEnd(null, null, true);				//add box to UI (if matches current filter)
56154		}
56155		
56156		function _checkPLineChangedVendor(oldPLineId, newPLineId, oldVendorId, newVendorId) {
56157			if (UTIL.coalesceInt(oldVendorId, -1) !== UTIL.coalesceInt(newVendorId, -1)) {
56158				var vendor = _conPos.getVendorObject(oldVendorId);
56159				if (vendor) { --vendor.product_line_count; }
56160				
56161				vendor = _conPos.getVendorObject(newVendorId);
56162				if (vendor) { ++vendor.product_line_count; }
56163			}
56164		}
56165		
56166		function _checkTypeChangedCategory(oldTypeId, newTypeId, oldCategoryId, newCategoryId) {
56167			if (UTIL.coalesceInt(oldCategoryId, -1) !== UTIL.coalesceInt(newCategoryId, -1)) {
56168				var category = _conPos.getObject(SA.POS.inventory_json.categories, "id", oldCategoryId);
56169				if (category) { --category.type_count; }
56170				
56171				category = _conPos.getObject(SA.POS.inventory_json.categories, "id", newCategoryId);
56172				if (category) { ++category.type_count; }
56173			}
56174		}
56175		
56176		function _checkColorChange(initialColor, newColor, initialBColor, newBColor) {			//= if change vendor or pline color need to refresh products with new color (toDo: later do this via JS).
56177			if ('rgb(' + initialColor + ')' === _DEFAULT_COLOR) { initialColor = ''; }
56178			if ('rgb(' + initialBColor + ')' === _DEFAULT_BACKGROUND_COLOR) { initialBColor = ''; }
56179			
56180			if (UTIL.cleanString(initialColor) !== newColor || UTIL.cleanString(initialBColor) !== newBColor) {
56181				_conPosEdit.refreshData();			//document.location = GLO.Link.WebsiteDomain + 'pos?edit=true';				//location.reload();
56182			}
56183		}
56184		
56185		_conPosEdit.clickBreadcrumbEnd = function(grandId, parentId, isSystemReset) {
56186			_clickBreadcrumbEnd(grandId, parentId, isSystemReset);
56187		}
56188		
56189		function _clickBreadcrumbEnd(grandId, parentId, isCloseEditPopup) {
56190			var jbread = $('#pos-product-header-breadcrumb');
56191			var jwindow = $('#pos-product-window');
56192			
56193			if (_conPos.sortType === 2) {
56194				parentId = UTIL.coalesce(parentId, jbread.find('#pos-breadcrumb-pline').attr('product_line_id'));
56195				grandId  = UTIL.coalesce(grandId,  jbread.find('#pos-breadcrumb-vendor').attr('vendor_id'));
56196			} else {
56197				parentId = UTIL.coalesce(parentId, jbread.find('#pos-breadcrumb-category-type').attr('inventory_type_id'));
56198				grandId = UTIL.coalesce(grandId, jbread.find('#pos-breadcrumb-category').attr('category_id'));
56199			}
56200			
56201			SA.POS.filterBoxesHome(null, isCloseEditPopup);
56202			
56203			if (_conPos.sortType === 2) {
56204				if (UTIL.isNumber(grandId)) {
56205					GLO.UI.click(jwindow, 'div[box_type="v"][vendor_id="' + grandId + '"]');
56206				}
56207				
56208				if (UTIL.isNumber(parentId)) {
56209					GLO.Popup.closeIfExist($('.pos-popup-box').closest('.glopop'));
56210					GLO.UI.click(jwindow, 'div[box_type="pl"][product_line_id="' + parentId + '"]');
56211				}
56212			} else {
56213				if (UTIL.isNumber(grandId)) {
56214					GLO.UI.click(jwindow, 'div[box_type="c"][category_id="' + grandId + '"]');
56215				}
56216				
56217				if (UTIL.isNumber(parentId)) {
56218					GLO.Popup.closeIfExist($('.pos-popup-box').closest('.glopop'));
56219					GLO.UI.click(jwindow, 'div[box_type="ct"][inventory_type_id="' + parentId + '"]');
56220				}
56221			}
56222			
56223			if (isCloseEditPopup) {
56224				GLO.Popup.closeIfExist($('.pos-popup-box').closest('.glopop'));
56225			}
56226		}
56227		
56228		_conPosEdit.changeDisplayTicketPanel = function() {
56229			var url = GLO.Link.WebsiteDomain + 'pos/HideTicketPanel';
56230			var displayPanel = $('#pos-ticket-edit-mode').find(':radio[name="POS_Edit_Ticket_Panel_Display"]:checked').attr('id');
56231			var jpanel = $('#pos-panel-client');
56232			
56233			if (displayPanel == 'POS_Edit_Ticket_Panel_Hide_This_Device') {
56234				jpanel.addClass('hideX');
56235				UTIL.setCookie('hide_ticket_panel_fl', '1');
56236				
56237				var successMsg = '<p>POS Ticket Panel (right-side of POS Screen) is now <b>Hidden on This Device</b></p>';
56238				GLO.Popup.Success.open(successMsg, 'POS Ticket Panel');
56239				return;
56240			} else if (displayPanel == 'POS_Edit_Ticket_Panel_Hide') {
56241				jpanel.addClass('hideX');
56242				UTIL.setCookieWithExpire('hide_ticket_panel_fl', null);
56243				url += '?hide=1';
56244				
56245				var successMsg = '<p>POS Ticket Panel (right-side of POS Screen) is now <b>Hidden</b></p>';
56246			} else if (displayPanel == 'POS_Edit_Ticket_Panel_Display') {
56247				jpanel.removeClass('hideX');
56248				UTIL.setCookieWithExpire('hide_ticket_panel_fl', null);
56249				url += '?hide=0';
56250				
56251				var successMsg = '<p>POS Ticket Panel (right-side of POS Screen) is now <b>Displayed</b></p>';
56252			}
56253			
56254			UI.addProcessingLayer();
56255			
56256			$.ajax({ "type": "POST", "url": url, "cache": false })
56257                .success(function(data, textStatus, jqXHR) {
56258                    UI.removeProcessingLayer();
56259                    GLO.Popup.Success.open(successMsg, 'POS Ticket Panel');
56260                }).error(function(jqXHR, textStatus, errorThrown) {
56261                    UI.removeProcessingLayer();
56262                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
56263                });
56264		}
56265		_conPosEdit.changeUseServiceImages = function(element) {
56266			if (element.checked) {
56267				var isUseServiceImages = 1;
56268			} else {
56269				var isUseServiceImages = 0;
56270			}
56271			
56272			var url = GLO.Link.WebsiteDomain + 'pos/UseServiceImage';
56273			var jd = { "use_service_image_fl": isUseServiceImages };
56274			
56275			UI.addProcessingLayer();
56276			
56277			$.ajax({ "type": "POST", "url": url, "cache": false, data: jd })
56278                .success(function(data, textStatus, jqXHR) {
56279                    UI.removeProcessingLayer();
56280                    
56281                    _conPos.inventory_json.use_service_image_fl = isUseServiceImages;
56282                    SA.POS.toggleList('services');
56283                }).error(function(jqXHR, textStatus, errorThrown) {
56284                    UI.removeProcessingLayer();
56285                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
56286                });
56287		}
56288		_conPosEdit.changeSortTypeService = function(element) {
56289			var url = GLO.Link.WebsiteDomain + 'pos/SortTypeService';
56290			var jd = { "sort_type_cd": element.value };
56291			var jcontainer = $('#pos-container');
56292			
56293			if (jd.sort_type_cd == 10) {
56294				jcontainer.removeClass('service-sort-custom');
56295			} else {
56296				jcontainer.addClass('service-sort-custom');
56297			}
56298			
56299			UI.addProcessingLayer();
56300			
56301			$.ajax({ "type": "POST", "url": url, "cache": false, data: jd })
56302                .success(function(data, textStatus, jqXHR) {
56303                    UI.removeProcessingLayer();
56304                    
56305                    var json = jQuery.parseJSON(data);
56306                    //json.no_toggle_menu_fl = true;
56307                }).error(function(jqXHR, textStatus, errorThrown) {
56308                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
56309                    UI.removeProcessingLayer();
56310                });
56311		}
56312		_conPosEdit.changeSortTypeProduct = function(element) {
56313			var url = GLO.Link.WebsiteDomain + 'pos/SortTypeProduct';
56314			var jd = { "sort_type_cd": element.value }
56315			UI.addProcessingLayer();
56316			
56317			$.ajax({ "type": "POST", "url": url, "cache": false, data: jd, dataType: "json" })
56318                .success(function(data, textStatus, jqXHR) {
56319                    UI.removeProcessingLayer();
56320                    
56321                    var json = jQuery.parseJSON(data);
56322                    //json.no_toggle_menu_fl = true;
56323                    
56324                    _conPos.init(json);
56325                    _conPos.filterBoxesHome();
56326                }).error(function(jqXHR, textStatus, errorThrown) {
56327                    GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
56328                    UI.removeProcessingLayer();
56329                });
56330		}
56331		_conPosEdit.reloadChanges = function() {
56332			GLO.UI.Form.beginProcessing($('#btnPosEditReloadChanges'));
56333			
56334			setTimeout(function() {
56335				location.reload();
56336			}, 150);
56337		}
56338		
56339		_conPosEdit.refreshData = function() {
56340			var url = GLO.Link.WebsiteDomain + 'pos/RefreshData';
56341			UI.addProcessingLayer();
56342			
56343			$.ajax({ "type": "GET", "url": url, "cache": false, dataType: "json" })
56344                .success(function(data, textStatus, jqXHR) {
56345                    UI.removeProcessingLayer();
56346                    var json = jQuery.parseJSON(data);
56347                    json.no_toggle_menu_fl = true;
56348                    
56349                    _conPos.init(json);
56350                    _clickBreadcrumbEnd(null, null, true);							//_conPos.filterBoxesHome();
56351                }).error(function(jqXHR, textStatus, errorThrown) {
56352                    //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
56353                    UI.removeProcessingLayer();
56354                });
56355		}
56356		
56357		_conPosEdit.imageUploadComplete = function(jupload, fileName, imgid, imgSize) {
56358			var img = 'url("' + GLO.Data.cdnDirectory + 'upload-folder/' + fileName + '")';
56359			var jpop = jupload.closest('.glopop');
56360			var jbox = null;
56361			
56362			jpop.find('.upload-preview').css({ "background-image": img });
56363			jpop.find('.sa-upload').attr('file_name_vc', fileName);
56364			
56365			if (jpop.find('#pos-popup-brand').length === 1) {
56366				var plid = jpop.find('#Product_Line_id').val();
56367				var vid = jpop.find('#Vendor_id').val();
56368				
56369				if (imgid == plid) {
56370					jbox = _conPos.getPLineObject(plid);
56371				} else if (imgid == vid) {
56372					jbox = _conPos.getVendorObject(vid);
56373				}
56374			} else if (jpop.find('#pos-popup-category').length === 1) {
56375				var tid = jpop.find('#Inventory_Type_id').val();
56376				var ctid = jpop.find('#Category_id').val();
56377				
56378				if (imgid == tid) {
56379					jbox = _conPos.getObject(SA.POS.inventory_json.types, "id", tid);
56380				} else if (imgid == ctid) {
56381					jbox = _conPos.getObject(SA.POS.inventory_json.categories, "id", ctid);
56382				}
56383			} else if (jpop.find('#pos-popup-product').length === 1) {
56384				var iid = jpop.find('#Inventory_id').val();
56385				
56386				if (imgid == iid) {
56387					jbox = _conPos.getProductObject(iid);
56388				}
56389			}
56390			
56391			if (jbox !== null) {
56392				$('#pos-header-edit-box').find('.pos-product-box').css({ "background-image": img });
56393				jbox.image_vc = fileName;
56394				
56395				jpop.find('.pos-popup-box').addClass('edit-image');
56396				_clickBreadcrumbEnd(null, null, true);
56397			}
56398		}
56399		
56400		_conPosEdit.openHelp = function() {
56401			if (!$('#pos-container').hasClass('edit-pos')) {
56402				SA.POS.Edit.changeMode();
56403			}
56404			
56405			GLO.Popup.closeIfExist($('#pop-pos-edit-help').closest('.glopop'));
56406			GLO.Popup.closeIfExist($('#pop-pos-help').closest('.glopop'));
56407			
56408			var arrow = '<b class="arrow-right">&#10140;</b>';
56409			var htmContact = '<h5 id="pop-pos-contact-sa" onclick="GLO.Log.openContactSAPopup(null, null, null, true)"> <i>Contact</i> ' + GLO.Info.getScheduleAnyoneHtm(true) + '</h5>';
56410			var msgServiceCustomDisclaimer = '';
56411			
56412			if (innerWidth < 1500) {
56413				msgServiceCustomDisclaimer = ' <b class="narrow-text" style="padding: 2px 4px; border-radius: 4px; background-color: yellow;">requires minimum screen width of 1500px, your screen width is: ' + innerWidth + 'px</b>';
56414			}
56415			
56416			var hService = '<h3>Sort + Customize Services</h3>'
56417			var aProfileService = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/4\', this, null, true)">Profile ' + arrow + ' Services</a>'
56418			var msgServiceAuto = '<p>Can use the <b class="narrow-text">Automatic</b> sorting of services <i class="narrow-text">(setup at ' + aProfileService + ')</i>';
56419			var msgServiceCustom = '<p>Can further <b class="narrow-text">Customize</b> the layout of services using <b class="narrow-text">Custom Service Layout</b>' + msgServiceCustomDisclaimer + '</p>';
56420			
56421			var htmServiceColor = '<p>Click any service to change the color and image <i class="narrow-text">the service icon or thumbnail image is used from the service gallery</i></p>';
56422			var htmServiceSort = '<p>' + msgServiceAuto + msgServiceCustom + '</p>';
56423			var htmServiceSort2 = '<p>When <b class="narrow-text">Custom Service Layout</b> selected can grab <b class="narrow-text">top-left</b> of any service and drag it to the desired location</p>';
56424			var htmService = hService + htmServiceSort + htmServiceSort2 + htmServiceColor;
56425			
56426			var hProduct = '<h3>Sort + Customize Products</h3>'
56427			var msgCategoryList = '<i class="narrow-text">(Shampoo, Conditioner, Cutical Oil, Massage Oil, etc..)</i>';
56428			var msgProductSortBrand = 'Can sort products by <b class="narrow-text">Brand</b> <i class="narrow-text">(like Keven Murphy, OPI, Keratase, etc)</i>';
56429			var msgProductSortCategory = ' <span style="white-space: nowrap;">or <b class="narrow-text">Category</b> ' + msgCategoryList;
56430			var htmProductSort = '<p>' + msgProductSortBrand + msgProductSortCategory + '</p>';
56431			
56432			var htmProductColor = '<p>Click any product to change the color and image</p>';
56433			var htmProductCustomize = '<p>Can also create/edit product brands, product lines, categories, and sub-categories</p>';
56434			
56435			var onclickProductNew = ' onclick="GLO.Uri.gotoUriWithSpinner(\'provider/inventory#action=new-product\', this, null, true)"';
56436			var aProductNew = '<a class="narrow-text"' + onclickProductNew + '>Manage Inventory ' + arrow + ' Create ' + arrow + ' Product</a>';
56437			var htmProductNew = '<p>To create a new product available to sell in the P.O.S. go to ' + aProductNew + '</p>';
56438			
56439			var htmProduct = hProduct + htmProductSort + htmProductColor + htmProductCustomize + htmProductNew;
56440			
56441			var hStaff = '<h3>Sort + Customize Staff</h3>';
56442			
56443			var btnSortStaff = '<span class="btnAdd"> <a onclick="GLO.RunningTotal.OrderCalendar.openPopup()"><b style="color: inherit;">Staff Order</b></a> </span>';
56444			var helpSortStaff = '<span class="helpIcon2 sa-sprite" onclick="GLO.Provider.Advanced.Help.C
56444alendar.openStaffOrder()" title=""></span>';
56445			var msgSortStaff = 'Staff sorted by arrival time <i class="narrow-text">(clock-in time or scheduled start time)</i>'
56446					+ ', if staff arrive at same time <i class="narrow-text">(+ do NOT clock-in)</i> uses ';
56447			var htmSortStaff = '<p>' + msgSortStaff + btnSortStaff + helpSortStaff + '</p>';
56448			
56449			var urlProfileStaffGallery = GLO.Data.provider.urikey + '/gallery/Staff/edit?imgsize=thumb';
56450			var labelProfileStaffGallery = 'Profile ' + arrow + ' Website ' + arrow + ' Staff Gallery';
56451			var aProfileStaffGallery = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'' + urlProfileStaffGallery + '\', this, null, true)">' + labelProfileStaffGallery + '</a>';
56452			var htmProfileStaffGallery = '<p style="margin: 16px 0;">Can add staff images to the P.O.S. Screen by going to ' + aProfileStaffGallery + ' and uploading an icon or thumbnail image for each staff</p>';
56453			
56454			var labelProfileStaff = 'Profile ' + arrow + ' Staff';
56455			var aProfileStaff = '<a class="narrow-text" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/profile/5\', this, null, true)">' + labelProfileStaff + '</a>';
56456			var htmProfileStaff = '<p>Can change staff card background color go to ' + aProfileStaff + ' and press the staff name then in staff popup ' + arrow + ' press the color wheel</p>';
56457			
56458			var htmStaff = hStaff + htmSortStaff + htmProfileStaffGallery + htmProfileStaff;
56459			
56460			var htm = '<div id="pop-pos-edit-help">' + htmContact + htmService + htmProduct + htmStaff + '</div>';
56461			var h1 = GLO.Info.getScheduleAnyoneHtm(true) + ' Customize P.O.S. Screen';
56462			var jpop = GLO.Popup.Custom.openSimple(htm, h1).addClass('pop-pos');
56463			
56464			jpop.find('h1').css({ "background-color": "darkmagenta" });
56465	    	GLO.Popup.Custom.singleButton(jpop, 'Close');
56466		}
56467		
56468		return _conPosEdit;
56469    })();
56470    
56471    return _conPos;
56472})();
56473
56474SA.POS.PAX = (function() {
56475	//default
56476	var paxApiSvcBaseUrl = 'http://localhost:9000/';
56477	var COMPorts;
56478	var paxDevices;
56479	var uuid;
56480	var osVersion;
56481	var _jpopAddPaxWifiDevice;
56482
56483	function _pax(paxapiurl) {
56484		paxApiSvcBaseUrl = paxapiurl;
56485	 }
56486
56487	 _pax.init = function(deviceId) {
56488		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56489		if (paxDeviceId == "") {
56490			if (deviceId == "") {
56491				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56492				return;
56493			}
56494			else {
56495				paxDeviceId = deviceId;
56496			}
56497		}
56498
56499    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getinitrequest/' + paxDeviceId;
56500
56501        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56502            .success(function(data, textStatus, jqXHR) {
56503                window.onbeforeunload = null;
56504                // GLO.UI.Form.resetProcessing(); 		
56505				var jsonMR = JSON.stringify(data);
56506            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56507            })
56508            .error(function(jqXHR, textStatus, errorThrown) {
56509                GLO.UI.Form.resetProcessing(); 		
56510                new GLO.Popup.Error('Unable to get GETVAR request');
56511            });
56512
56513	 }
56514	
56515	 //get the merchantId and TSYS deviceId associated with device
56516	_pax.getvar = function(deviceId) {
56517		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56518		if (paxDeviceId == "") {
56519			if (deviceId == "") {
56520				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56521				return;
56522			}
56523			else {
56524				paxDeviceId = deviceId;
56525			}
56526		}
56527
56528    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getgetvarrequest/' + paxDeviceId;
56529
56530        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56531            .success(function(data, textStatus, jqXHR) {
56532                window.onbeforeunload = null;
56533				var jsonMR = JSON.stringify(data);
56534            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56535            })
56536            .error(function(jqXHR, textStatus, errorThrown) {
56537                GLO.UI.Form.resetProcessing(); 		
56538                new GLO.Popup.Error('Unable to get GETVAR request');
56539            });
56540	}
56541
56542	//link device with merchantId 
56543	_pax.setvar = function(deviceId) {
56544		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56545		if (paxDeviceId == "") {
56546			if (deviceId == "") {
56547				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56548				return;
56549			}
56550			else {
56551				paxDeviceId = deviceId;
56552			}
56553		}
56554    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getsetvarrequest/' + paxDeviceId;
56555
56556        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56557            .success(function(data, textStatus, jqXHR) {
56558				window.onbeforeunload = null;
56559				
56560				var jsonMR = JSON.stringify(data);
56561				_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56562				setTimeout(_pax.updateimage(paxDeviceId), 5000);
56563            })
56564            .error(function(jqXHR, textStatus, errorThrown) {
56565                new GLO.Popup.Error('Unable to get SETVAR request');
56566            });
56567	}
56568
56569	_pax.updateimage = function(deviceId) {
56570		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56571		if (paxDeviceId == "") {
56572			if (deviceId == "") {
56573				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56574				return;
56575			}
56576			else {
56577				paxDeviceId = deviceId;
56578			}
56579		}
56580    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getupdateimagerequest/' + paxDeviceId;
56581
56582        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56583            .success(function(data, textStatus, jqXHR) {
56584				window.onbeforeunload = null;
56585				
56586				var jsonMR = JSON.stringify(data);
56587            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56588            })
56589            .error(function(jqXHR, textStatus, errorThrown) {
56590                new GLO.Popup.Error('Unable to get UPDATEIMAGE request');
56591            });
56592	}
56593
56594	//clear screen message
56595	_pax.reset = function(deviceId) {
56596
56597		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56598		if (paxDeviceId == "") {
56599			if (deviceId == "") {
56600				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56601				return;
56602			}
56603			else {
56604				paxDeviceId = deviceId;
56605			}
56606		}
56607    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getresetrequest/' + paxDeviceId;
56608
56609        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56610            .success(function(data, textStatus, jqXHR) {
56611				window.onbeforeunload = null;
56612				
56613				var jsonMR = JSON.stringify(data);
56614            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56615            })
56616            .error(function(jqXHR, textStatus, errorThrown) {
56617                new GLO.Popup.Error('Unable to get RESET request');
56618            });
56619	}
56620
56621	//reboot the device
56622	_pax.reboot = function(deviceId) {
56623    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getrebootrequest/' + deviceId;
56624
56625        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56626            .success(function(data, textStatus, jqXHR) {
56627				window.onbeforeunload = null;
56628				
56629				var jsonMR = JSON.stringify(data);
56630            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56631            })
56632            .error(function(jqXHR, textStatus, errorThrown) {
56633                new GLO.Popup.Error('Unable to get REBOOT request');
56634            });
56635	}
56636	
56637	function _getAuthUrl(isCredit, deviceId, isSale, cid, smid, scid, amount, tip) {
56638		if (isCredit) {
56639			var authType = 'credit';
56640		} else {
56641			var authType = 'debit';
56642		}
56643		
56644		var url = GLO.Link.WebsiteDomain + 'api/PAX/get' + authType + 'authrequest/' + deviceId + '?isSale=' + isSale + '&cid=' + cid;
56645		
56646		if (scid) {
56647			url += '&scid=' + scid;
56648		}
56649		
56650		return url + '&smid=' + UTIL.coalesceString(smid, '0') + '&amount=' + amount + '&tip=' + UTIL.coalesceMoney(tip);
56651	}
56652
56653	_pax.getprepaydialog = function(deviceId) {
56654		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56655		if (paxDeviceId == "") {
56656			if (deviceId == "") {
56657				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56658				return;
56659			}
56660			else {
56661				paxDeviceId = deviceId;
56662			}
56663		}
56664
56665    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/getprepaymentdialogrequest/' + paxDeviceId;
56666
56667        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56668            .success(function(data, textStatus, jqXHR) {
56669                window.onbeforeunload = null;
56670				var jsonMR = JSON.stringify(data);
56671            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56672            })
56673            .error(function(jqXHR, textStatus, errorThrown) {
56674                GLO.UI.Form.resetProcessing(); 		
56675                new GLO.Popup.Error('Unable to get SHOWDIALOG request');
56676            });
56677	}
56678	
56679	_pax.gettipdialog = function(deviceId) {
56680		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
56681		if (paxDeviceId == "") {
56682			if (deviceId == "") {
56683				new GLO.Popup.Error('Unable to find device. Please make sure device is connected.');
56684				return;
56685			}
56686			else {
56687				paxDeviceId = deviceId;
56688			}
56689		}
56690
56691    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/gettipdialogrequest/' + paxDeviceId;
56692
56693        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56694            .success(function(data, textStatus, jqXHR) {
56695                window.onbeforeunload = null;
56696				var jsonMR = JSON.stringify(data);
56697            	_pax.postManageRequestToPAXApi(jsonMR,paxDeviceId);
56698            })
56699            .error(function(jqXHR, textStatus, errorThrown) {
56700                GLO.UI.Form.resetProcessing(); 		
56701                new GLO.Popup.Error('Unable to get SHOWDIALOG request');
56702            });
56703	}
56704
56705	_pax.creditauth = function(deviceId, isSale, cid, smid, scid, amount, tip) {
56706    	var uri = _getAuthUrl(true, deviceId, isSale, cid, smid, scid, amount, tip);
56707    	
56708        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56709            .success(function(data, textStatus, jqXHR) {
56710				window.onbeforeunload = null;
56711				
56712				var jsonPR = JSON.stringify(data);
56713            	_pax.postPaymentRequestToPAXApi(jsonPR, deviceId, isSale, cid, smid, scid, amount);
56714            })
56715            .error(function(jqXHR, textStatus, errorThrown) {
56716                _displayEmvCommunicateError('Unable to connect to payment device', null, false);
56717                
56718                /*
56719                setTimeout(function() {
56720                	var jwarn = $('#pop-warn-emv-communicate').closest('.glopop');
56721                	
56722                	if (jwarn.length) {
56723	                	GLO.Popup.close(jwarn);
56724                	}
56725                	
56726                	UserPortal.Price.Payment.openCreditCard();
56727                }, 2500);
56728                */
56729            });
56730	}
56731
56732	_pax.debitauth = function(deviceId, isSale, cid, smid, scid, amount, tip) {
56733    	var uri = _getAuthUrl(false, deviceId, isSale, cid, smid, scid, amount, tip);
56734    	
56735        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
56736            .success(function(data, textStatus, jqXHR) {
56737				window.onbeforeunload = null;
56738				
56739				var jsonPR = JSON.stringify(data);
56740            	_pax.postPaymentRequestToPAXApi(jsonPR, deviceId, isSale, cid, smid, scid, amount);
56741            })
56742            .error(function(jqXHR, textStatus, errorThrown) {
56743                _displayEmvCommunicateError('Unable to get DEBIT AUTH request', null, true);
56744            });
56745	}
56746	//cancel transaction in progess
56747	_pax.canceltrans = function(deviceId) {
56748		_pax.postCancelTransToPAXApi();
56749	}
56750	//get devices on terminal's serial port
56751	_pax.getCOMPortsFromPAXApi = function(paxMacAddr, _callback) {
56752    	var uri = paxApiSvcBaseUrl + 'api/PAX/portinfo?mac=' + paxMacAddr;
56753
56754        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, contentType: "application/json" })
56755            .success(function(data, textStatus, jqXHR) {
56756                window.onbeforeunload = null;
56757				//call pax api
56758				//COMPorts = data;
56759				if (data.length > 0) {
56760					COMPorts = new Array(0);
56761					for (var i = 0; i < data.length; i++) {
56762						var COMPort = {
56763							"Name":data[i].Name,
56764							"Port":data[i].Port,
56765							"Direction":data[i].Direction,
56766							"TerminalUniqueId": SA.POS.PAX.uuid,
56767							"OSVersion":SA.POS.PAX.osVersion,
56768							"token":"",
56769							"IPAddress":"",
56770							"MacAddress":""
56771						};
56772						COMPorts.push(COMPort);
56773					}
56774				}
56775
56776            	return _callback(COMPorts);
56777
56778            })
56779            .error(function(jqXHR, textStatus, errorThrown) {
56780                new GLO.Popup.Error('No payment devices found');
56781			});	
56782	}
56783
56784	
56785	_pax.clearPAXDevice = function() {
56786		document.cookie = 'paxdevice=; Max-Age=0; path=/; domain=' + location.host;
56787		setTimeout(function() {
56788			location.reload();
56789		}, 3100);
56790	}
56791
56792	_pax.openAddWifiDevice = function() {
56793		if (UTIL.isEmpty(_jpopAddPaxWifiDevice)) {
56794			_jpopAddPaxWifiDevice = $('#pax-wifi-setup').outerHTML();
56795			$('#pax-wifi-setup').remove();
56796		}
56797		
56798		
56799		var jpop = GLO.Popup.Custom.openSimple(_jpopAddPaxWifiDevice, 'Connect Wifi Device', function () { return SA.POS.PAX.savePaxWifiDevice(); });
56800		
56801	}
56802
56803	_pax.getWifiDevices = function(_callback) {
56804    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/GetPaxDevices';
56805
56806        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, contentType: "application/json" })
56807            .success(function(data, textStatus, jqXHR) {
56808                window.onbeforeunload = null;
56809				//call pax api
56810				//paxDevices = data;
56811
56812				if (data.length > 0) {
56813					if ((typeof(paxDevices) == 'undefined') || (paxDevices == null)) { paxDevices = new Array(0); }
56814					for (var i = 0; i < data.length; i++) {
56815						if (data[i].IPAddress !== '') {
56816							var COMPort = {
56817								"Name":data[i].DeviceName,
56818								"Port":"",
56819								"Direction":"",
56820								"TerminalUniqueId": SA.POS.PAX.uuid,
56821								"OSVersion":SA.POS.PAX.osVersion,
56822								"token":"",
56823								"IPAddress":data[i].IPAddress,
56824								"MacAddress":""
56825							};
56826							paxDevices.push(COMPort);
56827						}
56828
56829					}
56830				}
56831				//console.log(data);
56832            	return _callback(paxDevices);
56833
56834            })
56835            .error(function(jqXHR, textStatus, errorThrown) {
56836                new GLO.Popup.Error('No Wifi PAX devices found');
56837			});	
56838	}
56839	_pax.savePaxWifiDevice = function() {
56840		
56841		var uri = GLO.Link.WebsiteDomain + 'api/PAX/ConnectPAXDevice';
56842
56843		var jpop = $('#pax-wifi-setup').closest('.glopop');
56844		var ipAddress = jpop.find('#pax-wifi-ip').val();
56845		//remove leading zeros from ip
56846		var cleanIPAddress = ipAddress.replace(/(^|\.)0+(?=[^.])/g, '.');
56847
56848		var wifiDevice = {
56849			"Name":"Wifi device",
56850			"Port":"",
56851			"Direction":"",
56852			"TerminalUniqueId": SA.POS.PAX.uuid,
56853			"OSVersion":SA.POS.PAX.osVersion,
56854			"token":"",
56855			"IPAddress":cleanIPAddress,
56856			"MacAddress":""
56857		};
56858
56859		var jsonCOMPort = JSON.stringify(wifiDevice);
56860
56861        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonCOMPort, contentType: "application/json" })
56862            .success(function(data, textStatus, jqXHR) {
56863				window.onbeforeunload = null;
56864				//update the device list table
56865				_pax.ShowSelectedWifiDeviceInDeviceList(data);
56866				//_pax.setvar(data.DeviceId);
56867            	new GLO.Popup.Success('Device connected.', 19000);
56868            })
56869            .error(function(jqXHR, textStatus, errorThrown) {
56870                GLO.UI.Form.resetProcessing(); 		
56871                new GLO.Popup.Error('Unable to Connect to Selected Device');
56872            });
56873	}
56874
56875	_pax.getMacOSFromPAXApi = function(_callback) {
56876    	var uri = paxApiSvcBaseUrl + 'api/info/macos';
56877
56878        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, contentType: "application/json" })
56879            .success(function(data, textStatus, jqXHR) {
56880                window.onbeforeunload = null;
56881				//call pax api
56882				_callback(data);
56883
56884            })
56885            .error(function(jqXHR, textStatus, errorThrown) {
56886                new GLO.Popup.Error('Error getting UUID and OS version from local terminal');
56887            });
56888	}
56889
56890
56891	_pax.postManageRequestToPAXApi = function(manageRequest,deviceId) {
56892    	var uri = paxApiSvcBaseUrl + 'api/PAX/manage';
56893
56894        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: manageRequest, contentType: "application/json" })			// , timeout:30000
56895            .success(function(data, textStatus, jqXHR) {
56896                window.onbeforeunload = null;
56897				if (data.transResult.Code != "1") {
56898					new GLO.Popup.Error(data.transResult.Msg);
56899				}
56900				else {
56901					//call SA api
56902					var jsonMR = JSON.stringify(data.manageResponse);
56903					_pax.postManageResponseToSA(jsonMR,deviceId);
56904
56905					//testing - proof of concept changes
56906					// if (data.manageResponse.ResultCode == "000000" && data.manageResponse.ButtonNum == "1") {
56907					// 	//http://www.test2.com/api/PAX/getcreditauthrequest/6?isSale=false&cid=36574&smid=156468&amount=55
56908					// 	_pax.creditauth(deviceId,false,36574,156468,null,55);
56909					// }
56910				}
56911            })
56912            .error(function(jqXHR, textStatus, errorThrown) {
56913                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
56914                GLO.Popup.Error.open('Error communicating with PAX device', 'Device Unavailable');
56915            });
56916	}
56917	
56918	function _displayEmvCommunicateError(msg, h1, isCloseSwipePopup) {					        //only display warning if has swipe popup open (+ not processing card-on-file)
56919		if ($('#appt-price-swipe-ready').closest('.glopop').length > 0) {
56920			if ($('#pop-card-on-file-view').closest('.glopop').length === 0 && $('#btnUseCardOnFile.btnProcessing4').length === 0) {
56921				if ($('#pop-warn-emv-communicate').length === 0 && $('.pop-error.glopop, .pop-warning.glopop').length === 0) {
56922					h1 = UTIL.coalesceString(h1, 'Payment Processing Warning');
56923					var htmEnterManually = '<div id="enter-card-manually"> <a onclick="UserPortal.Price.Payment.openCreditCard()">Enter Card Manually</a> </div>';
56924					var htm = '<div id="pop-warn-emv-communicate">' + msg + htmEnterManually + '</div>';
56925					
56926					var jpop = GLO.Popup.Warning.open(htm, h1).getPopup();
56927	            	
56928	            	if (isCloseSwipePopup) {
56929	            		UserPortal.Price.Payment.closeSwipePopup(true);
56930	            	} else {
56931	            		_addReconnectButton();
56932	            		
56933	            		var btnConnect = '<span id="btnConnectEmv" class="btnAdd" style="float: right; margin: 0;"><a onclick="SA.POS.PAX.addConnectButton()">Connect Payment Device</a></span>';
56934	            		var btnOk = jpop.find('.btnOk');
56935	            		
56936	            		btnOk.find('> a').text('Cancel').click(function() { UserPortal.Price.Payment.closeSwipePopup(true); });
56937	            		btnOk.after(btnConnect);
56938	            	}
56939	            	
56940	            	//_pax.postCancelTransToPAXApi();
56941					return true;
56942				}
56943			}
56944		}
56945		
56946		return false;
56947	}
56948	
56949	function _addReconnectButton() {
56950		var jpop = $('#appt-price-swipe-ready').closest('.glopop');
56951		var btn = '<span id="btnConnectEmv" class="btnAdd"><a onclick="SA.POS.PAX.addConnectButton()">Connect EMV</a></span>';
56952		
56953		if (jpop.find('#btnConnectEmv').length === 0) {
56954			jpop.find('#enter-card-manually').after(btn);
56955		}
56956	}
56957	_pax.addConnectButton = function() {
56958		GLO.Popup.closeIfExist($('#pop-warn-emv-communicate').closest('.glopop'));
56959		
56960		UserPortal.Price.Payment.quickReopenSwipePopup();
56961	}
56962	_pax.addConnectingSpinner = function(timeoutWait) {
56963		var imgThrobber = '<img id="imgThrobber" src="' + GLO.Data.cdnDirectory + 'image/icon/throbber-blue.gif" style="margin: 4px;"/>';
56964    	var blueThrobber = '<div class="blue-throbber" style="margin-top: 32px;">' + imgThrobber + '<i>Connecting Payment Device</i></div>';
56965    	var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
56966    	jPopSwipe.find('#enter-card-manually').after(blueThrobber);
56967    	jPopSwipe.find('#enter-card-manually').css('display','none');
56968    	var jSwipeThrobber = jPopSwipe.find('.blue-throbber');
56969    	
56970    	setTimeout(function() {
56971    		jSwipeThrobber.remove();
56972    		jPopSwipe.find('#enter-card-manually').css('display','block');
56973    	}, timeoutWait);
56974	}
56975	
56976	_pax.postManageResponseToSA = function(manageResponse,deviceId) {
56977    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/ProcessManageResponse?device=' + deviceId;
56978
56979        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: manageResponse, contentType: "application/json" })
56980            .success(function(data, textStatus, jqXHR) {
56981                window.onbeforeunload = null;
56982
56983            	GLO.Popup.Success.open(data, 'Manage Device', 19000);
56984            })
56985            .error(function(jqXHR, textStatus, errorThrown) {
56986                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
56987                GLO.Popup.Error.open('Unable to POST Manage response', 'Payment Processing Warning', );
56988            });
56989	}
56990
56991	_pax.postPaymentRequestToPAXApi = function(paymentRequest, deviceId, isSale, cid, smid, scid, amount) {
56992    	var uri = paxApiSvcBaseUrl + 'api/PAX/payment';
56993    	var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
56994    	var startConnect = new Date();
56995    	
56996    	var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: paymentRequest, contentType: "application/json" })			// , timeout:30000
56997            .success(function(data, textStatus, jqXHR) {
56998                window.onbeforeunload = null;
56999                jPopSwipe.find('.blue-throbber').remove();
57000                
57001                if (data.paymentResponse) {
57002	                var resultText = data.paymentResponse.ResultTxt;
57003	                
57004	                if (jPopSwipe.length && resultText !== 'ABORTED' && resultText !== 'TIMEOUT') {
57005		                var throb = UI.getBlueThrobber();
57006		                jPopSwipe.find('#enter-card-manually').addClass('hide').after(throb);
57007		                jPopSwipe.find('#store-card-container').addClass('hide');
57008	                }
57009	                
57010	                _pax.postPaymentResponseToSA(data.paymentResponse, deviceId, isSale, cid, smid, scid, amount);
57011                } else {
57012                	var logMsg = 'Connect time: ' + startConnect + ' thru ' + new Date() + ' is ' + UTIL.numberWithCommas(new Date() - startConnect) + 'milliseconds';
57013                	GLO.Log.insert(logMsg, 'PAX Response Empty', smid, 'warning');
57014                	
57015                	_displayEmvCommunicateError('Unable to Connect to Payment Device', 'Unable to Connect', false);
57016                }
57017            })
57018            .error(function(jqXHR, textStatus, errorThrown) {
57019                jPopSwipe.find('.blue-throbber').remove();
57020                _displayEmvCommunicateError('Error communicating with PAX device. Please try again.');
57021                //this does not work -> SA.POS.PAX.postCancelTransToPAXApi(true);		//might not have properly cancelled previous request, so instead of having to wait for timeout of current screen can call this
57022                
57023                var keywords = smid + ' $' + amount
57024                var msg = '_pax.postPaymentRequestToPAXApi() ' + errorThrown + ': ' + paymentRequest;
57025                
57026                if (jqXHR && jqXHR.responseJSON) {
57027                	msg += ' -> ' + jQuery.parseJSON(jqXHR.responseJSON);
57028                }
57029                
57030                msg = UTIL.htmlEncode(msg);
57031                GLO.Log.insert(msg, 'PAX Response Error', keywords, 'error');
57032            });
57033	}
57034	
57035	_pax.postPaymentResponseToSA = function(jsonPayResponse, deviceId, isSale, cid, smid, scid, amount) {
57036    	var jsonPR = JSON.stringify(jsonPayResponse);
57037    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/ProcessPaymentResponse?device=' + deviceId + '&isSale=' + isSale + '&client=' + cid + '&smid=' 
57037+ smid + '&amount=' + amount;
57038    	
57039    	if (scid) {
57040    		uri += '&scid=' + scid;
57041    	}
57042    	
57043        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonPR, contentType: "application/json" })
57044            .success(function(data, textStatus, jqXHR) {
57045                window.onbeforeunload = null;
57046                GLO.Popup.closeIfExist($('#pop-warn-close-swipe').closest('.glopop'));
57047                
57048                if (jsonPayResponse.ResultTxt === 'OK') {
57049            		UserPortal.Price.Payment.saveCreditCard_complete(data, true);
57050            		_displayPaymentResponseWarning(jsonPayResponse);
57051            		_checkForTipOnPayment(jsonPayResponse, data);
57052	                //GLO.Popup.Success.open(data, 'Payment Successful', 19000);
57053            	} else if (data !== '') {
57054            		UserPortal.Price.Payment.saveCreditCard_error(data);
57055            		UserPortal.reloadTicket(smid);
57056            		_lookupMissingTsysTransaction(isSale, cid, smid, scid, amount);
57057            	} else {
57058            		_displayEmvCommunicateError(jsonPayResponse.ResultTxt, 'Payment Failed', true);
57059            		var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
57060            		
57061            		if (jPopSwipe.length) {
57062		                jPopSwipe.find('#imgThrobberContainer').remove();
57063		                jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide');
57064	                }
57065	                
57066	                _lookupMissingTsysTransaction(isSale, cid, smid, scid, amount);
57067            	}
57068            })
57069            .error(function(jqXHR, textStatus, errorThrown) {
57070                var fn = function() {
57071                	UserPortal.reloadTicket(smid);
57072                }
57073                
57074                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
57075                GLO.Popup.Error.open('Unable to process all card transactions', 'Multi-Merchant Transaction Failed', fn);
57076            });
57077	}
57078	function _lookupMissingTsysTransaction(isSale, cid, smid, scid, amount) {
57079		var uri = GLO.Link.WebsiteDomain + 'payment/FindOrphanTsysTransaction?isSale=' + isSale + '&client=' + cid + '&smid=' + smid + '&scid=' + scid + '&amount=' + amount;
57080    	var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false })
57081            .success(function(data, textStatus, jqXHR) {
57082            })
57083            .error(function(jqXHR, textStatus, errorThrown) {
57084            });
57085	}
57086	function _checkForTipOnPayment(jsonPayResponse, data) {					//= if tip is added from EMV device, then re-load ticket so tip correctly added to services
57087		if (UTIL.coalesceMoney(jsonPayResponse.ApprovedAmount/100) > 0) {
57088			var jdata = $(data);
57089			var newTip = UTIL.coalesceMoney(jdata.find('li').attr('tip_mn'));
57090			
57091			if (newTip > 0 && !UserPortal.Class.isClass()) {
57092				if (UTIL.isEmpty(jdata.attr('error_cd')) && UTIL.isEmpty(jdata.attr('warning_cd'))) {
57093					var smid = jdata.attr('schedule_multi_id');
57094					
57095					window.setTimeout(function() {					//put in setTimeout so receipt is printed
57096						UserPortal.reloadTicket(smid);
57097					}, 150);
57098				}
57099			}
57100		}
57101	}
57102	function _displayPaymentResponseWarning(jsonPayResponse) {
57103		var pmtRequest = UTIL.coalesceMoney(jsonPayResponse.RequestedAmount/100);
57104		var pmtApproved = UTIL.coalesceMoney(jsonPayResponse.ApprovedAmount/100);
57105		
57106		if (Math.abs(pmtRequest - pmtApproved) > .02) {
57107			if (pmtRequest - pmtApproved > 0) {
57108				var label = 'less';
57109			} else {
57110				var label = 'more';
57111			}
57112			
57113			var msg1 = '<p>' + UTIL.displayMoney(pmtRequest) + ' payment requested</p>';
57114			var msg2 = '<p>' + UTIL.displayMoney(pmtApproved) + ' payment approved</p>';
57115			var msg3 = '<p style="margin-top: 24px; font-weight: bold; color: red;">Actual payment ' + UTIL.displayMoney(pmtRequest - pmtApproved) + ' ' + label + ' than requested</p>';
57116			var htm = '<div id="pop-pax-payment-warning">' + msg1 + msg2 + msg3 + '</p>';
57117			
57118			GLO.Popup.Warning.open(htm, 'Amount Different');
57119		}
57120	}
57121	_pax.postCancelTransToPAXApi = function(isSilentMode) {
57122    	var uri = paxApiSvcBaseUrl + 'api/PAX/cancel';
57123
57124        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" })
57125            .success(function(data, textStatus, jqXHR) {
57126                window.onbeforeunload = null;
57127				var htm = '<div id="pop-cancel-emv-connect">' + data.result + '</div>';
57128				var isSilentMode = true;
57129            	
57130            	if (!isSilentMode && $('#pop-cancel-emv-connect').length === 0) {
57131            		GLO.Popup.Success.open(htm, 'Cancel PAX EMV Connection');			//toDo: comment this out after Beta goes live (this is just for testing)
57132            	}
57133            })
57134            .error(function(jqXHR, textStatus, errorThrown) {
57135                new GLO.Popup.Error('Error communicating with PAX device');
57136            });
57137	}
57138	//connect to selected device
57139	_pax.ConnectPAXDevice = function(i) {
57140    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/ConnectPAXDevice';
57141
57142		var COMPort = COMPorts[i];
57143		COMPort.TerminalUniqueId= SA.POS.PAX.uuid;
57144		COMPort.OSVersion = SA.POS.PAX.osVersion;
57145		var jsonCOMPort = JSON.stringify(COMPort);
57146
57147        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonCOMPort, contentType: "application/json" })
57148            .success(function(data, textStatus, jqXHR) {
57149				window.onbeforeunload = null;
57150				//update the device list table
57151				_pax.ShowSelectedDeviceInDeviceList(data);
57152				//_pax.setvar(data.DeviceId);
57153            	new GLO.Popup.Success('Device connected.', 19000);
57154            })
57155            .error(function(jqXHR, textStatus, errorThrown) {
57156                GLO.UI.Form.resetProcessing(); 		
57157                new GLO.Popup.Error('Unable to Connect to Selected Device');
57158            });
57159	}
57160
57161	_pax.ShowSelectedDeviceInDeviceList = function(paxDevice) {
57162
57163		//loop thru device list table and reset the table
57164		$('#ComPortsList tr').each(function(i,row){
57165			$(this).find('td').each(function(j,cell){
57166				if (typeof cell !== 'undefined') {
57167					if (cell.innerHTML == '<span>Selected</span>')  {
57168						cell.innerHTML = '<td><span id="btnConnect" class="btnReportAll btnAdd" onclick="SA.POS.PAX.ConnectPAXDevice(' + i + ')" tabindex="1" title="Select"><a>Select</a></span></td>';
57169					}
57170				}
57171			});
57172		});
57173
57174		//loop thru device list table and mark the selected device
57175		$('#ComPortsList tr').each(function(i,row){
57176			$(this).find('td').each(function(j,cell){
57177				if (typeof cell !== 'undefined') {
57178					if (cell.innerText != "" && (cell.innerText == paxDevice.SerialPort || cell.innerText == paxDevice.IPAddress))  {
57179						row.cells[4].innerHTML = '<span>Selected</span>';
57180					}
57181				}
57182			});
57183		});
57184	}
57185
57186	_pax.ShowSelectedWifiDeviceInDeviceList = function(paxDevice) {
57187
57188		//loop thru device list table and reset the table
57189		$('#PAXWifiDeviceList tr').each(function(i,row){
57190			$(this).find('td').each(function(j,cell){
57191				if (typeof cell !== 'undefined') {
57192					if (cell.innerHTML == '<span>Selected</span>')  {
57193						cell.innerHTML = '<td><span id="btnConnect" class="btnReportAll btnAdd" onclick="SA.POS.PAX.ConnectPAXWifiDevice(' + i + ')" tabindex="1" title="Select"><a>Select</a></span></td>';
57194					}
57195				}
57196			});
57197		});
57198
57199		//loop thru device list table and mark the selected device
57200		$('#PAXWifiDeviceList tr').each(function(i,row){
57201			$(this).find('td').each(function(j,cell){
57202				if (typeof cell !== 'undefined') {
57203					if (cell.innerText != "" && (cell.innerText == paxDevice.SerialPort || cell.innerText == paxDevice.IPAddress))  {
57204						row.cells[4].innerHTML = '<span>Selected</span>';
57205					}
57206				}
57207			});
57208		});
57209	}
57210
57211	_pax.DisconnectPAXDevice = function(COMPort) {
57212		var uri = GLO.Link.WebsiteDomain + 'api/PAX/DisconnectPAXDevice';
57213
57214		var COMPort = COMPorts[i];
57215		var jsonCOMPort = JSON.stringify(COMPort);
57216
57217        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonCOMPort, contentType: "application/json" })
57218            .success(function(data, textStatus, jqXHR) {
57219                window.onbeforeunload = null;
57220
57221            	GLO.Popup.Success.open(data, 'Disconnect Pax Emv Reader', 19000);
57222            })
57223            .error(function(jqXHR, textStatus, errorThrown) {
57224                GLO.UI.Form.resetProcessing(); 		
57225                new GLO.Popup.Error('Unable to Disconnect Device');
57226            });
57227	}
57228
57229	_pax.getPAXDeviceIdFromCookie = function() {
57230		var name = 'paxdevice' + "=";
57231		var decodedCookie = decodeURIComponent(document.cookie);
57232		var ca = decodedCookie.split(';');
57233		for(var i = 0; i <ca.length; i++) {
57234		  var c = ca[i];
57235		  while (c.charAt(0) == ' ') {
57236			c = c.substring(1);
57237		  }
57238		  if (c.indexOf(name) == 0) {
57239			return c.substring(name.length, c.length);
57240		  }
57241		}
57242		return "";
57243	}
57244
57245	_pax.getPAXDeviceByDeviceId = function(deviceId) {
57246		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
57247		if (paxDeviceId == "") {
57248			if (deviceId == "") {
57249				GLO.Popup.closeAll();
57250				new GLO.Popup.Error('Unable to find last used device. Please make sure device is connected and selected.');
57251				return;
57252			}
57253			else {
57254				paxDeviceId = deviceId;
57255			}
57256		}
57257    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/GetPAXDeviceSettings/' + paxDeviceId;
57258
57259        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57260            .success(function(data, textStatus, jqXHR) {
57261				window.onbeforeunload = null;
57262				
57263            	_pax.ShowSelectedDeviceInDeviceList(data);
57264				_pax.ShowSelectedWifiDeviceInDeviceList(data);
57265            })
57266            .error(function(jqXHR, textStatus, errorThrown) {
57267                new GLO.Popup.Error('Unable to get PAX Device Settings');
57268            });
57269	}
57270
57271	_pax.getPAXCred = function(deviceId) {
57272		var paxDeviceId = _pax.getPAXDeviceIdFromCookie();
57273		if (paxDeviceId == "") {
57274			if (deviceId == "") {
57275				new GLO.Popup.Error('Unable to find last used device. Please make sure device is connected and selected.');
57276				return;
57277			}
57278			else {
57279				paxDeviceId = deviceId;
57280			}
57281		}
57282    	var uri = GLO.Link.WebsiteDomain + 'api/PAX/GetPAXCred/' + paxDeviceId;
57283
57284        var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57285            .success(function(data, textStatus, jqXHR) {
57286				window.onbeforeunload = null;
57287				
57288            	_pax.ShowSelectedDeviceInDeviceList(data);
57289            })
57290            .error(function(jqXHR, textStatus, errorThrown) {
57291                new GLO.Popup.Error('Unable to get PAX Device Settings');
57292            });
57293	}
57294
57295	return _pax;
57296})();
57297
57298SA.POS.CCBolt = (function() {
57299	var _isConnected = false;
57300	var _currentPaymentMerchantIdString = null;
57301	
57302	function _bolt(mid) { }
57303	
57304	_bolt.getCurrentPaymentMerchantIdString = function() {
57305		return _currentPaymentMerchantIdString;
57306	}
57307	
57308	//get the list of terminals associated with a merchantId
57309	_bolt.listTerminals = function(ccMID) {
57310		if (!ccMID) {
57311			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57312			return;
57313		}
57314
57315		var uri = GLO.Link.WebsiteDomain + 'api/bolt/listTerminals/' + ccMID;
57316
57317		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57318		.success(function(data, textStatus, jqXHR) {
57319			window.onbeforeunload = null;
57320			return data;
57321		})
57322		.error(function(jqXHR, textStatus, errorThrown) {
57323			GLO.UI.Form.resetProcessing(); 		
57324			new GLO.Popup.Error('Unable to get CardConnect Terminals for merchant');
57325		});
57326	}
57327	
57328	_bolt.initEmvDeviceScreen = function() {
57329		var popup = UTIL.cleanString(GLO.Uri.url('popup')).toLowerCase();
57330		
57331		if (popup == 'setup-tips') {
57332			$('#btnTipPercent').find('a').click();
57333		}
57334	}
57335	
57336	_bolt.listTerminalDetailsWithCallback = function(ccMID,_callback) {
57337		if (!ccMID) {
57338			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57339			return;
57340		}
57341	
57342		var uri = GLO.Link.WebsiteDomain + 'api/bolt/terminalDetails/' + ccMID;
57343	
57344		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57345			.success(function(data, textStatus, jqXHR) {
57346				window.onbeforeunload = null;
57347				return _callback(data);
57348			})
57349			.error(function(jqXHR, textStatus, errorThrown) {
57350				GLO.UI.Form.resetProcessing(); 		
57351				new GLO.Popup.Error('Unable to get CardConnect Terminals Details for merchant');
57352			});
57353		}
57354	
57355	_bolt.loadDeviceList = function(json) {
57356		var deviceCount = 0;
57357		
57358		if (UTIL.isJson(json)) {				//typeof json.length !== 'undefined'
57359			$('#pax-column-header').addClass('hide');
57360			$('#bolt-column-header').removeClass('hide');
57361			
57362			var bolt = JSON.parse(json);
57363			var isDisplayPrintOptions = !UTIL.isEmpty($.cookies.get('emv-print'));
57364			deviceCount = bolt.terminalDetails.length;
57365			
57366			for (var i = 0; i < bolt.terminalDetails.length; i++) {				//Append each row to html table
57367			    var isConnected = bolt.terminalDetails[i].connected;
57368			    var hasPrinter = bolt.terminalDetails[i].deviceCapabilities.printer;
57369			    //var prettyName = SA.POS.CCBolt.deviceTypePrettyName(bolt.terminalDetails[i].deviceType);
57370				var midString = bolt.terminalDetails[i].merchantId;
57371				var btnConnect = '<span id="btnConnect" class="btnAdd"><a onclick="SA.POS.CCBolt.SaveBoltDevice(\'' + midString + '\',\'' + bolt.terminalDetails[i].hsn + '\', this);">Select</a></span>';
57372			
57373			    var tr = $('<tr/>');
57374			    tr.append('<td class="bolt-column-connect-device">' + btnConnect + '</td>');
57375			    tr.append('<td class="bolt-column-name">' + bolt.terminalDetails[i].hsn + '</td>');
57376			    tr.append('<td class="bolt-column-device-connected">' + UI.getCheckmark(isConnected) + '</td>');
57377			    tr.append('<td class="bolt-column-device-type">' + SA.POS.CCBolt.deviceTypePrettyName(bolt.terminalDetails[i].deviceType) + '</td>');
57378			    tr.append('<td class="bolt-column-device-emv">' + UI.getCheckmark(bolt.terminalDetails[i].deviceCapabilities.emv) + '</td>');
57379			    tr.append('<td class="bolt-column-device-nfc">' + UI.getCheckmark(bolt.terminalDetails[i].deviceCapabilities.nfc) + '</td>');
57380			    tr.append('<td class="bolt-column-device-signature hide">' + UI.getCheckmark(bolt.terminalDetails[i].deviceCapabilities.signature) + '</td>');
57381			    tr.append('<td class="bolt-column-device-printer-has">' + UI.getCheckmark(hasPrinter) + '</td>');
57382			    //tr.append('<td>' + '<span id="btnDisconnect" class="btnReportAll btnAdd" onclick="SA.POS.PAX.DisconnectPAXDevice()" tabindex="1" title="Unselect"><a>Un-Select</a></span>' + '</td>');
57383			    $('table#ComPortsList').append(tr);
57384			
57385			    if (hasPrinter) {			// && isConnected
57386			        isDisplayPrintOptions = true;
57387			    }
57388			}
57389			
57390			//check if bolt device cookie exists
57391			var serialNo = SA.POS.CCBolt.getDeviceSerialNo();
57392			
57393			if (serialNo && serialNo.length > 1) {
57394			    SA.POS.CCBolt.ShowSelectedBoltDeviceInDeviceList(serialNo);
57395			}
57396			
57397			UI.initTableSorter($('#report-main table.tablesorter'));
57398		}
57399		
57400		var jVivoPay = $('#btnCCMobileSdkEnabled #toggleCCMobileSdk');
57401		
57402		if (jVivoPay.length) {
57403			if (jVivoPay.prop('checked')) {
57404				var btnBlue = '<b style="display: inline-block; padding: 2px 24px; border-radius: 8px; background-color: blue; color: white;">';
57405				var htmVivoSetupList = '<li>Open an appointment</li>'
57406					+ '<li>In the Edit Appointment popup, press the price <small>(top left corner)</small></li>'
57407					+ '<li>Press Credit</li>'
57408					+ '<li>In the Checkout Screen <b class="arrow-right">&#10140;</b> press the big blue button: ' + btnBlue + 'Next</b></li>'
57409					+ '<li>Press <b class="arrow-right">&#10140;</b> <b style="color: blue;">Connect a different card reader</b></li>'
57410					+ '<li>Turn on you Vivo Pay card reader</li>'
57411					+ '<li>In the <b>Select a Reader</b> popup, select your card reader</li>'
57412					+ '<li>Press the blue button: ' + btnBlue + 'Charge Card</b></li>'
57413					+ '<li>The first time the card reader connects to your device it might take up to 20-30 seconds, after that it will only take a couple seconds to connect</li>'
57414					+ '<li>When the popup changes from <b>Searching</b> <i>to</i> <b>Please Swipe, Tag, or Insert</b> then you can process the card</li>';
57415				
57416				var htm = '<p>Your Vivo Pay Device is Enabled</p><p>To complete your Vivo Pay Device Setup</p><ol>' + htmVivoSetupList + '</ol>';
57417				GLO.Popup.Info.open('<div id="pop-vivo-pay-enable">' + htm + '</div>', 'Vivo Pay Device Setup');
57418			} else if ($('#ComPortsList tbody tr').length === 0) {
57419				var htm = '<p>Enable <b style="color: black;">Mobile Reader</b> to begin the setup of your Vivo Pay Device</p>';
57420				GLO.Popup.Info.open('<div id="pop-vivo-pay-device-setup">' + htm + '</div>', 'Vivo Pay Device Setup');
57421			}
57422		} else if (deviceCount == 0) {
57423			var merchantType = $('#manage-emv-header').attr('merchant_type_cd');
57424			
57425			if (merchantType == 50) {
57426				var htmVP3300 = 'No Vivo Pay <span class="narrow-text" style="color: inherit;">(ID-Tech VP3300)</span>';
57427				var msg1 = '<p>' + htmVP3300 + ' credit card device found</p>';
57428					
57429				var uri = GLO.Link.WebsiteDomain + 'provider/manage/ManageEMV?clover=1';
57430				var btnClover = '<span id="btnConnectClover" class="btnAdd">
57430<a onclick="GLO.Uri.gotoUri(\'' + uri + '\', this, event, true);">Load Clover Devices</a></span>';
57431				var msg2 = '<p>Would you like to ' + btnClover + ' to connect to</p>';
57432			} else {
57433				var msg1 = '<p>No credit card device found</p>';
57434				var msg2 = '<p>If you need to connect a credit card reader please contact ' + GLO.Info.getScheduleAnyoneHtm() + '</p>';
57435			}
57436			
57437			var htm = '<div id="pop-error-emv-device-list-empty">' + msg1 + msg2 + '</div>';
57438			GLO.Popup.Warning.open(htm, 'No Devices Found');
57439		}
57440		
57441		// if (isDisplayPrintOptions) {
57442		// 	SA.POS.CCBolt.displayPrinterOptions('Clover');
57443		// }
57444	}
57445	_bolt.loadPrinterSettings = function(json) {
57446		if (UTIL.isJson(json)) {				//typeof json.length !== 'undefined'
57447
57448			var bolt = JSON.parse(json);
57449			var isDisplayPrintOptions = !UTIL.isEmpty($.cookies.get('emv-print'));
57450			
57451			for (var i = 0; i < bolt.terminalDetails.length; i++) {				//Append each row to html table
57452			    var isConnected = bolt.terminalDetails[i].connected;
57453			    var hasPrinter = bolt.terminalDetails[i].deviceCapabilities.printer;
57454			    //var prettyName = SA.POS.CCBolt.deviceTypePrettyName(bolt.terminalDetails[i].deviceType);
57455				var midString = bolt.terminalDetails[i].merchantId;
57456			
57457			    if (hasPrinter) {			// && isConnected
57458			        isDisplayPrintOptions = true;
57459			    }
57460			}
57461		} 
57462		
57463		if (isDisplayPrintOptions) {
57464			SA.POS.CCBolt.displayPrinterOptions('Clover');
57465		}
57466	}
57467
57468	_bolt.displayPrinterOptions = function(prettyName) {
57469		var rdoStart = '<input type="radio" name="emv_print_cd" onchange="SA.POS.CCBolt.changePrintSetting(this)" ';
57470		var cbAsNeededStaffPrint = '<input type="checkbox" name="emv_print_as_needed_staff_print_cd" onchange="SA.POS.CCBolt.changeStaffPrintSetting(this)" ';
57471		var aStandAlone = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'/provider/manage/receipt?helloback=advanced&tabback=payment\', this, event, true)">stand-alone printer</a>';
57472		var smallNever = '<small>(suggested if have ' + aStandAlone + ' or prefer going green and just email/texting receipt)</small>';
57473		var smallAsk = '<small style="white-space: pre-wrap;">(suggested if you have no other printer and want to print occasionally)</small>';
57474		var labelAsNeeded = '<label for="emv_print_as_needed_staff_print_cd">Send staff prints to receipt printer</label>';
57475		
57476		if (innerWidth < 760) {
57477			var smallNever = '<small>(have ' + aStandAlone + ' or just email/text receipt)</small>';
57478		}
57479		
57480		var htm = '<div id="manage-emv-printer-options">'
57481				+ '<h5>Use ' + prettyName + ' Printer</h5>'
57482				+ '<div>' + rdoStart + 'id="emv_print_always"/><label for="emv_print_always"><b>Always for Credit Card Payments</b> <small>(suggested if you have no other printer)</small></label></div>'
57483				+ '<div>' + rdoStart + 'id="emv_print_once"/><label for="emv_print_once"><b>After Credit Card Payment</b> <small>(good option if you also have ' + aStandAlone + ')</small></label></div>'
57484				+ '<div>' + rdoStart + 'id="emv_print_as_needed"/><label for="emv_print_as_needed"><b>Ask Customer</b> ' + smallAsk + '</label>'
57485					+ '<div id="emv_print_as_needed_staff_print" style="margin-left:40px" class="hide">' + cbAsNeededStaffPrint + ' id="emv_print_as_needed_staff_print_cd"/>' + labelAsNeeded + '</div>' 
57486				+ '</div>'
57487				+ '<div>' + rdoStart + 'id="emv_print_never"/><label for="emv_print_never"><b>Never Use This Printer</b> ' + smallNever + '</label></div>'
57488			+ '</div>';
57489		
57490		// $('#manage-emv-header-message').replaceWith(htm);
57491		$("#clover-receipt-printer-settings").html(htm);
57492		_setCurrentPrintSetting();
57493	}
57494	
57495	function _setCurrentPrintSetting() {
57496		var usePrinterDB = UTIL.parseBool($('#manage-emv-header').attr('use_builtin_receipt_printer'));
57497		var usePrinterCookie = $.cookies.get('emv-print');
57498		
57499		if (usePrinterCookie == 'once') {
57500			$('#emv_print_once').prop('checked', true);
57501			$('#emv_print_as_needed_staff_print').addClass('hide');
57502		} else if (usePrinterCookie == 'asneeded' || usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) {
57503			$('#emv_print_as_needed').prop('checked', true);
57504			$('#emv_print_as_needed_staff_print').removeClass('hide');
57505			if (usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) {
57506				$('#emv_print_as_needed_staff_print_cd').attr('checked','checked');
57507			}
57508			else {
57509				$('#emv_print_as_needed_staff_print_cd').removeAttr('checked');
57510			}
57511			
57512		}else if (usePrinterCookie == 'always') {
57513			$('#emv_print_always').prop('checked', true);
57514			$('#emv_print_as_needed_staff_print').addClass('hide');
57515		} else if (usePrinterCookie == 'never') {
57516			$('#emv_print_never').prop('checked', true);
57517			$('#emv_print_as_needed_staff_print').addClass('hide');
57518		} else if (usePrinterDB) {
57519			$('#emv_print_once').prop('checked', true);
57520			$('#emv_print_as_needed_staff_print').addClass('hide');
57521		} else {
57522			$('#emv_print_never').prop('checked', true);
57523			$('#emv_print_as_needed_staff_print').addClass('hide');
57524		}
57525	}
57526	_bolt.changeStaffPrintSetting = function(checkbox) {	
57527		var cookieValue = 'asneeded';
57528		var useBuiltIn = true;
57529		if (checkbox.checked) {
57530			cookieValue = 'asneeded+'
57531			$('#emv_print_as_needed_staff_print_cd').attr('checked','checked');
57532		}
57533		else {
57534			cookieValue = 'asneeded';
57535			$('#emv_print_as_needed_staff_print_cd').removeAttr('checked')
57536		}
57537		UTIL.setCookie("emv-print", cookieValue);
57538		GLO.Log.insertSimple('Set Emv Print Cookie', 'bolt.changePrintSetting: use-built-in-printer = ' + useBuiltIn + ' (cookieValue = ' + cookieValue + ')', 'warning');
57539		var cookieValueEncoded = encodeURIComponent(cookieValue);
57540		_changePrintSetting(useBuiltIn,cookieValueEncoded);
57541
57542	}
57543
57544	_bolt.changePrintSetting = function(rdo) {				//= save to DB + set cookie
57545		if (rdo.id == 'emv_print_once') {
57546			var cookieValue = 'once';
57547			var useBuiltIn = true;
57548			//uncheck asneeded staff checkbox
57549			$('#emv_print_as_needed_staff_print_cd').removeAttr('checked');
57550			$('#emv_print_as_needed_staff_print').addClass('hide');
57551		} else if (rdo.id == 'emv_print_as_needed') { 
57552			var cookieValue = 'asneeded';
57553			var useBuiltIn = true;
57554			$('#emv_print_as_needed_staff_print').removeClass('hide');
57555		}else if (rdo.id == 'emv_print_always') {
57556			var cookieValue = 'always';
57557			var useBuiltIn = true;
57558			//uncheck asneeded staff checkbox
57559			$('#emv_print_as_needed_staff_print_cd').removeAttr('checked');
57560			$('#emv_print_as_needed_staff_print').addClass('hide');
57561		} else if (rdo.id == 'emv_print_never') {
57562			var cookieValue = 'never';
57563			var useBuiltIn = false;
57564			//uncheck asneeded staff checkbox
57565			$('#emv_print_as_needed_staff_print_cd').removeAttr('checked');			
57566			$('#emv_print_as_needed_staff_print').addClass('hide');
57567		} else {
57568			var cookieValue = null;
57569			var useBuiltIn = false;
57570			//uncheck asneeded staff checkbox
57571			$('#emv_print_as_needed_staff_print_cd').removeAttr('checked');			
57572			$('#emv_print_as_needed_staff_print').addClass('hide');
57573		}
57574		UTIL.setCookie("emv-print", cookieValue);
57575		GLO.Log.insertSimple('Set Emv Print Cookie', 'bolt.changePrintSetting: use-built-in-printer = ' + useBuiltIn + ' (cookieValue = ' + cookieValue + ')', 'warning');
57576		_changePrintSetting(useBuiltIn,cookieValue);
57577
57578	}
57579	function _changePrintSetting(useBuiltIn, cookieValue) {
57580		var uri = GLO.Link.WebsiteDomain + 'provider/manage/SetEMVPrinter?useBuiltIn=' + useBuiltIn + '&printmode=' + cookieValue;
57581
57582        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" })
57583            .success(function(data, textStatus, jqXHR) {
57584				GLO.Popup.Success.open('Print Setting Saved', 'Payment Device Printer');
57585            })
57586            .error(function(jqXHR, textStatus, errorThrown) {
57587                GLO.UI.Form.resetProcessing(); 		
57588                new GLO.Popup.Error('Unable to save to print setting');
57589            });
57590	}
57591	
57592	function _getDeviceTypeCode(deviceTypeLabel) {
57593		if (UTIL.isEmpty(deviceTypeLabel)) {
57594			return '';
57595		}
57596		
57597		deviceTypeLabel = deviceTypeLabel.toLowerCase();
57598		
57599		if (deviceTypeLabel.indexOf('clover mini') !== -1) {
57600			return 35;
57601		} else if (deviceTypeLabel.indexOf('flex') !== -1) {
57602			return 38;
57603		} else if (deviceTypeLabel.indexOf('ingenico 3') !== -1) {
57604			return 51;
57605		} else if (deviceTypeLabel.indexOf('ismp4') !== -1) {
57606			return 52;
57607		} else if (deviceTypeLabel.indexOf('ingenico') !== -1) {
57608			return 50;
57609		}
57610		
57611		return '';
57612	}
57613
57614	_bolt.changeTipMode = function(rdo) {				//= save to DB + set cookie
57615		if (rdo.id == 'tip-by-amount') {
57616			$('#tip-by-amount').attr('checked','checked');
57617			$('#tip-by-percent').removeAttr('checked');
57618			$('#tipPercentsFieldset').addClass('hide');
57619		} else if (rdo.id == 'tip-by-percent') {
57620			$('#tip-by-percent').attr('checked','checked');
57621			$('#tip-by-amount').removeAttr('checked');
57622			$('#tipPercentsFieldset').removeClass('hide');
57623		} 
57624		
57625	}	
57626	
57627	_bolt.SaveBoltDevice = function(ccMID, serialNo, element) {
57628		var deviceTypeLabel = $(element).closest('tr').find('.bolt-column-device-type').text();
57629		var deviceTypeCode = _getDeviceTypeCode(deviceTypeLabel)
57630		//var json = { "devicetype": deviceTypeCode };
57631		var uri = GLO.Link.WebsiteDomain + 'api/bolt/SaveBoltDevice/' + ccMID + '/' + serialNo + '?devicetype=' + deviceTypeCode;
57632		
57633        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" })
57634            .success(function(data, textStatus, jqXHR) {
57635				window.onbeforeunload = null;
57636				
57637				_bolt.ShowSelectedBoltDeviceInDeviceList(serialNo);
57638            	GLO.Popup.Success.open('Reloading Device List...', 'Device Selected', 19000);
57639            	
57640            	setTimeout(function() {
57641            		location.reload();
57642            	}, 3100);
57643            })
57644            .error(function(jqXHR, textStatus, errorThrown) {
57645                GLO.UI.Form.resetProcessing(); 		
57646                new GLO.Popup.Error('Unable to save to Selected Device');
57647            });
57648	}
57649
57650	_bolt.isBoltMobileSdkEnabled = function() {
57651		var name = 'boltmobilesdk' + "=";
57652		var decodedCookie = decodeURIComponent(document.cookie);
57653		var ca = decodedCookie.split(';');
57654		for(var i = 0; i <ca.length; i++) {
57655		  var c = ca[i];
57656		  while (c.charAt(0) == ' ') {
57657			c = c.substring(1);
57658		  }
57659		  if (c.indexOf(name) == 0) {
57660			return c.substring(name.length, c.length);
57661		  }
57662		}
57663		return "";
57664	}
57665
57666	_bolt.SetMobileSdkStatus = function() {
57667		var boltMobileSdkStatus = SA.POS.CCBolt.isBoltMobileSdkEnabled();
57668
57669		if (boltMobileSdkStatus == 'enabled') {
57670			$('#toggleCCMobileSdk').prop("checked",true);
57671		}
57672		else {
57673			$('#toggleCCMobileSdk').prop("checked",false);
57674		}
57675	}
57676
57677	_bolt.ToggleMobileSdk = function(ccMID) {
57678		var mobileSdkEnabled = 'disable';
57679		var isEnabled = $('#toggleCCMobileSdk').prop("checked");
57680
57681		if (isEnabled) {
57682			mobileSdkEnabled = 'enable';
57683		}
57684
57685		var uri = GLO.Link.WebsiteDomain + 'api/bolt/ToggleMobileSdk/' + ccMID + '?isEnabled=' + mobileSdkEnabled;
57686
57687        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: null, contentType: "application/json" })
57688            .success(function(data, textStatus, jqXHR) {
57689				window.onbeforeunload = null;
57690				if (isEnabled) {
57691					GLO.Popup.Success.open('Enabled Mobile Reader...', 'Bolt Mobile', 19000);
57692					setTimeout(function() { location.reload(); }, 400);
57693				}
57694				else {
57695					GLO.Popup.Success.open('Disabled Mobile Reader...', 'Bolt Mobile', 19000);
57696					setTimeout(function() { location.reload(); }, 400);
57697				}	
57698            })
57699            .error(function(jqXHR, textStatus, errorThrown) {
57700				$('#toggleCCMobileSdk').prop("checked",!isEnabled);//previous state
57701                GLO.UI.Form.resetProcessing(); 		
57702                new GLO.Popup.Error('Unable to enable or disable Bolt Mobile');
57703            });
57704	}
57705
57706	_bolt.deviceTypePrettyName = function(deviceType) {
57707		if (deviceType == 'iPP320') {
57708            return 'iPP320 Ingenico';
57709        } else if (UTIL.startsWith(deviceType, 'Mini')) {
57710            return 'Clover ' + deviceType;
57711        } else {
57712        	return deviceType;
57713        }
57714	}
57715	
57716	_bolt.ShowSelectedBoltDeviceInDeviceList = function(serialNo) {
57717
57718		//loop thru device list table and mark the selected device
57719		$('#ComPortsList tr').each(function(i,row){
57720			$(this).find('td').each(function(j,cell){
57721				if (typeof cell !== 'undefined') {
57722					if (cell.innerText != "" && (cell.innerText == serialNo)) {
57723						row.cells[0].innerHTML = UI.getCheckmark(true);				// '<span>Selected</span>';
57724					}
57725				}
57726			});
57727		});
57728	}
57729
57730	_bolt.postAuthResponseToBoltApi = async function(authResponse,ccMID,serialNo, isSale, tipAmount, cid, smid, scid, ccArr, isTipFromDevice) {
57731		var uri = GLO.Link.WebsiteDomain + 'api/bolt/payment/' + ccMID + '/' + serialNo + '?isSale=' + isSale + '&client=' + cid + '&smid=' + smid + '&tip=' + tipAmount;
57732    	var tipSplit = UserPortal.Price.QuickTip.getSplit();
57733    	
57734    	if (scid) {
57735    		uri += '&scid=' + scid;
57736    	}
57737    	
57738    	if (!UTIL.isEmpty(tipSplit)) {
57739    		uri += '&tipSplit=' + tipSplit;
57740    	}
57741    	
57742    	if (UTIL.parseBool(isTipFromDevice)) {
57743    		uri += '&isTipFromDevice=true';
57744    	}
57745    	
57746    	var dxml = UTIL.htmlEncode(UserPortal.Price.Discount.toXml());
57747		var ccArrJsonString = JSON.stringify(ccArr);
57748    	var jsd = { "authResponse": authResponse, "discount_xml": dxml , "merchants": ccArrJsonString };
57749    	
57750    	UserPortal.Price.Payment.addPayMethDiscount(jsd, true, 10);
57751    	
57752        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsd, dataType: 'html', contentType: 'application/x-www-form-urlencoded; charset=UTF-8' })
57753            .success(function(data, textStatus, jqXHR) {
57754                window.onbeforeunload = null;
57755                GLO.Popup.closeIfExist($('#pop-warn-close-swipe').closest('.glopop'));
57756                
57757				return data;
57758            })
57759            .error(function(jqXHR, textStatus, errorThrown) {
57760                var fn = function() {
57761                	UserPortal.reloadTicket(smid);
57762                }
57763                
57764                GLO.UI.Form.resetProcessing(); 		
57765                GLO.Popup.Error.open('Unable to POST Payment response', 'Payment Warning', fn);
57766            });
57767
57768			return await jqxhr;
57769	}
57770
57771	_bolt.postAddtionalPaymentsToBoltApi = function(serverResponse,ccMID,serialNo, isSale, tipAmount, cid, multiScheduleId, scid,ccArr) {
57772		var uri = GLO.Link.WebsiteDomain + 'api/bolt/multimerchantpayment/' + ccMID + '/' + serialNo + '?isSale=' + isSale + '&client=' + cid + '&smid=' + multiScheduleId + '&tip=' + tipAmount;
57773    	
57774    	if (scid) {
57775    		uri += '&scid=' + scid;
57776    	}
57777    	
57778    	var dxml = UTIL.htmlEncode(UserPortal.Price.Discount.toXml());
57779		var ccArrJsonString = JSON.stringify(ccArr);
57780    	var jsd = { "serverResponse": serverResponse, "discount_xml": dxml , "merchants": ccArrJsonString };
57781    	UserPortal.Price.Payment.addPayMethDiscount(jsd, true, 10);
57782    	
57783        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsd, dataType: 'html', contentType: 'application/x-www-form-urlencoded; charset=UTF-8' })
57784            .success(function(data, textStatus, jqXHR) {
57785                window.onbeforeunload = null;
57786                GLO.Popup.closeIfExist($('#pop-warn-close-swipe').closest('.glopop'));
57787				var paymentResponse = UTIL.safeParseJson(data);
57788				
57789                if (!UserPortal.Price.Payment.saveCreditCard_complete(paymentResponse.receipthtml, true, true, 2))  {
57790            		if (paymentResponse.receipthtml !== '') {
57791	            		UserPortal.Price.Payment.saveCreditCard_error(paymentResponse.receipthtml);
57792	            		UserPortal.reloadTicket(multiScheduleId);
57793	            	} else {
57794	            		var msg = $(paymentResponse.receipthtml).html();
57795	            		_displayEmvCommunicateError(msg , 'Payment Failed', true);
57796	            		var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
57797	            		
57798	            		if (jPopSwipe.length) {
57799			                jPopSwipe.find('#imgThrobberContainer').remove();
57800			                jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide');
57801		                }
57802		            }
57803            	}
57804            })
57805            .error(function(jqXHR, textStatus, errorThrown) {
57806                var fn = function() {
57807                	UserPortal.reloadTicket(multiScheduleId);
57808                }
57809                
57810                GLO.UI.Form.resetProcessing(); 		
57811                GLO.Popup.Error.open('Unable to POST Payment response', 'Payment Warning', fn);
57812            });
57813
57814	}
57815
57816	_bolt.connect = async function(ccMID,serialNo) {
57817		if (!ccMID) {
57818			new GLO.Popup.Error('<div><p>Fiserv merchant not connected to ' + GLO.Info.getScheduleAnyoneHtm(
57818) + '</p><p>Please refresh page and try again</p></div>', 'Merchant Id Missing');
57819			return;
57820		} else if (UTIL.isEmpty(serialNo) && GLO.Info.roleType > 169) {
57821			//if ($('#pop-warn-bolt-connect').closest('.glopop').length === 0) {
57822			var labelConnect = '<label><i>Card Reader</i> Not Connected</label>';
57823			var aConnect = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/ManageEMV\', this, event, true)" title="Press Here to Setup Card Reader">Setup Card Reader</a>';
57824			var btnConnect = '<span class="btnAdd">' + aConnect + '</span>';
57825			var htmHello = '<div id="hello-bar-warn-bolt-connect-inner">' + labelConnect + btnConnect + '</div>';
57826			
57827			var helloBarId = 'hello-bar-warn-bolt-connect', cssClass = 'hello-bar-warn';
57828			var jpopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
57829			
57830			GLO.Popup.addHelloBar(jpopSwipe, htmHello, helloBarId, cssClass);			//GLO.Popup.Warning.open(htm, 'Card Reader Not Connected');
57831			return;
57832		}
57833
57834		var uri = GLO.Link.WebsiteDomain + 'api/bolt/connect/' + ccMID + '/' + serialNo;
57835
57836		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57837		.success(function(data, textStatus, jqXHR) {
57838			window.onbeforeunload = null;
57839			return data;
57840		})
57841		.error(function(jqXHR, textStatus, errorThrown) {
57842			GLO.UI.Form.resetProcessing();
57843			var trswipe = $('#appt-price-popup').closest('.glopop').find('tr.swipe');
57844			
57845			if (trswipe.length) {	
57846				if (UserPortal.Price.Payment.openCreditCard(false, true)) {
57847					setTimeout(UserPortal.Price.Payment.resetSaveButton, 200);
57848				}
57849			}
57850			
57851			GLO.Popup.Error.open('Unable to connect to card reader', 'Payment Issue');
57852		});
57853
57854		return await jqxhr;
57855	}
57856
57857	_bolt.disconnect = async function(ccMID,serialNo) {
57858		if (!ccMID) {
57859			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57860			return;
57861		}
57862
57863		var uri = GLO.Link.WebsiteDomain + 'api/bolt/disconnect/' + ccMID + '/' + serialNo;
57864
57865		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57866		.success(function(data, textStatus, jqXHR) {
57867			window.onbeforeunload = null;
57868			return data;
57869		})
57870		.error(function(jqXHR, textStatus, errorThrown) {
57871			GLO.UI.Form.resetProcessing(); 		
57872			new GLO.Popup.Error('Unable to disconnect CardConnect Terminal for merchant');
57873		});
57874
57875		return await jqxhr;
57876	}
57877
57878	_bolt.ping = async function(ccMID,serialNo) {
57879
57880		if (!ccMID) {
57881			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57882			return;
57883		}
57884
57885		var uri = GLO.Link.WebsiteDomain + 'api/bolt/ping/' + ccMID + '/' + serialNo;
57886
57887		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57888		.success(function(data, textStatus, jqXHR) {
57889			window.onbeforeunload = null;
57890			return data;
57891		})
57892		.error(function(jqXHR, textStatus, errorThrown) {
57893			GLO.UI.Form.resetProcessing(); 		
57894			new GLO.Popup.Error('Unable to Ping device');
57895		});
57896
57897		return await jqxhr;
57898	}
57899
57900	_bolt.display = async function(ccMID,serialNo,displayText) {
57901
57902		if (!ccMID) {
57903			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57904			return;
57905		}
57906
57907		var uri = GLO.Link.WebsiteDomain + 'api/bolt/display/' + ccMID + '/' + serialNo + '?displayText=' + encodeURIComponent(displayText);
57908
57909		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57910		.success(function(data, textStatus, jqXHR) {
57911			window.onbeforeunload = null;
57912			return data;
57913		})
57914		.error(function(jqXHR, textStatus, errorThrown) {
57915			GLO.UI.Form.resetProcessing(); 		
57916			new GLO.Popup.Error('Unable to Display on CardConnect Terminal for merchant');
57917		});
57918
57919		return await jqxhr;
57920	}
57921
57922	_bolt.clearDisplay = async function(ccMID,serialNo) {
57923
57924		if (!ccMID) {
57925			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57926			return;
57927		}
57928
57929		var uri = GLO.Link.WebsiteDomain + 'api/bolt/cleardisplay/' + ccMID + '/' + serialNo;
57930
57931		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
57932		.success(function(data, textStatus, jqXHR) {
57933			window.onbeforeunload = null;
57934			return data;
57935		})
57936		.error(function(jqXHR, textStatus, errorThrown) {
57937			GLO.UI.Form.resetProcessing(); 		
57938			new GLO.Popup.Error('Unable to Clear Display on CardConnect Terminal for merchant');
57939		});
57940
57941		return await jqxhr;
57942	}
57943
57944	_bolt.tip = async function(ccMID,serialNo,multiScheduleId,amount, ticketTotal) {
57945		if (!ccMID) {
57946			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57947			return;
57948		}
57949		
57950		let subTotal = (Math.round(amount * 100));
57951		var uri = GLO.Link.WebsiteDomain + 'api/bolt/tip/' + ccMID + '/' + serialNo;
57952		var payload = { "multiScheduleId": multiScheduleId , "amount": subTotal, "total": (Math.round(ticketTotal * 100)) };
57953
57954		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' })
57955		.success(function(data, textStatus, jqXHR) {
57956			window.onbeforeunload = null;
57957			return data;
57958		})
57959		.error(function(jqXHR, textStatus, errorThrown) {
57960			GLO.UI.Form.resetProcessing(); 		
57961			new GLO.Popup.Error('Unable to invoke tip function for merchant');
57962		});
57963
57964		return await jqxhr;
57965	}
57966
57967	_bolt.printReceiptOnBolt = async function(ccMID,serialNo,multiScheduleId) {
57968		if (!ccMID) {
57969			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57970			return;
57971		}
57972		
57973		var uri = GLO.Link.WebsiteDomain + 'api/bolt/printreceipt/' + ccMID + '/' + serialNo;
57974		var payload = {"multiScheduleId": multiScheduleId , "amount": 0};
57975
57976		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' })
57977		.success(function(data, textStatus, jqXHR) {
57978			window.onbeforeunload = null;
57979			return data;
57980		})
57981		.error(function(jqXHR, textStatus, errorThrown) {
57982			GLO.UI.Form.resetProcessing(); 		
57983			new GLO.Popup.Error('Unable to invoke print Receipt function for merchant');
57984		});
57985
57986		return await jqxhr;
57987	}	
57988	
57989
57990	_bolt.readConfirmation = async function(ccMID,serialNo,multiScheduleId,amount) {
57991
57992		if (!ccMID) {
57993			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
57994			return;
57995		}
57996
57997		var uri = GLO.Link.WebsiteDomain + 'api/bolt/readconfirmation/' + ccMID + '/' + serialNo;
57998		var payload = {"multiScheduleId": multiScheduleId };
57999
58000		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' })
58001		.success(function(data, textStatus, jqXHR) {
58002			window.onbeforeunload = null;
58003			return data;
58004		})
58005		.error(function(jqXHR, textStatus, errorThrown) {
58006			GLO.UI.Form.resetProcessing(); 		
58007			new GLO.Popup.Error('Unable to read confirmation for merchant');
58008		});
58009
58010		return await jqxhr;
58011	}
58012
58013	_bolt.receiptConfirmation = async function(ccMID,serialNo,multiScheduleId) {
58014
58015		if (!ccMID) {
58016			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
58017			return;
58018		}
58019
58020		var uri = GLO.Link.WebsiteDomain + 'api/bolt/receiptconfirmation/' + ccMID + '/' + serialNo;
58021		var payload = {"multiScheduleId": multiScheduleId };
58022
58023		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' })
58024		.success(function(data, textStatus, jqXHR) {
58025			window.onbeforeunload = null;
58026			return data;
58027		})
58028		.error(function(jqXHR, textStatus, errorThrown) {
58029			GLO.UI.Form.resetProcessing(); 		
58030			new GLO.Popup.Error('Unable to ask for receipt confirmation for merchant');
58031		});
58032
58033		return await jqxhr;
58034	}
58035
58036	_bolt.authCard = async function(ccMID,overrideMID,serialNo,multiScheduleId,amount,totalMultiMerchant) {
58037
58038		if (!ccMID) {
58039			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
58040			return;
58041		}
58042
58043		var uri = GLO.Link.WebsiteDomain + 'api/bolt/authCard/' + ccMID + '/' + serialNo;
58044		var payload = {"MultiScheduleId": multiScheduleId , "Amount": amount, "OverrideMid": overrideMID};
58045
58046		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: payload, dataType: 'json' })
58047			.success(function(data, textStatus, jqXHR) {
58048				window.onbeforeunload = null;
58049				//var jd = JSON.parse(data);
58050				return data;
58051			})
58052			.error(function(jqXHR, textStatus, errorThrown) {
58053				GLO.UI.Form.resetProcessing(); 		
58054				new GLO.Popup.Error('Unable to authorize card for merchant');
58055			});
58056
58057		return await jqxhr;
58058	}
58059	
58060	_bolt.checkIfPaymentActuallyProcessed = function(smid) {
58061		if (smid > 0) {
58062    		var price = UserPortal.Price.getPrice(true, true, true);
58063    		var payment = UserPortal.Price.Payment.getTotalPaymentOnTicket();
58064    		var amount = UTIL.coalesceMoney(price - payment);
58065    		
58066    		_checkIfPaymentActuallyProcessed(smid, amount);
58067    	}
58068	}
58069	
58070	function _checkIfPaymentActuallyProcessed(smid, amount, boltResponse) {
58071		if (smid == UserPortal.Price.Payment.getSMID()) {
58072			var dxml = UTIL.htmlEncode(UserPortal.Price.Discount.toXml());
58073            var multiTicketXml = '';
58074            
58075            if (!UTIL.isEmptyObject(UserPortal.Price.multiTicketXml)) {
58076            	multiTicketXml = UTIL.htmlEncode(UserPortal.Price.MultiTicket.saveTickets());
58077            }
58078            
58079            var jd = { "discount_xml": dxml, "multi_ticket_xml": multiTicketXml };
58080		} else {
58081			var jd = {};
58082		}
58083		
58084		if (UTIL.isEmpty(smid)) {
58085			return;
58086		}
58087		
58088		setTimeout(function() {					//Add ~2 second wait to orphan check process
58089			SA.POS.CCBolt.checkIfPaymentActuallyProcessed2(smid, amount, boltResponse, jd);
58090		}, 1900);
58091	}
58092	_bolt.checkIfPaymentActuallyProcessed2 = function(smid, amount, boltResponse, jd) {
58093		//$('#appt-price-swipe-ready #enter-card-manually').css({ "height": "", "padding-top": "24px" }).find('> a').replaceWith(GLO.Report.Template2.getBlueThrobber());
58094		var uri = GLO.Link.WebsiteDomain + 'payment/LookupOrphanTransaction?smid=' + smid + '&price=' + amount;
58095		
58096		if (UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 0) > 9) {
58097			uri += '&mid=' + GLO.Uri.url('mid');
58098		}
58099		
58100		var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jd })
58101			.success(function(data, textStatus, jqXHR) {
58102				window.onbeforeunload = null;
58103				var jd = $(data);
58104				
58105				if (jd.attr('id') == 'orphan-transaction-response') {
58106					var jwarn = jd.find('warning');
58107					
58108					if (jwarn.length && UserPortal.getAppt().length && UserPortal.Edit.scheduleMultiId == smid) {
58109						var jsonPostProcess = { "processing_header_vc": "Loading Payment", "processing_message_vc": "Updating Appointment" };
58110						UserPortal.Edit.checkIfUpdated(smid, null, true, true, jsonPostProcess);
58111					}
58112				}
58113				
58114				return data;
58115			})
58116			.error(function(jqXHR, textStatus, errorThrown) {
58117				window.onbeforeunload = null;
58118			});
58119	}
58120	
58121	function _processConnectResponse(connectResponse, ccMID, serialNo) {
58122		console.log(connectResponse);
58123		
58124		if (connectResponse.errorMessage) {
58125			var err = new Error(connectResponse.errorMessage);
58126			err.isConnectError = true;
58127			throw err;
58128		}
58129		
58130		return _bolt.ping(ccMID, serialNo);
58131	}
58132	function _processPingResponseForPrint(pingResponse, ccMID, serialNo, multiScheduleId) {
58133		console.log(pingResponse);
58134		
58135		if (UTIL.safeParseJson(pingResponse).errorMessage) {
58136			throw new Error(`${UTIL.safeParseJson(pingResponse).errorMessage}`);
58137		}
58138		
58139		if (UTIL.safeParseJson(pingResponse).connected == true) {
58140
58141			return _bolt.printReceiptOnBolt(ccMID, serialNo, multiScheduleId);
58142
58143		} else {
58144			throw new Error(`Terminal not connected. Please make sure terminal is connected.`);
58145		}
58146	}
58147
58148	function _processPrintResponse(printResponse, ccMID, serialNo, multiScheduleId) {
58149		// console.log(printResponse);
58150		var json = UTIL.safeParseJson(printResponse);
58151		
58152		if (Object.keys(json).length == 0) {
58153			return _bolt.disconnect(ccMID,serialNo);
58154		}
58155
58156
58157		if (json.errorMessage) {
58158			throw new Error(`${UTIL.safeParseJson(printResponse).errorMessage}`);
58159		}
58160
58161		if (json.hasOwnProperty('receiptData')) {				//receipt print was successful
58162			return _bolt.disconnect(ccMID,serialNo);
58163		} else {
58164			throw new Error(`Receipt could not be printed. Please make sure terminal is available.`);
58165		}
58166	}
58167
58168	function _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,amount, tipEnabled, isGotoConfirm, ccArr,useListPrice,servicesTotalPrice) {
58169		// console.log(pingResponse);
58170		
58171		if (UTIL.safeParseJson(pingResponse).errorMessage) {
58172			throw new Error(`${UTIL.safeParseJson(pingResponse).errorMessage}`);
58173		}
58174		
58175		if (UTIL.safeParseJson(pingResponse).connected == true) {
58176			let confirmAmount = UTIL.displayMoney(amount, true);				//(Math.round(amount * 100) / 100).toFixed(2);
58177			let originalAmount = UTIL.displayMoney(baseAmount, true);
58178			let servicesTotal = UTIL.displayMoney(servicesTotalPrice, true);
58179
58180			if (isGotoConfirm) {
58181				return _bolt.readConfirmation(ccMID, serialNo, multiScheduleId, confirmAmount);
58182			} else if (tipEnabled) {
58183				if (useListPrice) {
58184					if (UTIL.coalesceMoney(servicesTotal) > 0) {			//&& ccArr && ccArr.length == 1
58185						return _bolt.tip(ccMID, serialNo, multiScheduleId, servicesTotal, confirmAmount);
58186					}
58187				} else if (UTIL.coalesceMoney(confirmAmount) > 0) {
58188					return _bolt.tip(ccMID, serialNo, multiScheduleId, confirmAmount, confirmAmount);
58189				}
58190			}
58191			
58192			var totalAmount = Math.round(amount * 100);
58193			
58194			if (ccArr && ccArr.length > 1) {
58195				confirmAmount = _getMultiMerchantFirstPaymentAmount(ccArr, ccMID);
58196			} else {
58197				confirmAmount = totalAmount;
58198			}
58199			
58200			return _bolt.authCard(ccMID, overrideMID, serialNo, multiScheduleId, confirmAmount, totalAmount);
58201		} else {
58202			throw new Error(`Terminal not connected. Please make sure terminal is connected.`);
58203		}
58204	}
58205	function _processReadConfirmationResponse(readConfirmationResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, amount, tipEnabled, ccArr, useListPrice, servicesTotalPrice) {
58206		console.log(readConfirmationResponse);
58207		
58208		if (UTIL.safeParseJson(readConfirmationResponse).errorMessage) {
58209			throw new Error(`${UTIL.safeParseJson(readConfirmationResponse).errorMessage}`);
58210		}
58211		
58212		if (UTIL.safeParseJson(readConfirmationResponse).confirmed == true) {
58213			let confirmAmount = UTIL.displayMoney(amount, true);				//(Math.round(amount * 100) / 100).toFixed(2);
58214			let originalAmount = UTIL.displayMoney(baseAmount, true);
58215			let servicesTotal = UTIL.displayMoney(servicesTotalPrice, true);
58216
58217			//record client confirmation in appt update log
58218			SA.Profile.Payment.LogConfirmationToApptUpdateLog(multiScheduleId);
58219
58220			if (tipEnabled) {
58221				if (useListPrice) {					// && ccArr && ccArr.length == 1
58222					if (UTIL.coalesceMoney(servicesTotal) > 0) {
58223						return _bolt.tip(ccMID, serialNo, multiScheduleId, servicesTotal, confirmAmount);
58224					}
58225				} else if (UTIL.coalesceMoney(confirmAmount) > 0) {
58226					return _bolt.tip(ccMID, serialNo, multiScheduleId, confirmAmount, confirmAmount);
58227				}
58228			}
58229			
58230			var totalAmount = Math.round(amount * 100);
58231			
58232			if (ccArr && ccArr.length > 1) {
58233				confirmAmount = _getMultiMerchantFirstPaymentAmount(ccArr, ccMID);
58234			} else {
58235				confirmAmount = totalAmount;
58236			}
58237			
58238			return _bolt.authCard(ccMID, overrideMID, serialNo, multiScheduleId, confirmAmount, totalAmount);
58239		} else {
58240			throw new Error('Customer did not confirm question or message. Please check with customer.');
58241		}
58242	}
58243
58244	function _getMultiMerchantFirstPaymentAmount(ccArr, ccMID) {
58245		var chargeMerchant = ccArr.filter(function(mc) {
58246			return mc.merchantid === ccMID;
58247		});
58248		
58249		if (UTIL.isEmptyObject(chargeMerchant) || chargeMerchant.length === 0) {
58250			chargeMerchant = ccArr;
58251		}
58252		
58253		return UTIL.coalesceInt(UTIL.coalesceInt(chargeMerchant[0].amount * 100, 0) + UTIL.coalesceInt(chargeMerchant[0].tip * 100, 0));
58254	}
58255	function _processConfirmResponse(confirmationResponse, ccMID, serialNo, multiScheduleId, amount) {
58256		console.log(confirmationResponse);
58257		
58258		if (UTIL.safeParseJson(confirmationResponse).errorMessage) {
58259			throw new Error(`${UTIL.safeParseJson(confirmationResponse).errorMessage}`);
58260		}
58261		
58262		if (UTIL.safeParseJson(confirmationResponse).confirmed == true){
58263			return _bolt.tip(ccMID,serialNo,multiScheduleId,amount);
58264		} else {
58265			var warning = new Error('<div style="pop-error-card-connect"><p>Amount was not confirmed</p><p>Please check with client</p></div>');
58266			warning.isWarning = true;
58267			throw warning;
58268		}
58269	}
58270	function _processTipResponse(tipResponse, ccMID, overrideMID,serialNo, multiScheduleId, amount, ccArr, servicesTotalPrice) {
58271		console.log(tipResponse);
58272		
58273		if (UTIL.isEmpty(tipResponse)) {
58274			GLO.Log.insert(tipResponse, 'bolt.ProcessTipResponse', multiScheduleId, 'warning');
58275			throw new Error('Card Reader Timeout');
58276		}
58277		
58278		var jsonTipResponse = UTIL.safeParseJson(tipResponse);
58279		
58280		if (jsonTipResponse.errorMessage) {
58281			throw new Error(`${ jsonTipResponse.errorMessage}`);
58282		} else if (jsonTipResponse.respstat == 'A' && jsonTipResponse.token) {					//= tipResponse is actually authResponse
58283			return tipResponse;
58284		}
58285		
58286		if (UTIL.parseBool(GLO.Data.provider.useListPriceForTip)) {
58287			var total = UTIL.coalesceMoney(servicesTotalPrice);
58288		} else {
58289			var total = UTIL.coalesceMoney(jsonTipResponse.total);
58290		}
58291		
58292		var totalTip = UTIL.coalesceMoney(jsonTipResponse.tip);
58293		
58294		if (totalTip > 0 & ccArr.length > 1) {							//divide tip equally among merchants
58295			for (const ccmerchant of ccArr) {
58296				//var merchantTipPercent = parseFloat(((ccmerchant.amount / total) * 100).toFixed(2));
58297				//ccmerchant.tip = parseFloat((merchantTipPercent * (totalTip / 100)).toFixed(2));
58298				_setTip(ccmerchant, total, totalTip);
58299			}
58300			
58301			_verifyTip(ccArr, totalTip);
58302		} else {
58303			ccArr[0].tip = UTIL.coalesceMoney(totalTip/100);
58304		}
58305		
58306		//multi-ticket scenario VERIFY
58307		if (ccArr.length == 1) {
58308			if (ccArr[0].amount !== amount) {
58309				ccArr[0].amount = amount;
58310			}
58311		}
58312		
58313		var chargeMerchant = null;
58314		
58315		if (overrideMID != '') {
58316			chargeMerchant = ccArr.filter(function(mc) { return mc.merchantid === overrideMID;});
58317		} else {
58318			chargeMerchant = ccArr.filter(function(mc) { return mc.merchantid === ccMID;});
58319		}
58320		
58321		//var chargeTotal = (UTIL.coalesceInt(chargeMerchant[0].amount * 100, 0) + UTIL.coalesceInt(chargeMerchant[0].tip * 100, 0)).toString();
58322		//var chargeTotal = UTIL.coalesceInt((UTIL.coalesceMoney(chargeMerchant[0].amount, 0) + UTIL.coalesceMoney(chargeMerchant[0].tip, 0)) * 100).toString();		//problem: this can cause a rounding issue where '401.99999999999994' is rounded to '401'
58323		var chargeTotal = Math.round((UTIL.coalesceMoney(chargeMerchant[0].amount, 0) + UTIL.coalesceMoney(chargeMerchant[0].tip, 0)) * 100);
58324		
58325		return _bolt.authCard(ccMID, overrideMID,serialNo, multiScheduleId, chargeTotal, total);
58326	}
58327	
58328	function _setTip(merchant, total, totalTip) {			//= splits tip amount by service price (ignores products + outcall fee)
58329		var payto = merchant.pay_to;
58330		var amount = merchant.amount;
58331		
58332		var jedit = UserPortal.getEditAppt();
58333		var tr = jedit.find('.editServiceRow');
58334		var serviceTotal = 0, merchantService = 0;
58335		var split = GLO.Data.provider.split_tip_cd;					//UserPortal.Price.QuickTip.getSplit();
58336		
58337		for (var i=0; i < tr.length; i++) {
58338			var jstaff = tr.eq(i).find('.staffDD option:selected');
58339			var mt = UTIL.coalesceInt(jstaff.attr('merchant_type_cd'), 99);
58340			var sid = jstaff.attr('value');
58341			
58342			//if (split == 110 || split == 100) {			at this time: split tip = 'evenly' is NOT supported for multi-merchant transactions (when tipping on Clover device)
58343			if (split == 10) {
58344				var service = UTIL.coalesceMoney(UserPortal.Booking.service[i].price_mn);
58345			} else {
58346				var service = UTIL.coalesceMoney(UserPortal.Booking.service[i].price_mn) + UTIL.coalesceMoney(UserPortal.Booking.service[i].add_on_fee_mn)
58347						  + -UTIL.coalesceMoney(UserPortal.Booking.service[i].new_discount_mn, UserPortal.Booking.service[i].discount_mn)
58348						  + UTIL.coalesceMoney(UserPortal.Booking.service[i].tax_mn);
58349			}
58350			
58351			serviceTotal += service;
58352			
58353			if ((payto == 'h' && mt < 50) || (payto == sid)) {
58354				merchantService += service;
58355			}
58356		}
58357		
58358		//var total = UTIL.coalesceMoney((total - totalTip)/100 - UserPortal.getOutcallFee());
58359		var pct = UTIL.coalesceMoney(merchantService/serviceTotal);			//round percent to
58360		
58361		if (pct > 1 ) {
58362			pct = 1;
58363		}
58364		
58365		merchant.tip = UTIL.coalesceMoney(pct * totalTip/100);
58366	}
58367
58368	function _verifyTip(ccArr, totalTip) {			//= if tip has a rounding error (should not happen often, but could be off by +/- .01), then adjust first tip amount.
58369		totalTip = UTIL.coalesceMoney(totalTip/100);
58370		
58371		for (const ccmerchant of ccArr) {
58372			totalTip = UTIL.coalesceMoney(totalTip - ccmerchant.tip);
58373		}
58374		
58375		if (totalTip !== 0) {
58376			if (Math.abs(totalTip) > .01) {
58377				GLO.Log.insertFromAppt('Card Connect Multi-Merchant Verify Tip Adjustment: ' + totalTip);
58378			}
58379			
58380			ccArr[0].tip = UTIL.coalesceMoney(ccArr[0].tip + totalTip);
58381		}
58382	}
58383	
58384	function _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr, isTipFromDevice) {
58385		console.log(authResponse);
58386		var ojAuthResponse = UTIL.safeParseJson(authResponse);
58387		
58388		if (ojAuthResponse.errorMessage) {
58389			if (ojAuthResponse.errorCode) {			// == 8
58390				//errorMessage == 'Operation Cancelled' -> staff closes appointment (or client removes card) just before transaction finishes processing
58391				//errorMessage == 'Command Cancelled' -> client does not remove card after payment in timely manner
58392				
58393				if (ojAuthResponse.authResponse && ojAuthResponse.errorMessage !== 'Authorization Voided') {
58394					//there was an error during the payment response but auth may have succeeded
58395					var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
58396					jPopSwipe.find('#enter-card-manually').css({ "height": "", "padding-top": "24px" }).find('> a').replaceWith(GLO.Report.Template2.getBlueThrobber());
58397					jPopSwipe.find('#store-card-container').remove();
58398					
58399					var innerAuthResponse =  JSON.stringify(ojAuthResponse.authResponse);
58400					ccMID = UTIL.coalesceString(overrideMID, ccMID);
58401					//innerAuthResponse.orderId = multiScheduleId; //set the orderId so it maps to the ticket
58402					return _bolt.postAuthResponseToBoltApi(innerAuthResponse, ccMID, serialNo, isSale, tipAmount, cid, multiScheduleId, scid, ccArr, isTipFromDevice);
58403
58404				} else if (ojAuthResponse.authResponse && ojAuthResponse.errorMessage === 'Authorization Voided') {
58405					//authorizaton was voided for some reason, notify staff
58406					var htm = '<div id="pop-error-bolt-auth=response"><p>Error Code ' + ojAuthResponse.errorCode + '</p><p>' + ojAuthResponse.errorMessage + '</p><p>Please retry the payment.</p></div>';
58407					GLO.Popup.Warning.open(htm, 'Payment Processing Error');
58408					
58409				} else {
58410					//check for orphan xsaction
58411					_checkIfPaymentActuallyProcessed(multiScheduleId, amount, ojAuthResponse);
58412				}
58413			} else if (ojAuthResponse.errorMessage === 'Command Cancelled') {
58414				_checkIfPaymentActuallyProcessed(multiScheduleId, amount, ojAuthResponse);
58415			//} else if (jd.respstat != 'A' || jd.amount == 0) {			//= handles expired card (and maybe other errors)
58416			//	var htm = '<div id="pop-warn-bolt-auth"><p>Card Not Charged</p><p>' + jd.resptext + '</p></div>';
58417			//	GLO.Popup.Warning.open(htm, 'Credit Card Response');
58418			} else {
58419				var htm = '<div id="pop-error-bolt-auth=response"><p>Error Code ' + ojAuthResponse.errorCode + '</p><p>' + ojAuthResponse.errorMessage + '</p></div>';
58420				GLO.Popup.Warning.open(htm, 'Payment Processing Error');
58421			}
58422			
58423			throw new Error(`${ojAuthResponse.errorMessage}`);
58424		} else if (ojAuthResponse.respstat != 'A') {
58425			throw new Error(ojAuthResponse.resptext);
58426		}
58427		
58428		var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
58429		jPopSwipe.find('#enter-card-manually').css({ "height": "", "padding-top": "24px" }).find('> a').replaceWith(GLO.Report.Template2.getBlueThrobber());
58430		jPopSwipe.find('#store-card-container').remove();
58431		
58432		ccMID = UTIL.coalesceString(overrideMID, ccMID);
58433		return _bolt.postAuthResponseToBoltApi(authResponse, ccMID, serialNo, isSale, tipAmount, cid, multiScheduleId, scid, ccArr, isTipFromDevice);
58434
58435	}
58436
58437	function _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr,isEnabledReceiptConfirmation) {
58438		console.log(serverResponse);
58439		var ojServerResponse = UTIL.safeParseJson(serverResponse);
58440		var xmlDoc = $.parseXML(ojServerResponse.receipthtml);
58441		
58442		if (ojServerResponse.receipthtml === '') {
58443			var msg = UTIL.coalesceString(ojServerResponse.warning, 'Payment Response Invalid');
58444			
58445			if (!UTIL.isEmpty(ojServerResponse.warning)) {
58446				var h1 = 'Unable to Process Tip';
58447				
58448				setTimeout(function() {
58449					UserPortal.reloadTicket(multiScheduleId);
58450				}, 2500);
58451			} else {
58452				var h1 = 'Payment Failed';
58453			}
58454			
58455			_displayEmvCommunicateError(msg, h1, true);
58456			var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
58457			
58458			if (jPopSwipe.length) {
58459				jPopSwipe.find('#imgThrobberContainer').remove();
58460				jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide');
58461			}
58462		} else if (ojServerResponse.multimerchant == 'true') {							//= IF MULTIMERCHANT IS TRUE, THEN SEND THE SECOND/ADDITIONAL TRANSACTIONS TO SERVER
58463			 if (UserPortal.Price.Payment.saveCreditCard_complete(ojServerResponse.receipthtml, true, true, 1)) {
58464				ojServerResponse.receipthtml = '';
58465				var serverResponseJsonNoHtml = JSON.stringify(ojServerResponse);
58466				var jProgressBar = $('#appt-price-swipe-ready #enter-card-manually');
58467				
58468				var remainingAmount = _remainingAmountAfterFirstTransaction(ccArr);
58469				var msg = '<p>First transaction completed successfuly</p><p>Processing ' + UTIL.pluralLabel(ccArr.length - 1, ' other transaction') + ' for ' + remainingAmount + '</p>';
58470				var boltMessage = 'First Transaction Successful\n\nProcessing ' + UTIL.pluralLabel(ccArr.length - 1, ' More Transaction') + ' for ' + remainingAmount + '...';
58471				
58472				UI.startProgressBar(jProgressBar, 36, msg);		//wait for gateway timeout seconds
58473				
58474				setTimeout(function () {
58475					_bolt.clearDisplay(ccMID,serialNo);
58476					var midString = UTIL.coalesceString(overrideMID, ccMID);
58477					_processAdditionalTransactions(serverResponseJsonNoHtml, midString, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr);
58478				}, ojServerResponse.gatewaytimeoutms);
58479				
58480				return _bolt.display(ccMID,serialNo, boltMessage);
58481			/* } else {
58482				/*
58483					_displayEmvCommunicateError($xml.find("ul").attr('error_cd') , 'Payment Failed', true);
58484					var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
58485					
58486					if (jPopSwipe.length) {
58487						jPopSwipe.find('#imgThrobberContainer').remove();
58488						jPopSwipe.find('#enter-card-manually, #store-card-container').removeClass('hide');
58489					}
58490			*/
58491			}
58492		} else {
58493			UserPortal.Price.Payment.saveCreditCard_complete(ojServerResponse.receipthtml, true, true);
58494		}
58495
58496		var usePrinterCookie = $.cookies.get('emv-print');
58497		//ask for receipt if enabled and clover receipt is set to asneeded
58498		if ((usePrinterCookie == 'asneeded' || usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) && isEnabledReceiptConfirmation) {
58499			return _bolt.receiptConfirmation(ccMID,serialNo,multiScheduleId);
58500		}
58501		else {
58502			return _bolt.disconnect(ccMID, serialNo);
58503		}
58504	}
58505	
58506	function _remainingAmountAfterFirstTransaction(ccArr) {
58507		var total = 0;
58508		
58509		for (var i=1; i < ccArr.length; i++) {
58510			total += UTIL.coalesceMoney(ccArr[1].amount) + UTIL.coalesceMoney(ccArr[1].tip);
58511		}
58512		
58513		return UTIL.displayMoney(total);
58514	}
58515
58516	function _processAdditionalTransactions(serverResponse, ccMID, serialNo, isSale, cid, multiScheduleId, scid, amount, tipAmount, ccArr) {
58517		var ojServerResponse = UTIL.safeParseJson(serverResponse);
58518
58519		_bolt.postAddtionalPaymentsToBoltApi(serverResponse,ccMID,serialNo, isSale, tipAmount, cid, multiScheduleId, scid,ccArr);
58520
58521	}
58522	function _processDisconnectResponse(disconnectResponse) {
58523		console.log(disconnectResponse);
58524		
58525		if (Object.keys(UTIL.safeParseJson(disconnectResponse)).length == 0) {
58526			return;
58527		}
58528
58529		if (UTIL.safeParseJson(disconnectResponse).errorMessage) {
58530			throw new Error(`${UTIL.safeParseJson(disconnectResponse).errorMessage}`);
58531		}
58532		
58533		if (UTIL.safeParseJson(disconnectResponse).disconnected == true){
58534			console.log('disconnected');
58535		} else {
58536			throw new Error(`{"errorMessage":"Disconnect failed!"}`);
58537		}
58538	}
58539	function _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation) {
58540		console.log(disconnectOrReceiptResponse);
58541		//response can be receipt, disconnect or display
58542
58543		if (disconnectOrReceiptResponse == '') {
58544			return '';
58545		}
58546
58547		var usePrinterCookie = $.cookies.get('emv-print');
58548		//Print Receipt response
58549		if ((usePrinterCookie == 'asneeded' || usePrinterCookie == 'asneeded+' || usePrinterCookie == encodeURIComponent('asneeded+')) && isEnabledReceiptConfirmation) {
58550			var receiptConfirmationResponse = disconnectOrReceiptResponse;
58551		
58552			if (UTIL.safeParseJson(receiptConfirmationResponse).errorMessage) {
58553				throw new Error(`${UTIL.safeParseJson(receiptConfirmationResponse).errorMessage}`);
58554			}
58555			
58556			if (UTIL.safeParseJson(receiptConfirmationResponse).confirmed == true) {
58557				return _bolt.printReceiptOnBolt(ccMID, serialNo, multiScheduleId);
58558			}
58559
58560			// return _bolt.disconnect(ccMID,serialNo);
58561		}
58562		else {
58563			//disconnect response
58564			if (UTIL.safeParseJson(disconnectOrReceiptResponse).errorMessage) {
58565				throw new Error(`${UTIL.safeParseJson(disconnectOrReceiptResponse).errorMessage}`);
58566			}
58567			
58568			if (UTIL.safeParseJson(disconnectOrReceiptResponse).disconnected == true){
58569				console.log('disconnected');
58570				return;
58571			} else {
58572				throw new Error(`{"errorMessage":"Disconnect failed!"}`);
58573			}
58574		}
58575	}
58576	function _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId) {
58577		console.log(printOrDisconnectResponse);
58578
58579		if (printOrDisconnectResponse == '') {
58580			return;
58581		}
58582
58583		//Print Receipt response
58584		if (Object.keys(UTIL.safeParseJson(printOrDisconnectResponse)).length == 0 || typeof UTIL.safeParseJson(printOrDisconnectResponse).receiptData !== "undefined") {
58585			return _bolt.disconnect(ccMID,serialNo);
58586		}
58587
58588		if (UTIL.safeParseJson(printOrDisconnectResponse).errorMessage) {
58589			throw new Error(`${UTIL.safeParseJson(printOrDisconnectResponse).errorMessage}`);
58590		}
58591
58592		//disconnect response
58593		if (typeof UTIL.safeParseJson(printOrDisconnectResponse).disconnected !== "undefined") {
58594			if (UTIL.safeParseJson(printOrDisconnectResponse).disconnected == true){
58595				console.log('disconnected');
58596			} else {
58597				throw new Error(`{"errorMessage":"Disconnect failed!"}`);
58598			}
58599		}
58600
58601		return _bolt.disconnect(ccMID,serialNo);
58602		
58603	}
58604	function _processErrorResponse(e, ccMID, serialNo, isPrint) {
58605		console.log(e);
58606		GLO.UI.Form.resetProcessing();
58607		
58608		var isBoltConnectWarning = $('#pop-warn-bolt-connect').closest('.glopop').length;
58609		var isInMerchantMode = (e && e.message && e.message.indexOf('in merchant mode') !== -1);
58610		var isAlreadyInUse = (e && e.message && e.message.indexOf('already in use') !== -1);
58611		
58612		if (isBoltConnectWarning) {						//= if bolt connect error, allow entering card manually
58613			var jPopSwipe = $('#appt-price-swipe-ready').closest('.glopop');
58614			jPopSwipe.find('#imgThrobber, .blue-throbber').remove();
58615			
58616			GLO.Log.insertJSErrorSimple(e, 'Bolt Connect Fail', 'warning', ccMID + '/' + serialNo);
58617			return;
58618		} else if (isInMerchantMode) {
58619			_isConnected = false;
58620		} else if (isAlreadyInUse) {
58621			_bolt.resetTerminal(ccMID, serialNo);
58622			_isConnected = false;
58623		} else {
58624			//if (UTIL.parseBool(e.isConnectError) && !isPrint) { _isConnected = true; }
58625			GLO.Log.insertJSErrorSimple(e, 'Bolt Process Error Response', 'high', ccMID + '/' + serialNo);
58626			//UserPortal.Price.Payment.closeSwipePopup(true);
58627		}
58628		
58629		if (_isConnected) {
58630			_isConnected = false;
58631			e.isConnectError = true;
58632			GLO.Log.insertJSErrorSimple(e, 'Bolt Process Error Response');
58633			
58634			_processErrorResponse2(e, ccMID, serialNo, isPrint, isAlreadyInUse, isInMerchantMode, true);
58635			return _bolt.disconnect(ccMID,serialNo);
58636		}
58637		
58638		_processErrorResponse2(e, ccMID, serialNo, isPrint, isAlreadyInUse, isInMerchantMode);
58639	}
58640	
58641	function _processErrorResponse2(e, ccMID, serialNo, isPrint, isAlreadyInUse, isInMerchantMode, isConnectError) {
58642		if (isAlreadyInUse || isInMerchantMode || (UTIL.parseBool(e.isConnectError) && !isPrint && e.message !== 'Command Cancelled' && e.message !== 'Card Reader Timeout')) {			//= if cannot connect to clover reader then need to allow staff to enter manually
58643			UserPortal.Price.Payment.openCreditCard(false, isConnectError);
58644		}
58645		
58646		if (isInMerchantMode) {
58647			GLO.Log.insertJSErrorSimple(e, 'Bolt In Merchant Mode', 'warning', ccMID + '/' + serialNo);
58648			var msg2 = 'Please change Card Reader to <b style="padding: 4px 8px; color: black; background-color: rgb(0,255,0);">Customer Mode</b>';
58649			_displayBoltWarningMessge(e, 'Device in Merchant Mode', 'pop-bolt-warn-merchant-mode', msg2);
58650		} else if (isAlreadyInUse) {
58651			_displayBoltWarningMessge(e, 'Device Already in Use by another Session', 'pop-bolt-warn-in-use');
58652			GLO.Log.insertJSErrorSimple(e, 'Bolt Is Already Connected to another Session', 'warning', ccMID + '/' + serialNo);
58653		} else if (e.message) {
58654			if (e.message === 'Command Cancelled' || e.message === 'Card Reader Timeout') {
58655				_isConnected = false;
58656			} else {
58657				var msg2 = '', header = 'Payment failed';
58658				var isNotConnected = (e && e.message.indexOf('Terminal not connected') !== -1);			//thrown by SA in pingResponse when ping returns not connected, toDo: why is Connect succeeding ??
58659				var isPrintReceiptError = (e && e.message.indexOf('PrintReceiptResponse') !== -1);
58660				
58661				if (isNotConnected) {
58662					msg2 = 'Please verify another session not connected to device';
58663				}
58664				
58665				if (e.isConnectError) {
58666					header = 'Unable to Connect to Clover';
58667				}
58668				
58669				if (isPrintReceiptError) {
58670					msg2 = 'Please check printer paper is present and terminal is connected to a power supply and try again.'
58671				}
58672				
58673				if (e.isConnectError && e.message.indexOf('No request queue registered for') !== -1) {
58674					var msg = '<p>Unable to Connect to Clover ' + serialNo + '</p><p>Please check Clover screen to verify device is in <b class="narrow-text">Customer Mode</b></p>';
58675					_displayBoltWarningMessge(e, header, 'pop-bolt-warn', msg);
58676				} else if (e.isWarning) {
58677					_displayBoltWarningMessge(e, header, 'pop-bolt-warn', msg2);
58678				} else {
58679					_displayBoltWarningMessge(e, header, 'pop-bolt-error', msg2);
58680				}
58681			}
58682			
58683			GLO.Log.insertSimple('Bolt Process Error Response', e.message, 'high');
58684		} else if ($('.pop-error').closest('.glopop').length === 0) {
58685			GLO.Popup.Error.open('<p>Unable to process payment</p><p>Please try again</p>', 'Credit Card Reader');
58686			GLO.Log.insertSimple('Unable to Process Payment', ccMID + ' | ' + serialNo, 'high');
58687		}
58688	}
58689	
58690	function _displayBoltWarningMessge(e, h1, popid, msg2) {
58691		if ($('#hello-bar-warn-bolt-connect').closest('.glopop').length) { return; }
58692		
58693		var msgTry = '', msg = 'Unable to Communicate with Clover Connect Device';
58694		popid = UTIL.coalesceString(popid, 'pop-bolt-warning');
58695		
58696		if (e && e.message) {
58697			msg = e.message;
58698			
58699			try {
58700				msgTry = JSON.parse('{ '+ e.message + '}').errorMessage;
58701			} catch (e) { }
58702		}
58703		
58704		h1 = UTIL.coalesceString(h1, 'Payment Device Issue');
58705		msg = UTIL.coalesceString(msgTry, msg);
58706		msg2 = UTIL.coalesceString(msg2, 'Please Try Again');
58707		
58708		var htm = '<div id="' + popid + '"><p>' + msg + '</p><p style="text-align: center;">' + msg2 + '</p></div>';
58709		
58710		if (popid.indexOf('error') !== -1) {
58711			var ojpop = GLO.Popup.Error.open(htm, h1);
58712		} else {
58713			var ojpop = GLO.Popup.Warning.open(htm, h1);
58714		}
58715		
58716		ojpop.getPopup().addClass('pop-fail-cc-pay-bolt');
58717	}
58718	
58719	_bolt.resetTerminal = function(mid, serialNumber) {
58720		if (UTIL.isEmpty(serialNumber)) {
58721			serialNumber = $.cookies.get('boltdevice');
58722		}
58723		
58724		if (UTIL.isEmpty(mid)) {
58725			mid = GLO.Data.provider.merchants[0].idString;
58726		}
58727
58728		SA.POS.CCBolt.clearDisplay(mid, serialNumber);
58729
58730		setTimeout(function () {
58731			SA.POS.CCBolt.disconnect(mid, serialNumber);
58732		}, 2000);
58733		
58734
58735	}
58736	
58737	_bolt.startTakePayment = function(ccArr, cid, smid, scid, baseAmount, amount, tipAmount, totalPrice, isForceDisableTip, servicesTotalPrice) {
58738		let serialNo = SA.POS.CCBolt.getDeviceSerialNo();
58739		let ticketHasHouseAccount = true;
58740		ccArr = _convertMerchantArrayForBolt(ccArr);
58741		var isEnabledDeviceGetConfirmation = false;
58742		var isEnabledReceiptConfirmation = false;
58743
58744		var houseAccount = ccArr.filter(function(item) {				//get the house account mid if on ticket else get the first chair mid on ticket
58745			return item.pay_to === 'h';
58746		});
58747		
58748		if (houseAccount.length > 0) {
58749				//ticket has house account
58750		} else {
58751			ticketHasHouseAccount = false;
58752			houseAccount = GLO.Data.provider.merchants.filter(function(item) { return item.type === 10;})
58753		}
58754		
58755		var cloverMerchantId = (ticketHasHouseAccount) ? houseAccount[0].merchantid : ccArr[0].merchantid;
58756
58757		//get device confirmation settings
58758		var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetConfirmationSettings/' + cloverMerchantId;
58759
58760		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
58761			.success(function(data, textStatus, jqXHR) {
58762				isEnabledDeviceGetConfirmation = data.GetConfirmationEnabled;		
58763				isEnabledReceiptConfirmation = data.ReceiptConfirmationEnabled;
58764				
58765				//get device tip settings
58766				var uri = GLO.Link.WebsiteDomain + 'api/Bolt/GetTipPercents/' + cloverMerchantId;
58767
58768				var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
58769					.success(function(data, textStatus, jqXHR) {
58770						var isEnableTip = _isEnableTip(data.TipEnabled, ccArr, tipAmount, totalPrice, isForceDisableTip);
58771						var useListPrice = data.UseListPrice;
58772						if (isEnableTip && tipAmount > 0) {
58773							tipAmount = 0;
58774						}
58775						
58776						SA.POS.CCBolt.TakePayment(cloverMerchantId,ccArr, serialNo, true, cid, smid, scid, baseAmount ,amount, tipAmount, isEnableTip, isEnabledDeviceGetConfirmation,isEnabledReceiptConfirmation,useListPrice, servicesTotalPrice);
58777					})
58778					.error(function(jqXHR, textStatus, errorThrown) {		
58779						new GLO.Popup.Error('Unable to get Tip Settings for device');
58780					});				
58781			})
58782			.error(function(jqXHR, textStatus, errorThrown) {		
58783				new GLO.Popup.Error('Unable to get Confirmation Settings for device');
58784			});
58785
58786
58787	}
58788	
58789	function  _isEnableTip(isEnableTip, ccArr, tipAmount, totalPrice, isForceDisableTip) {
58790		if (!isEnableTip) {
58791			return false;
58792		}
58793		
58794		if (UTIL.parseBool(isForceDisableTip)) {
58795			return false;
58796		} else if (isEnableTip && tipAmount > 0) {
58797			if (ccArr.length > 1) {
58798				return false;
58799			}
58800			
58801			var payto = ccArr[0].pay_to;
58802			var mt = UTIL.coalesceInt(GLO.Data.provider.merchant_type_cd, 0);
58803			
58804			var jPricePop = $('#appt-price-popup').closest('.glopop');
58805			var trpay = jPricePop.find('tr.appt-price-payment-row');
58806			
58807			for (var i=0; i < trpay.length; i++) {
58808				var trPayTo = trpay.eq(i).attr('payment_to_staff_id');
58809				
58810				if (!trpay.eq(i).hasClass('swipe')) {
58811					if (mt < 10 || (mt < 20 && payto == 'h') || (mt < 50 && payto == 'p') || (mt == 50 && payto == trPayTo) ) {
58812						tipAmount = UTIL.coalesceMoney(tipAmount - UTIL.coalesceMoney(trpay.eq(i).attr('original_tip_mn'), trpay.eq(i).attr('tip_mn')));
58813					}
58814				}
58815			}
58816			
58817			if (tipAmount > .01) {
58818				return false;
58819			} else {
58820				ccArr[0].amount = UTIL.coalesceMoney(ccArr[0].amount + ccArr[0].tip);
58821				ccArr[0].tip = tipAmount = 0;
58822			}
58823		}
58824		
58825		return isEnableTip;
58826	}
58827	
58828	function _convertMerchantArrayForBolt(ccArr) {
58829		if (ccArr && ccArr.length) {
58830			for (var i=ccArr.length-1; i >= 0; i--) {
58831				if (UTIL.coalesceMoney(ccArr[i].amount) === 0) {
58832					ccArr.splice(i, 1);
58833				} else {
58834					ccArr[i].amount = UTIL.coalesceMoney(UTIL.coalesceMoney(ccArr[i].amount) - UTIL.coalesceMoney(ccArr[i].tip));
58835				}
58836			}
58837		}
58838		
58839		return ccArr;
58840	}
58841	
58842	_bolt.TakePayment = async function(ccMID,ccArr,serialNo,isSale,cid,multiScheduleId,scid,baseAmount,totalAmount,totalTipAmount,tipOnDeviceEnabled, isEnabledDeviceGetConfirmation,isEnabledReceiptConfirmation,useListPrice,servicesTotalPrice) {
58843		_isConnected = false;
58844		_currentPaymentMerchantIdString = ccMID;
58845		
58846		let chargeAmount = 0;
58847		let chargeTipAmount = 0;
58848		let ticketHasHouseAccount = true;
58849		let overrideMID = ''; //auth override
58850		var isTipFromDevice = false;
58851		
58852		//get the house account mid if on ticket else get the first chair mid on ticket
58853		var houseAccount = ccArr.filter(function(item) { return item.pay_to === 'h';})
58854		if (houseAccount.length > 0 ) {
58855				//ticket has house account
58856				//ccMID = house account MID
58857		}
58858		else
58859		{
58860			ticketHasHouseAccount = false;
58861			houseAccount = GLO.Data.provider.merchants.filter(function(item) { return item.type === 10;})
58862			
58863			if (houseAccount[0].co == 30) {
58864				overrideMID = ccMID;
58865				ccMID = houseAccount[0].idString;
58866			}
58867		}
58868
58869		if (ccArr.length == 1) {
58870			chargeAmount = totalAmount;
58871			chargeTipAmount = totalTipAmount;
58872		}
58873		else {
58874			chargeAmount = (ticketHasHouseAccount) ? houseAccount[0].amount : ccArr[0].amount;
58875			chargeTipAmount = (ticketHasHouseAccount) ? UTIL.coalesceMoney(houseAccount[0].tip) : UTIL.coalesceMoney(ccArr[0].tip);
58876		}
58877
58878		//Steps:
58879		//1. call connect endpoint and get session key
58880		//2. if session key returned, ping device
58881		//3. ask for confirmation if enabled
58882		//4. ask for tip if enabled
58883		//5. run auth
58884		//66. disconnect device and expire session keyS
58885		
58886		 if (!tipOnDeviceEnabled && !isEnabledDeviceGetConfirmation) { //tipping disabled on device
58887			_bolt.connect(ccMID,serialNo)
58888			.then((connectResponse) => {
58889				var json = _processConnectResponse(connectResponse, ccMID, serialNo);
58890				_isConnected = true;
58891				return json;
58892			}).then((pingResponse) => {
58893				var gotoConfirmPrompt = false;
58894				return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice,servicesTotalPrice);
58895			}).then((authResponse) => {
58896				return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, chargeTipAmount,ccArr);
58897			}).then((serverResponse) => {
58898				return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation);
58899			}).then((disconnectOrReceiptResponse) => {
58900				return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation);
58901			}).then((printOrDisconnectResponse) => {
58902				return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId);
58903			}).catch(e => { 
58904				return _processErrorResponse(e, ccMID, serialNo);
58905			});
58906		} else if (tipOnDeviceEnabled && !isEnabledDeviceGetConfirmation) {
58907			_bolt.connect(ccMID,serialNo)
58908			.then((connectResponse) => {
58909				var json = _processConnectResponse(connectResponse, ccMID, serialNo);
58910				_isConnected = true;
58911				return json;
58912			}).then((pingResponse) => {
58913				var gotoConfirmPrompt = false;
58914				return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice, servicesTotalPrice);
58915			}).then((tipResponse) => {
58916				var json = _processTipResponse(tipResponse, ccMID, overrideMID, serialNo, multiScheduleId, totalAmount, ccArr, servicesTotalPrice);
58917				totalTipAmount = UTIL.coalesceMoney(Math.round(UTIL.safeParseJson(tipResponse).tip) / 100);
58918				isTipFromDevice = (totalTipAmount > 0);
58919				return json;
58920			}).then((authResponse) => {
58921				return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr, isTipFromDevice);
58922			}).then((serverResponse) => {
58923				return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation);
58924			}).then((disconnectOrReceiptResponse) => {
58925				return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation);
58926			}).then((printOrDisconnectResponse) => {
58927				return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId);
58928			}).catch(e => { 
58929				return _processErrorResponse(e, ccMID, serialNo);
58930			});
58931		} else if (!tipOnDeviceEnabled && isEnabledDeviceGetConfirmation) {
58932			_bolt.connect(ccMID,serialNo)
58933			.then((connectResponse) => {
58934				var json = _processConnectResponse(connectResponse, ccMID, serialNo);
58935				_isConnected = true;
58936				return json;
58937			}).then((pingResponse) => {
58938				var gotoConfirmPrompt = true;
58939				return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice,servicesTotalPrice);
58940			}).then((readConfirmationResponse) => {
58941				return _processReadConfirmationResponse(readConfirmationResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, totalAmount, tipOnDeviceEnabled, ccArr, useListPrice, servicesTotalPrice);
58942			}).then((authResponse) => {
58943				return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, chargeTipAmount,ccArr);
58944			}).then((serverResponse) => {
58945				return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation);
58946			}).then((disconnectOrReceiptResponse) => {
58947				return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation);
58948			}).then((printOrDisconnectResponse) => {
58949				return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId);
58950			}).catch(e => { 
58951				return _processErrorResponse(e, ccMID, serialNo);
58952			});
58953		} else if (tipOnDeviceEnabled && isEnabledDeviceGetConfirmation) {
58954			_bolt.connect(ccMID,serialNo)
58955			.then((connectResponse) => {
58956				var json = _processConnectResponse(connectResponse, ccMID, serialNo);
58957				_isConnected = true;
58958				return json;
58959			}).then((pingResponse) => {
58960				var gotoConfirmPrompt = true;
58961				return _processPingResponse(pingResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount,totalAmount, tipOnDeviceEnabled, gotoConfirmPrompt, ccArr, useListPrice,servicesTotalPrice);
58962			}).then((readConfirmationResponse) => {
58963				return _processReadConfirmationResponse(readConfirmationResponse, ccMID, overrideMID, serialNo, multiScheduleId, baseAmount, totalAmount, tipOnDeviceEnabled, ccArr, useListPrice, servicesTotalPrice);
58964			}).then((tipResponse) => {
58965				var json = _processTipResponse(tipResponse, ccMID, overrideMID, serialNo, multiScheduleId, totalAmount, ccArr, servicesTotalPrice);
58966				totalTipAmount = UTIL.coalesceMoney(Math.round(UTIL.safeParseJson(tipResponse).tip) / 100);
58967				isTipFromDevice = (totalTipAmount > 0);
58968				return json;
58969			}).then((authResponse) => {
58970				return _processAuthResponse(authResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr, isTipFromDevice);
58971			}).then((serverResponse) => {
58972				return _processServerResponse(serverResponse, ccMID, overrideMID, serialNo, isSale, cid, multiScheduleId, scid, chargeAmount, totalTipAmount,ccArr,isEnabledReceiptConfirmation);
58973			}).then((disconnectOrReceiptResponse) => {
58974				return _processAskReceiptOrDisconnectResponse(disconnectOrReceiptResponse,ccMID,serialNo,multiScheduleId,isEnabledReceiptConfirmation);
58975			}).then((printOrDisconnectResponse) => {
58976				return _processPrintOrDisconnectResponse(printOrDisconnectResponse,ccMID,serialNo,multiScheduleId);
58977			}).catch(e => { 
58978				return _processErrorResponse(e, ccMID, serialNo);
58979			});
58980		} else {
58981			//do nothing
58982		}
58983	}
58984
58985
58986	_bolt.PrintReceipt = async function(ccMID, serialNo, multiScheduleId, retryAttempt) {
58987		_isConnected = false;
58988		var isConnectInProgress = true;
58989		
58990		//Steps:
58991		//1. call connect endpoint and get session key
58992		//2. if session key returned, ping device
58993		//3. run print receipt
58994		//4. disconnect device and expire session keyS
58995		
58996			_bolt.connect(ccMID,serialNo)
58997			.then((connectResponse) => {
58998				var json = _processConnectResponse(connectResponse, ccMID, serialNo);
58999				_isConnected = true;
59000				isConnectInProgress = false;
59001				return json;
59002			}).then((pingResponse) => {
59003				return _processPingResponseForPrint(pingResponse, ccMID, serialNo, multiScheduleId);
59004			}).then((printResponse) => {
59005				return _processPrintResponse(printResponse, ccMID, serialNo, multiScheduleId);
59006			}).then((disconnectResponse) => {
59007				return _processDisconnectResponse(disconnectResponse);
59008			}).catch(e => { 
59009				if (isConnectInProgress && UTIL.coalesceInt(retryAttempt, 0) === 0) {			//= if client very quickly removes card after card processed clover mini often still in use.
59010					setTimeout(function() {
59011						SA.POS.CCBolt.PrintReceipt(ccMID, serialNo, multiScheduleId, 1);
59012					}, 2500);
59013				} else {
59014					return _processErrorResponse(e, ccMID, serialNo, true);
59015				}
59016			});
59017	}
59018
59019	_bolt.cancel = function(serialNo) {
59020		var ccMID = GLO.Data.provider.merchants[0].idString;				//UTIL.coalesceString(_currentPaymentMerchantIdString, GLO.Data.provider.merchants[0].idString);
59021		
59022		if (!ccMID) {
59023			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
59024			return;
59025		}
59026		
59027		if (UTIL.isEmpty(serialNo)) {
59028			GLO.Log.insertSimple('Bolt.Cancel with No Serial Number', 'Bolt.Cancel with Empty Serial Number', 'medium');
59029			return;
59030		}
59031		
59032		var uri = GLO.Link.WebsiteDomain + 'api/bolt/cancel/' + ccMID + '/' + serialNo;
59033
59034		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: null, dataType: 'json' })
59035		.success(function(data, textStatus, jqXHR) {
59036			window.onbeforeunload = null;
59037			return data;
59038		})
59039		.error(function(jqXHR, textStatus, errorThrown) {
59040			GLO.UI.Form.resetProcessing(); 		
59041			
59042			if ($('.pop-error.glopop').length === 0) {
59043				GLO.Popup.Error.open('Unable to cancel cardconnect transaction', 'Credit Card Reader');
59044			}
59045		});
59046
59047	}
59048
59049	_bolt.getDeviceSerialNo = function() {
59050		var name = 'boltdevice' + "=";
59051		var decodedCookie = decodeURIComponent(document.cookie);
59052		var ca = decodedCookie.split(';');
59053		for(var i = 0; i <ca.length; i++) {
59054		  var c = ca[i];
59055		  while (c.charAt(0) == ' ') {
59056			c = c.substring(1);
59057		  }
59058		  if (c.indexOf(name) == 0) {
59059			return c.substring(name.length, c.length);
59060		  }
59061		}
59062		return "";
59063	}
59064
59065	_bolt.getReceipt = function(ccMID,serialNo,multiScheduleId,amount) {
59066
59067		if (!ccMID) {
59068			new GLO.Popup.Error('CardConnect MID not found. Please refresh page and try again.');
59069			return;
59070		}
59071
59072		var uri = GLO.Link.WebsiteDomain + 'api/bolt/getreceiptjson/' + ccMID + '/' + serialNo;
59073		var payload = {"multiScheduleId": multiScheduleId , "amount": amount};
59074		var jqxhr = $.ajax({ type: "GET", url: uri, "cache": false, data: payload, dataType: 'json' })
59075		.success(function(data, textStatus, jqXHR) {
59076			window.onbeforeunload = null;
59077			return data;
59078		})
59079		.error(function(jqXHR, textStatus, errorThrown) {
59080			GLO.UI.Form.resetProcessing(); 		
59081			new GLO.Popup.Error('Unable to Ping device');
59082		});
59083
59084	}
59085
59086	_bolt.ClientCheckIn = function() {
59087		//TODO: CLIENT CHECK-IN FLOW 
59088	}
59089
59090	function _displayEmvCommunicateError(msg, h1, isCloseSwipePopup) {					        //only display warning if has swipe popup open (+ not processing card-on-file)
59091		if ($('#appt-price-swipe-ready').closest('.glopop').length > 0) {
59092			if ($('#pop-card-on-file-view').closest('.glopop').length === 0 && $('#btnUseCardOnFile.btnProcessing4').length === 0) {
59093				if ($('#pop-warn-emv-communicate').length === 0 && $('.pop-error.glopop, .pop-warning.glopop').length === 0) {
59094					h1 = UTIL.coalesceString(h1, 'Payment Processing Warning');
59095					msg = '<div id="pop-warn-emv-communicate">' + msg + '</div>';
59096					GLO.Popup.Warning.open(msg, h1);
59097	            	
59098	            	if (isCloseSwipePopup) {
59099	            		UserPortal.Price.Payment.closeSwipePopup(true);
59100	            	}
59101	            	
59102					return true;
59103				}
59104			}
59105		}
59106	}
59107
59108	return _bolt;
59109})();
59110
59111SA.Ticket = (function() {
59112    function _conTicket() { }
59113    var _addLineToHeaderTimeout = null, _isLoading = false, _time = null;
59114    
59115    var _timeoutApplyDiscounts = null;
59116    var _serviceXml = '';			//<tr>
59117    var _productXml = '';			//<ul> <li>
59118	var _paymentXml = '';			//<ol> <lp>
59119	var _discountXml = '';			//<dl> <dd>
59120	var _multiTicketXml = '';		//<ml> <mt>
59121	var _clientTagXml = null, _clientTagRelationshipXml = null;			//<tags> <tag> | <rl> <li>
59122	
59123	_conTicket.discountDelArray = [];
59124	_conTicket.bookingNumber = null; _conTicket.createDate = null; _conTicket.lastUpdateDate = null;
59125	_conTicket.clientId = null; _conTicket.clientName = null; _conTicket.clientType = null;		//POS only supports client buyers: _conTicket.staffId = null; _conTicket.staffName = null;
59126	_conTicket.promoCode = null; _conTicket.isCustomDiscount = false; _conTicket.waitId = null;
59127	_conTicket.memberServiceXml = null;
59128	
59129	var _deleteInventoryXml = '', _deleteScheduleIds = '';
59130	var _initialPayment = 0, _originalTotal = 0, _productTip = 0;
59131    var _cftid = null, _membershipId = null, _giftBalance = 0, _birthDays = null;
59132    var _clientLoyalty = 0, _ticketLoyalty = 0, _availableLoyalty = 0;
59133    var _lastServiceStart = null, _lastServiceEnd = null;		//= only used when open/save ticket.
59134    
59135    var _apptStatus = null, _dtCheckin = null, _dtCheckout = null, _dtSignin = null;
59136    var _clientNote = '', _staffNote = '', _dtDue = null, _scheduleRecurId = null, _imageCount = 0, _providerReferral = null;
59137	var _discountCount = 0; _referralDiscount = 0;
59138	
59139	_conTicket.getTotalPrice = function() {
59140		var jticket = $('#pos-ticket');
59141		return UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''));
59142	}
59143	_conTicket.getTotalPayment = function() {
59144		var lp = $('<ol>' + _paymentXml + '</ol>').find('lp');
59145		var payment = 0;
59146		
59147		for (var i=0; i < lp.length; i++) {
59148			payment += UTIL.coalesceMoney(lp.eq(i).attr('payment_mn'));
59149		}
59150		
59151		return UTIL.coalesceMoney(payment);
59152	}
59153	_conTicket.getTime = function() {
59154		return _time;
59155	}
59156	_conTicket.getPaymentDate = function() {
59157		var lp = $('<ol>' + _paymentXml + '</ol>').find('lp');
59158		
59159		for (var i=0; i < lp.length; i++) {
59160			var payment = UTIL.coalesceMoney(lp.eq(i).attr('payment_mn'));
59161			
59162			if (payment > 0) {
59163				return new Date(lp.eq(i).attr('create_dt'));
59164			}
59165		}
59166		
59167		return null;
59168	}
59169	
59170	_conTicket.getPaymentXml = function() {
59171		return _paymentXml;			// $('<ol>' + _paymentXml + '</ol>').find('lp');
59172	}
59173	function _getDiscountXml(isAddActive) {
59174    	if (!UTIL.isEmpty(_discountXml)) {
59175	    	var dxml = $('<dl>' + _discountXml + '</dl>');
59176	    	
59177	    	if (isAddActive) {
59178		    	var dd = dxml.find('dd');
59179		    	
59180		    	for (var i=0; i < dd.length; i++) {
59181		    		dd.eq(i).attr('is_active_fl', '1');
59182		    	}
59183	    	}
59184	    	
59185	    	return dxml.outerHTML();
59186    	} else {
59187    		return '';
59188    	}
59189    }
59190	_conTicket.getDiscountArray = function() {
59191		var isPaid = UserPortal.Price.isTicketHasCheckout();
59192		var dxml = $('<dl>' + _discountXml + '</dl>');
59193		
59194		return UserPortal.Price.Discount.addXml(dxml, isPaid);
59195	}
59196	_conTicket.setDiscountXml = function(discountArray, discountXml) {
59197		if (!UTIL.isEmpty(discountXml)) {
59198			if (discountXml.html) {
59199				_discountXml = discountXml.html();
59200			} else {
59201				_discountXml = discountXml;
59202			}
59203		} else if (discountArray && discountArray.length) {
59204			var dxml = UserPortal.Price.Discount.arrayToXml(discountArray);
59205			
59206			if (!UTIL.isEmpty(dxml)) {
59207				_discountXml = $(dxml).html();
59208			} else {
59209				_discountXml = '';
59210			}
59211		} else {
59212			_discountXml = '';
59213			return;
59214		}
59215		
59216		_conTicket.recalculateDiscountTotal();
59217	}
59218	_conTicket.getDiscountValues = function() {
59219		var jlines = $('#pos-ticket-order').find('.pos-ticket-line-item');
59220		var totalLineItemDiscount = 0, totalLineItemFee = 0;
59221		
59222		for (var l=0; l < jlines.length; l++) {
59223			var jl = jlines.eq(l);
59224			var cnt = UTIL.coalesceInt(jl.find('.line-item-amount').val(), 1);
59225			
59226			var addOnFee = UTIL.coalesceMoney(jl.attr('add_on_fee_mn'));
59227			var discount = UTIL.coalesceMoney(jl.attr('new_discount_mn'), jl.attr('discount_mn'));
59228			
59229			totalLineItemFee = UTIL.coalesceMoney(cnt * addOnFee + totalLineItemFee);
59230			totalLineItemDiscount = UTIL.coalesceMoney(cnt * discount + totalLineItemDiscount);
59231		}
59232		
59233		return { "discount_mn": totalLineItemDiscount, "add_on_fee_mn": totalLineItemFee };
59234	}
59235	_conTicket.updateDiscountAttributes = function() {			//= use for debugging
59236		var dds = $('<dl>' + _discountXml + '</dl>').find('dd');
59237		var totalDiscount = 0, totalFee = 0;
59238		
59239		for (var i=0; i < dds.length; i++) {
59240			var dd = dds.eq(i);
59241			var dmn = UTIL.coalesceMoney(dd.attr('discount_mn')), dpct = UTIL.coalesceFloat(dd.attr('discount_pct'));
59242			
59243			_setDiscountTicketAttributes(dd);
59244			
59245			if (dmn < 0 || dpct < 0) {
59246				totalFee = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('fee_amount_mn'), dd.attr('amount_mn')) + totalFee);
59247			} else {
59248				totalDiscount = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('amount_mn')) + totalDiscount);
59249			}
59250		}
59251		
59252		return { "discount_mn": totalDiscount, "add_on_fee_mn": totalFee };
59253	}
59254	_conTicket.recalculateDiscountTotal = function() {
59255		if (UserPortal.Price.isTicketHasCheckout()) {
59256			return;
59257		}
59258		
59259		var totalFromLineItems = _conTicket.getDiscountValues();
59260		var totalFromDiscountItems = _conTicket.updateDiscountAttributes();
59261		
59262		var dLine = totalFromLineItems.discount_mn;
59263		var fLine = totalFromLineItems.add_on_fee_mn;
59264		
59265		var dItem = totalFromDiscountItems.discount_mn;
59266		var fItem = totalFromDiscountItems.add_on_fee_mn;
59267		
59268		/* if (!_isLoading && (dLine != dItem || fLine != fItem)) {
59269			var msg = 'P' + _conTicket.bookingNumber + ' diff in POS, discount = ' + UTIL.displayMoney(dLine - dItem) + ': ' + dLine + ' / ' + dItem;
59270			msg += ' | add-on fee = ' + UTIL.displayMoney(fLine - fItem) + ': ' + fLine + ' / ' + fItem;
59271			GLO.Log.insertSimple('Recalculate Discount Diff in POS', msg, 'high');
59272		} */
59273		
59274		//totalFromLineItems.discount_mn = UTIL.coalesceMoney(totalFromLineItems.discount_mn + _conTicket.getReferralDiscount());
59275		_conTicket.setDiscountUI(totalFromLineItems);
59276	}
59277	_conTicket.removeDiscount = function(providerDiscountId, scheduleDiscountId) {
59278		var arrd = _conTicket.getDiscountArray();
59279		
59280		for (var i=0; i < arrd.length; i++) {
59281			if (scheduleDiscountId = arrd[i].schedule_discount_id || (UTIL.isEmpty(scheduleDiscountId) && providerDiscountId == arrd[i].provider_discount_id)) {
59282				arrd.splice(i, 1);
59283			}
59284		}
59285		
59286		_conTicket.setDiscountXml(arrd);
59287	}
59288	_conTicket.updateDiscountAttribute = function(pdid, sdid, rowIndex, attributeName, attributeValue) {
59289		var arrd = _conTicket.getDiscountArray();
59290		
59291		for (var i=0; i < arrd.length; i++) {
59292			if (sdid = arrd[i].schedule_discount_id) {
59293				arrd[i][attributeName] = attributeValue;
59294				break;
59295			} else if (UTIL.isEmpty(sdid) && pdid == arrd[i].provider_discount_id && i == rowIndex) {
59296				arrd[i][attributeName] = attributeValue;
59297				break;
59298			}
59299		}
59300		
59301		_conTicket.setDiscountXml(arrd);
59302		_conTicket.recalculateDiscountTotal();
59303	}
59304	_conTicket.getServiceAttribute = function(rowIndex, attributeName) {
59305		return $('#pos-ticket').find('.pos-service-line-item').eq(rowIndex).attr(attributeName);
59306	}
59307	_conTicket.setServiceAttribute = function(rowIndex, attributeName, attributeValue) {
59308		$('#pos-ticket').find('.pos-service-line-item').eq(rowIndex).attr(attributeName, attributeValue);
59309	}
59310	_conTicket.setDiscountAttribute = function(rowIndex, attributeName, attributeValue) {
59311		var arrd = SA.Ticket.getDiscountArray();
59312		
59313		if (arrd && arrd[rowIndex]) {
59314			arrd[rowIndex][attributeName] = attributeValue;
59315			SA.Ticket.setDiscountXml(arrd);
59316		}
59317	}
59318	function _setDiscountTicketAttributes(dd) {
59319		var promo = dd.attr('promo_code_vc');
59320		_conTicket.promoCode = UTIL.coalesceString(promo, _conTicket.promoCode);
59321		
59322		if (UTIL.parseBool(dd.attr('custom_discount_fl'))) {
59323			_conTicket.isCustomDiscount = true;
59324		}
59325	}
59326	_conTicket.addDiscountToXml = function(discountObject) {
59327		var arr = _conTicket.getDiscountArray();
59328		arr.push(discountObject);
59329		_conTicket.setDiscountXml(arr);
59330	}
59331	
59332	_conTicket.getCheckoutDate = function() {
59333		var svcCount = $('#pos-ticket').find('.pos-service-line-item').length;
59334		
59335		if (svcCount > 0) {
59336			return _dtCheckout;
59337		} else if (SA.Ticket.getTotalPayment() >= SA.Ticket.getTotalPrice()) {
59338			return _conTicket.getPaymentDate();
59339		}
59340	}
59341	_conTicket.getReferralId = function() {
59342		return _providerReferral;
59343	}
59344	_conTicket.getMembershipId = function() {
59345		return _membershipId;
59346	}
59347	_conTicket.getBirthDays = function() {
59348		return _birthDays;
59349	}
59350	
59351	function _getTicketInventoryXml(jproducts, isIncludeUL, serviceCount) {
59352    	if (jproducts.length > 0) {
59353	    	var ixml = '';
59354			
59355			for (var i=0; i < jproducts.length; i++) {
59356				var jp = jproducts.eq(i);
59357				ixml += _openAddLineItem(jp);
59358			}
59359			
59360			if (isIncludeUL) {
59361				return '<ul>' + ixml + '</ul>';
59362			} else {
59363				return ixml;
59364			}
59365		} else {
59366			return '';
59367		}
59368    }
59369    _conTicket.getProductXml = function() {
59370		var jtix = $('#pos-ticket');
59371		var jproducts = jtix.find('.pos-ticket-line-item:not(.pos-service-line-item)');			//.pos-product-line-item
59372		var serviceCount = jtix.find('.pos-ticket-line-item.pos-service-line-item').length;
59373		
59374		return  _getTicketInventoryXml(jproducts, false, serviceCount);							//UserPortal.Price.inventoryXml
59375		//return _productXml;
59376	}
59377	_conTicket.setProductXml = function(xml) {
59378		var jproducts = $('#pos-ticket').find('.pos-product-line-item');
59379		var jli = $('<ul>' + xml + '</ul>').find('li');
59380		var hasUpdate = false;
59381		
59382		for (var p=0; p < jproducts.length; p++) {
59383			for (var i=0; i < jli.length; i++) {
59384				var siid = jproducts.eq(p).attr('schedule_inventory_id');
59385				
59386				if (siid == jli.eq(i).attr('schedule_inventory_id') || (UTIL.isEmpty(siid) && jproducts.eq(p).attr('inventory_id') == jli.eq(i).attr('inventory_id')) ) {
59387					hasUpdate = true;
59388					var addOnFee = jli.eq(i).attr('add_on_fee_mn');
59389					var discount = jli.eq(i).attr('discount_mn');
59390					var newDiscount = jli.eq(i).attr('new_discount_mn');
59391					
59392					if (!UTIL.isEmpty(addOnFee)) {
59393						jproducts.eq(p).attr('add_on_fee_mn', addOnFee);
59394					} else {
59395						jproducts.eq(p).removeAttr('add_on_fee_mn');
59396					}
59397					
59398					if (!UTIL.isEmpty(discount)) {
59399						jproducts.eq(p).attr('discount_mn', discount);
59400					} else {
59401						jproducts.eq(p).removeAttr('discount_mn');
59402					}
59403					
59404					if (!UTIL.isEmpty(newDiscount)) {
59405						jproducts.eq(p).attr('new_discount_mn', newDiscount);
59406					} else {
59407						jproducts.eq(p).removeAttr('new_discount_mn');
59408					}
59409				}
59410			}
59411		}
59412		
59413		if (hasUpdate) {
59414			//?? ToDo: update _productXml ??
59415		}
59416	}
59417	
59418	_conTicket.adjustMultiTicketTotal = function() {
59419		if (_multiTicketXml.length > 0 && _multiTicketXml.find('mt').length > 0) {
59420			var jticket = $('#pos-ticket');
59421			var jtickets = jticket.find('.multi-ticket-row');
59422			var totalDue = 0;
59423			//var thisTicketTotal = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''))
59424			
59425			for (var m = 0; m < jtickets.length; m++) {
59426				totalDue += UTIL.coalesceMoney(jtickets.eq(m).find('.multi-ticket-row-due').text().replace('$', ''))
59427			}
59428			
59429			_setMultiTicketTotal(totalDue);
59430		}
59431	}
59432	
59433    _conTicket.loadTicket = function(data) {
59434    	_conTicket.reset();
59435    	var jticket = $('#pos-ticket').addClass('is-loading');
59436    	var btnViewTicket = jticket.find('#btnViewTicket');
59437    	
59438    	GLO.UI.Form.beginProcessing(btnViewTicket);
59439    	_conTicket.displayTicket();
59440    	
59441    	setTimeout(function() {
59442	    	_isLoading = true;
59443	    	var isTicketDataLoaded = _loadTicketData(data);
59444	    	_isLoading = false;
59445	    	
59446	    	if (isTicketDataLoaded) {
59447		    	_conTicket.recalculate();
59448		    	_conTicket.recalculateDiscountTotal();
59449		    	_originalTotal = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''));
59450		    	
59451		    	jticket.find('#btnSaveTicket > a.unsaved-change').removeClass('unsaved-change');
59452		    	_setBookingNumber();
59453	    	}
59454	    	
59455	    	GLO.UI.Form.resetProcessing(btnViewTicket);
59456		    GLO.Popup.closeIfExist($('#pop-processing-view-in-pos').closest('.glopop'));
59457    	}, 20);
59458    }
59459    function _loadTicketData(data) {
59460    	var jticket = $('#pos-ticket');
59461    	var jd = $('<div>' + data + '</div>');
59462    	var pnotes = jd.find('p');					//note fields on product-only ticket
59463    	var h2 = jd.find('h2');
59464    	
59465    	if (h2.length === 0) {
59466    		h2 = $(data).eq(0);			//= use first <tr>
59467    	}
59468    	
59469    	_serviceXml = $('<tbody>' + data + '</tbody>').find('tr');			// $(data);
59470    	_productXml = jd.find('ul li');
59471    	_multiTicketXml = jd.find('ml');
59472		
59473		_loadTagXml(jd);
59474    	_loadMain(jticket, h2, pnotes);
59475    	_loadDiscountRows(jticket, jd, h2);
59476    	_loadPaymentRows(jd, h2);
59477    	_loadServiceRows();
59478    	
59479    	if (_loadProductRows()) {				//= has products that can be loaded in POS Screen or has no products
59480	    	_finishAddProductOrService();
59481	    	
59482	    	_conTicket.applyDiscounts(10, true);
59483	    	_originalTotal = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''));
59484	    	_conTicket.setStaffHeader();
59485	    	
59486	    	setTimeout(function() {
59487	    		$('#pos-ticket').removeClass('is-loading');
59488	    	}, 1500);
59489	    	
59490	    	return true;
59491    	} else {
59492    		jticket.removeClass('is-loading');
59493    		return false;
59494    	}
59495    }
59496    _conTicket.setStaffHeader = function() {
59497    	var jticket = $('#pos-ticket');
59498    	var jservices = jticket.find('.pos-service-line-item');
59499    	
59500    	if (jservices.length > 0) {
59501	    	var tip = 0, isClientRequest = false, currentStaffId = jservices.eq(0).attr('staff_id');
59502	    	
59503	    	for (var i=0; i < jservices.length; i++) {
59504	    		var jsvc = jservices.eq(i);
59505	    		var newStaffId = jsvc.attr('staff_id');
59506	    		
59507	    		if (currentStaffId != newStaffId) {
59508	    			_setStaffHeader2(jticket, currentStaffId, tip, isClientRequest);
59509	    			currentStaffId = newStaffId;
59510	    			tip = isClientRequest = 0;
59511	    		}
59512	    		
59513	    		//tip += UTIL.coalesceMoney(jsvc.attr('tip_mn'));
59514	    		//if (UTIL.parseBool(jsvc.attr('client_request_fl'))) { isClientRequest = true; }
59515	    		isClientRequest = _conTicket.getIsClientRequest(newStaffId);
59516	    	}
59517	    	
59518	    	_setStaffHeader2(jticket, currentStaffId, tip, isClientRequest);
59519    	}
59520    }
59521    function _setStaffHeader2(jticket, currentStaffId, tip, isClientRequest) {
59522    	var jStaffRow = jticket.find('#staff-row-' + currentStaffId);
59523		_setStaffHeaderTip(jStaffRow, tip);
59524		_setStaffHeaderClientRequest(jStaffRow, isClientRequest);
59525    }
59526    function _setStaffHeaderTip(jStaffRow, tip) {
59527    	if (tip > 0) {
59528			tip = UTIL.coalesceMoney(tip);
59529			var tipHtm = '<b class="staff-row-tip-amount" title="Tip = $' + tip + '"><i class="plus-sign">+</i><span class="dollar-sign">$</span><i>' + tip + '</i></b>';
59530			
59531			jStaffRow.append(tipHtm);
59532		} else {
59533			jStaffRow.find('.staff-row-tip-amount').remove();
59534		}
59535    }
59536    function _setStaffHeaderClientRequest(jStaffRow, isClientRequest) {
59537    	if (UTIL.parseBool(isClientRequest)) {
59538			var htm = '<span class="staff-row-client-request" title="Is Client Request"> <b class="checkmark-icon"></b> </span>';
59539			
59540			jStaffRow.addClass('is-client-request').prepend(htm);
59541		} else {
59542			jStaffRow.removeClass('is-client-request').find('.staff-row-client-request').remove();
59543		}
59544    }
59545    function _loadMain(jticket, h2, pnotes) {
59546    	SA.Ticket.resetDate();
59547    	var serviceCount = 0;
59548    	
59549    	if (_serviceXml && _serviceXml.length > 0) {
59550    		serviceCount = _serviceXml.length;
59551    	}
59552    	
59553    	if (h2.length > 0) {
59554    		var jmain = h2;
59555    		var day = h2.attr('appt_dt'), tm = h2.attr('time_vc');
59556    		//product_tip_mn
59557    	} else if (_serviceXml && _serviceXml.length > 0) {
59558    		var jmain = _serviceXml.eq(0);
59559    		var day = _serviceXml.eq(0).attr('appt_dt'), tm = _serviceXml.eq(0).attr('time_vc');
59560    		//var _dtCheckin = null, _dtCheckout = null, _dtSignin = null, _scheduleRecurId = null;
59561    	} else {
59562    		return;
59563    	}
59564    	
59565    	if (UTIL.isDate(day) && UTIL.isValidTime(tm)) {
59566			SA.Ticket.setStartDate(day, tm);
59567		}
59568    	
59569    	_loadTicketSpecific(jticket, jmain, serviceCount);
59570    	_loadNotes(jmain, pnotes);
59571    	_loadClientSpecific(jmain);
59572    	_displayTags();
59573    	
59574    	var clientAttributes = _displayClientAttributes();
59575    	_loadMultiTicket(clientAttributes);
59576    }
59577    function _loadMultiTicket(clientAttributes) {
59578    	if (_multiTicketXml.length > 0) {
59579    		var jcontainer = $('#pos-ticket-client-attributes').removeClass('hide');
59580	    	var mts = _multiTicketXml.find('mt');
59581	    	var icon = '<span class="multi-ticket-icon-container" title="' + UTIL.pluralLabel(mts.length, 'Linked Ticket') + '"></span>';	    	//$('#pos-ticket-client-header').prepend(icon);
59582	    	var totalDue = 0;
59583	    	
59584	    	for (var m = 0; m < mts.length; m++) {
59585	    		var mt = mts.eq(m);
59586	    		var smid = mt.attr('schedule_multi_id');
59587				var svcCount = mt.attr('service_count_sr');
59588				var cid = mt.attr('client_id');
59589				var cname = mt.attr('client_vc');
59590				
59591				var due = UTIL.coalesceMoney(UTIL.coalesceMoney(mt.attr('service_mn')) + UTIL.coalesceMoney(mt.attr('product_mn')) 
59592						- UTIL.coalesceMoney(mt.attr('discount_mn')) + UTIL.coalesceMoney(mt.attr('fee_mn')) 
59593						+ UTIL.coalesceMoney(mt.attr('tax_mn')) + UTIL.coalesceMoney(mt.attr('tip_mn')) - UTIL.coalesceMoney(mt.attr('payment_mn')));
59594				var fn = 'UserPortal.Price.MultiTicket.gotoTicket(' + smid + ', null, ' + cid + ', ' + svcCount + ', false)';
59595				
59596				if (due > 0) {
59597					var htmDue = '<b class="multi-ticket-row-due">$' + due + '</b>';
59598				} else {
59599					var htmDue = '<b class="multi-ticket-row-paid">PAID</b>';
59600				}
59601				
59602				var htmClient = '<b class="multi-ticket-row-client">' + UTIL.maxString(cname, 12, true) + '</b>';
59603				var htm = '<div class="multi-ticket-row" onclick="' + fn + '">' + icon + htmClient + htmDue + '</div>';
59604				jcontainer.append(htm);
59605				totalDue += due;
59606			}
59607			
59608			_setMultiTicketTotal(totalDue);
59609    	}
59610    }
59611    function _setMultiTicketTotal(totalDue) {
59612    	var jcontainer = $('#pos-ticket-client-attributes');
59613		var jticket = $('#pos-ticket');
59614		
59615    	var thisTicketPrice = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''));
59616    	var thisTicketPayment = UTIL.coalesceMoney(jticket.find('#pos-ticket-header-paid-amount').text().replace('$', ''));
59617		var due = UTIL.coalesceMoney(totalDue + thisTicketPrice - thisTicketPayment);
59618		
59619		if (due > 0) {
59620			var cssTotal = 'multi-ticket-total-due', htmTotal = '<label>Total Due</label> <b class="multi-ticket-row-due">' + UTIL.displayMoney(due) + '</b>';
59621		} else {
59622			var cssTotal = 'multi-ticket-total-paid', htmTotal = '<label>Total </label> <b class="multi-ticket-row-paid">PAID</b>';
59623		}
59624		
59625		jcontainer.find('.multi-ticket-row-total').remove();
59626		jcontainer.append('<div class="multi-ticket-row-total ' + cssTotal + '">' + htmTotal + '</div>');
59627    }
59628    function _loadTicketSpecific(jticket, jmain, serviceCount) {
59629    	var smid = jmain.attr('schedule_multi_id');
59630    	jticket.attr('schedule_multi_id', smid);
59631    	_apptStatus = _getApptStatus(smid, jmain.attr('appt_status_cd'));
59632    	
59633    	_conTicket.bookingNumber = UTIL.cleanString(jmain.attr('booking_nr'));
59634    	_conTicket.createDate = jmain.attr('create_dt');
59635    	_conTicket.lastUpdateDate = UTIL.coalesceString(jmain.attr('last_update_dt'), jmain.attr('update_dt'));
59636    	
59637    	_imageCount = UTIL.coalesceInt(jmain.attr('image_count_sr'), 0);
59638    	_productTip = UTIL.coalesceMoney(jmain.attr('product_tip_mn'));
59639    	_providerReferral = jmain.attr('provider_referral_id');
59640    	_scheduleRecurId = jmain.attr('schedule_recur_id');
59641    	
59642    	if (UTIL.isDate(jmain.attr('checkin_dt'))) { _dtCheckin = jmain.attr('checkin_dt'); }
59643    	if (UTIL.isDate(jmain.attr('checkout_dt'))) { _dtCheckout = jmain.attr('checkout_dt'); }
59644    	if (UTIL.isDate(jmain.attr('signin_dt'))) { _dtSignin = jmain.attr('signin_dt'); }
59645    	
59646    	if (UTIL.isDate(jmain.attr('due_dt'))) {
59647    		_dtDue = new Date(jmain.attr('due_dt'));
59648    		
59649    		if (serviceCount == 0) {
59650    			$('#pos #Ticket_day').val(_dtDue.toGloDate());
59651    		}
59652    	}
59653    }
59654	function _loadNotes(jmain, jnotes) {
59655		var clientNote = jmain.attr('special_request_vcl');
59656		var staffNote  = jmain.attr('staff_only_note_vc');
59657		
59658		for (var i=0; i < jnotes.length; i++) {
59659			if (jnotes.eq(i).attr('id') == 'ticket-client-note') {
59660				clientNote = UTIL.coalesceString(clientNote, jnotes.eq(i).text());
59661			}
59662			
59663			if (jnotes.eq(i).attr('id') == 'ticket-staff-note') {
59664				staffNote = UTIL.coalesceString(staffNote, jnotes.eq(i).text());
59665			}
59666		}
59667		
59668    	if (!UTIL.isEmpty(clientNote)) {
59669    		_clientNote = clientNote;
59670    		SA.Ticket.loadClientNote('appt-request', _clientNote);
59671    	}
59672        
59673        if (!UTIL.isEmpty(staffNote)) {
59674        	_staffNote = staffNote;
59675        	SA.Ticket.loadClientNote('appt-staff-only', _staffNote);
59676        }
59677        
59678        if (!UTIL.isEmpty(jmain.attr('staff_note_vcl'))) {
59679        	var staffNotePopup = jmain.attr('staff_note_vcl');
59680        	
59681        	if (!UTIL.isEmpty(staffNotePopup)) {
59682        		SA.Ticket.loadClientNote('client-important-note', staffNotePopup);		//UserPortal.displayClientStaffNote(staffNotePopup, true);
59683        	}
59684        }
59685    }
59686    function _loadClientSpecific(jmain) {
59687    	_conTicket.clientId = UTIL.cleanString(jmain.attr('client_id'));
59688    	_conTicket.clientName = UTIL.cleanString(jmain.attr('client_vc'));
59689    	_conTicket.clientType = UTIL.cleanString(jmain.attr('client_type_cd'));
59690    	
59691    	_clientLoyalty = UTIL.coalesceInt(jmain.attr('client_loyalty_nr'), 0);
59692    	_ticketLoyalty = UTIL.coalesceInt(jmain.attr('ticket_loyalty_nr'), 0);
59693    	_availableLoyalty = UTIL.coalesceInt(jmain.attr('available_loyalty_nr'), 0);
59694    	
59695    	_cftid = UTIL.coalesceInt(jmain.attr('card_on_file_tid'), jmain.attr('cftid'));
59696    	_membershipId = jmain.attr('membership_id');
59697    	_giftBalance = jmain.attr('gift_balance_mn');
59698    	_birthDays = jmain.attr('birth_sr');
59699    	
59700    	var hasNote = (UTIL.parseBool(jmain.attr('warning_see_note_fl')));
59701    	var tagCount = UTIL.coalesceInt(jmain.attr('tag_count_sr'), 0);
59702    	_addClientComplete2(hasNote, tagCount);
59703    }
59704    function _displayClientAttributes() {
59705    	//LATER: _scheduleRecurId, _imageCount, _providerReferral
59706		
59707    	var jch = $('#pos-ticket-client-header');
59708    	var jca = $('#pos-ticket-client-attributes');
59709    	var attributes = 0;
59710    	
59711    	if (_conTicket.clientType == 1) {
59712    		jch.prepend('<span class="new-client-text-icon" title="New Client"><b>new</b></span>');
59713    		++attributes;
59714    	}
59715    	
59716    	if (!UTIL.isEmpty(_membershipId)) {
59717    		var htmMemberIcon = GLO.Provider.Membership.getIcon(_membershipId, _conTicket.clientId, _conTicket.clientName);
59718    		
59719    		jch.prepend(htmMemberIcon);							//SA.Ticket.loadClientNote('client-membership', htmMember);
59720    		++attributes;
59721    	}
59722    	
59723    	if (!UTIL.isEmpty(_cftid)) {
59724    		var fnCoF = 'UserPortal.displayCardOnFile(\'' + _conTicket.clientId + '\',' + _cftid + ', \'' + _conTicket.clientName + '\')';
59725    		var htmCardOnFile = '<span class="client-has-card-on-file" cftid="' + _cftid + '" onclick="' + fnCoF + '" title="Has Card On File"><span></span></span>';
59726    		
59727    		jch.prepend(htmCardOnFile);							//SA.Ticket.loadClientNote('client-card-on-file', htmCardOnFile);
59728    		++attributes;
59729    	}
59730    	
59731    	if (!UTIL.isEmpty(_birthDays)) {
59732    		var apptDay = SA.Ticket.getStartDate();
59733    		var birthdayMessage = UserPortal.getBirthdayMessage(_birthDays, apptDay, 60);
59734    		
59735    		if (!UTIL.isEmpty(birthdayMessage)) {
59736	    		var htmBirth = '<span class="client-attribute-birthday">' + birthdayMessage + '</span>';
59737	    		
59738	    		SA.Ticket.loadClientNote('client-birthday', htmBirth);
59739	    		++attributes;
59740    		}
59741    	}
59742    	
59743    	if (_giftBalance > 0) {
59744    		var htmGift = '<span class="client-attribute-gift"><span class="dollar-sign">$</span>' + UTIL.displayMoney(_giftBalance, true, false, true) + ' Gift Card Balance</span>';
59745    		
59746    		SA.Ticket.loadClientNote('client-gift', htmGift);
59747    		++attributes;
59748    	}
59749    	
59750    	if (_clientLoyalty > 0) {
59751    		var loyaltyAttributes = ' client_loyalty_nr="' + _clientLoyalty + '" available_loyalty_nr="' + _availableLoyalty + '" ticket_loyalty_nr="' + _ticketLoyalty + '" title="' + _clientLoyalty + ' Loyalty Points"';
59752    		var htmLoyaltyIcon = '<span class="client-loyalty-points" onclick="UserPortal.displayLoyalty(this)"' + loyaltyAttributes + '><span>' + _clientLoyalty + '</span></span>';
59753    		var htmLoyalty = '<span class="client-attribute-loyalty"><label>
59753' + UTIL.makePlural('Loyalty Point', _clientLoyalty) + '</label>' + htmLoyaltyIcon + '</span>';
59754    		
59755    		SA.Ticket.loadClientNote('client-loyalty', htmLoyalty);
59756    		++attributes;
59757    	}
59758    	
59759    	return attributes;
59760    }
59761    function _displayTags() {
59762    	if (_clientTagXml && _clientTagXml.length) {
59763        	var htmTags = '';
59764        	
59765        	for (var i=0; i < _clientTagXml.length; i++) {
59766				var tagJson = UTIL.xmlToJson(_clientTagXml[i], 'tag');
59767				htmTags += GLO.ClientProfile.Tag.getTagHtm(tagJson, _conTicket.clientId, _conTicket.clientName, true);
59768			}
59769			
59770			_conTicket.loadClientNote('client-tag', htmTags, _clientTagXml.length);
59771			
59772			if (_clientTagRelationshipXml.length) {
59773	    		var htmRelationshipWithAppt = UserPortal.getApptRelatedTagHtm(_clientTagRelationshipXml, true);
59774	    		_conTicket.loadClientNote('client-tag-appt', htmRelationshipWithAppt, _clientTagRelationshipXml.length);
59775	    	}
59776        }
59777    }
59778    
59779    function _loadDiscountRows(jticket, jd, h2) {
59780    	_discountXml = '';
59781    	_discountCount = 0;
59782    	
59783    	var dds = jd.find('dl dd');
59784    	var total = { "discount_mn": 0, "add_on_fee_mn": 0 };
59785    	
59786    	if (h2 && h2.length > 0) {
59787    		if (UTIL.parseBool(h2.attr('custom_discount_fl'))) {
59788    			_conTicket.isCustomDiscount = true;
59789    		}
59790    	}
59791    	
59792    	_addBasicDiscountAttributes(total, dds, h2);			//is custom, count, promo code
59793    	_calculateDiscountAndFees(total);						//discount / fee on action line item is more reliable
59794    	
59795    	_conTicket.setDiscountUI(total);
59796    }
59797    function _calculateDiscountAndFees(total) {
59798    	var totalDiscount = 0, totalAddOnFee = 0;
59799    	
59800    	for (var s=0; s < _serviceXml.length; s++) {
59801    		totalDiscount += UTIL.coalesceMoney(_serviceXml.eq(s).attr('discount_mn'));
59802    		totalAddOnFee += UTIL.coalesceMoney(_serviceXml.eq(s).attr('add_on_fee_mn'));
59803    	}
59804    	
59805    	for (var p=0; p < _productXml.length; p++) {
59806    		totalDiscount += UTIL.coalesceMoney(_productXml.eq(p).attr('discount_mn'));
59807    		totalAddOnFee += UTIL.coalesceMoney(_productXml.eq(p).attr('add_on_fee_mn'));
59808    	}
59809    	
59810    	total.discount_mn 	= UTIL.coalesceMoney(totalDiscount);
59811    	total.add_on_fee_mn = UTIL.coalesceMoney(totalAddOnFee);
59812    }
59813    function _addBasicDiscountAttributes(total, dds, h2) {			//is custom, count, promo code
59814    	if (dds.length) {
59815    		for (var i=0; i < dds.length; i++) {
59816    			var dd = dds.eq(i);
59817    			
59818    			if (UTIL.parseBool(dd.attr('is_active_fl'))) {
59819    				var dmn = UTIL.coalesceMoney(dd.attr('discount_mn')), dpct = UTIL.coalesceFloat(dd.attr('discount_pct'));
59820    				
59821    				if (dmn > 0 || dpct > 0) {
59822	    				total.discount_mn = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('amount_mn')) + total.discount_mn);
59823	    			} else {
59824	    				total.add_on_fee_mn = UTIL.coalesceMoney(UTIL.coalesceMoney(dd.attr('fee_amount_mn'), dd.attr('amount_mn')) + total.add_on_fee_mn);
59825	    			}
59826	    			
59827	    			_discountXml += dd.outerHTML();
59828	    			_setDiscountTicketAttributes(dd);
59829	    			++_discountCount;
59830    			}
59831    		}
59832    	} else if (h2.length > 0) {
59833    		total.discount_mn = UTIL.coalesceMoney(h2.attr('total_discount_mn'));
59834    		total.add_on_fee_mn = UTIL.coalesceMoney(h2.attr('total_addOnFee_mn'));
59835    		
59836    		_discountCount = UTIL.coalesceInt(h2.attr('discount_count_sr'), 0);
59837    	}
59838    }
59839    
59840    _conTicket.sellProduct = function() {
59841    	_conTicket.displayTicket();
59842    	SA.POS.toggleList('products');
59843    }
59844    _conTicket.sellGiftCard = function() {
59845    	_conTicket.sellProduct();
59846    	
59847    	var ctypeId = SA.POS.inventory_json.gift_card_type_id;
59848		SA.POS.filterBoxesCategoryType(ctypeId, false, false);
59849    	
59850    	var jboxes = $('#pos-product-window .pos-product-box');
59851    	var jbox = jboxes.eq(0);
59852    	var minInventoryId = jbox.attr('inventory_id');
59853    	
59854    	for (var i=1; i < jboxes.length; i++) {
59855    		var inventoryId = jboxes.eq(i).attr('inventory_id');
59856    		
59857    		if (inventoryId < minInventoryId) {
59858    			minInventoryId = inventoryId;
59859    			jbox = jboxes.eq(i);
59860    		}
59861    	}
59862    	
59863    	if (jbox.length) {
59864    		SA.POS.addProductRowToTicket(minInventoryId, jbox);
59865    	} else {
59866    		var productBoxGiftVoucher = { "id": SA.POS.inventory_json.system_gift_voucher_id, "label":"Gift Voucher", "value":"Gift Voucher", "vend
59866or_id":"", "product_line_id":"", "vendor_merchant_id":""
59867    							, "inventory_type_id":"116", "category_id":"41", "tax_rate_pct":"0.00", "in_stock_dr":"", "sku_vc":"", "upc_vc":"", "vendor_name_vc":"", "size_vc":" "
59868    							, "cost_mn":"0.00", "price_mn":"", "employee_price_mn":"", "is_sku_upc_match_fl":"0", "is_gift_card_fl":"1", "default_type_id": 115 };
59869			
59870			var productBox = { "id": SA.POS.inventory_json.system_gift_card_id, "label":"Gift Card", "value":"Gift Card", "vendor_id":"", "product_line_id":"", "vendor_merchant_id":""
59871    							, "inventory_type_id":"115", "category_id":"41", "tax_rate_pct":"0.00", "in_stock_dr":"", "sku_vc":"", "upc_vc":"", "vendor_name_vc":"", "size_vc":" "
59872    							, "cost_mn":"0.00", "price_mn":"", "employee_price_mn":"", "is_sku_upc_match_fl":"0", "is_gift_card_fl":"1", "default_type_id": 115 };
59873			var productName = UTIL.maxStringHtml(productBox.label, 25, false, 'span', '', 'line-item-name', '');
59874			
59875    		_conTicket.addLine(productName, productBox.id, null, null, 1, productBox.price_mn, null, null, productBox);
59876			SA.POS.filterBoxesHome();				//press home button
59877    	}
59878    }
59879    
59880    _conTicket.getReferralDiscount = function() {
59881    	return UTIL.coalesceMoney(_referralDiscount);
59882    }
59883    _conTicket.setReferralDiscount = function(referralDiscount) {
59884    	_referralDiscount = UTIL.coalesceMoney(referralDiscount);
59885    	_conTicket.recalculateDiscountTotal();
59886    }
59887    _conTicket.setDiscountUI = function(total) {
59888    	var addOnFee = UTIL.coalesceMoney(total.add_on_fee_mn);
59889    	var discount = UTIL.coalesceMoney(total.discount_mn);
59890    	
59891    	var jtotal = $('#pos-ticket-total-line');
59892    	var jdiscount = jtotal.find('#pos-ticket-total-discount');
59893    	
59894    	var jfeeAmount = jdiscount.find(' > b#pos-ticket-add-on-fee-amount');
59895    	var jdiscountAmount = jdiscount.find(' > b#pos-ticket-discount-amount');
59896    	
59897    	var currentFee = UTIL.coalesceMoney(jfeeAmount.text().replace('$', ''));
59898    	var currentDiscount = UTIL.coalesceMoney(jdiscountAmount.text().replace('$', ''));
59899    	
59900    	if (addOnFee > 0) {
59901    		jdiscount.find(' > small').text('Add-On Fee');
59902    		jdiscount.addClass('has-add-on-fee');
59903    		jfeeAmount.text(UTIL.displayMoney(addOnFee));
59904    	} else {
59905    		jdiscount.removeClass('has-add-on-fee');
59906    		jfeeAmount.text('');
59907    	}
59908    	
59909    	if (discount > 0) {
59910    		jdiscount.find(' > small').text('Discount');
59911    		jdiscount.addClass('has-discount');
59912    		jdiscountAmount.text(UTIL.displayMoney(discount));
59913    	} else {
59914    		jdiscount.removeClass('has-discount');
59915    		jdiscountAmount.text('');
59916    	}
59917    	
59918    	if (currentFee != addOnFee || currentDiscount != discount) {
59919    		var subTotal = UTIL.coalesceMoney(jtotal.find('#pos-ticket-total-sub').find(' > b').text().replace('$', ''));
59920    		var tax = UTIL.coalesceMoney(jtotal.find('#pos-ticket-total-tax').find(' > b').text().replace('$', ''));
59921    		
59922    		var newTotal = UTIL.displayMoney(subTotal + tax - discount + addOnFee);
59923    		var jTotalCell = jtotal.find('#pos-ticket-total-box').find(' > b');
59924    		
59925    		jTotalCell.text(newTotal);
59926    		_styleTotalCell(jTotalCell);
59927    	}
59928    }
59929    _conTicket.applyDiscounts = function(waitLen, includeReorder) {
59930    	clearTimeout(_timeoutApplyDiscounts);
59931		waitLen = UTIL.coalesceInt(waitLen, 15);
59932		
59933		var jdiscount = $('#pos-ticket-total-discount');
59934		
59935		if (!UTIL.isEmpty(jdiscount.find('b').text())) {
59936			jdiscount.addClass('is-processing');
59937		}
59938		
59939		_timeoutApplyDiscounts = setTimeout(function() {
59940			if (UserPortal.Price.Discount.applyDiscounts(null, true)) {
59941	    		if (includeReorder) {
59942	    			UserPortal.Price.Discount.reorderDiscounts();
59943	    		}
59944	    	}
59945	    	
59946	    	_conTicket.recalculateDiscountTotal();
59947	    	$('#pos-ticket-total-discount').removeClass('is-processing');
59948	    	_setCheckInButton();
59949		}, waitLen);
59950    }
59951    function _setCheckInButton() {
59952    	var jticket = $('#pos-ticket');
59953    	var smid = jticket.attr('schedule_multi_id');
59954    	var price = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''));
59955    	var payment = UTIL.coalesceMoney(_initialPayment);
59956    	
59957    	var jfooter = jticket.find('#pos-ticket-footer');
59958    	var btnCheckinTicket = jfooter.find('#btnCheckinTicket');
59959    	var btnPrintTicket = jfooter.find('#btnPrintTicket');
59960    	var jpaid = jfooter.find('#pos-ticket-paid').addClass('hide');
59961    	var jdue = jfooter.find('#pos-ticket-due').addClass('hide');
59962    	var serviceCount = jticket.find('.pos-service-line-item').length;
59963    	var isToday = new Date($('#pos-ticket-datetime #Ticket_day').val()).toGloDate(
59963) == new Date().toGloDate();
59964    	
59965    	jticket.find('#btnDeleteTicket').addClass('hide');
59966    	
59967    	if (!isToday || serviceCount === 0) {
59968    		btnCheckinTicket.addClass('hide');
59969    		btnPrintTicket.addClass('hide');
59970    		
59971    		if (serviceCount === 0 && UTIL.isEmpty(smid) && jticket.find('.pos-product-line-item').length == 0) {
59972    			jticket.find('#btnDeleteTicket').removeClass('hide');
59973    		}
59974    	} else if (UTIL.coalesceInt(_apptStatus, 0) < 13) {
59975    		btnCheckinTicket.removeClass('hide');
59976    		btnPrintTicket.addClass('hide');
59977    	} else if (_apptStatus == 21 || _apptStatus == 25) {
59978    		btnCheckinTicket.addClass('hide');
59979    		
59980    		if (payment > 0) {
59981    			btnPrintTicket.addClass('hide');
59982    		} else {
59983    			btnPrintTicket.removeClass('hide');
59984    		}
59985    	} else {
59986    		btnCheckinTicket.addClass('hide');
59987    		btnPrintTicket.addClass('hide');
59988    	}
59989    	
59990    	if (payment > 0) {
59991    		jticket.find('#pos-ticket-header-paid-amount').text(UTIL.displayMoney(payment, true, false, true));
59992    		
59993    		if (payment >= price) {
59994    			var title = _getPaymentTitle(0);
59995    			jpaid.removeClass('hide').attr('title', title);
59996    		} else {
59997    			var title = _getPaymentTitle(price - payment);
59998    			var due = '<span class="dollar-sign">$</span>' + UTIL.displayMoney(price - payment, true, false, true);
59999    			
60000    			if (innerWidth > 1680 || due.length < 8) {
60001    				if (String(due).length < 3) {
60002    					due = '<small>Due</small> ' + due;
60003    				}
60004    			}
60005    			
60006    			jdue.removeClass('hide').attr('title', title).html(due);
60007    		}
60008    		
60009    		SA.Ticket.adjustMultiTicketTotal();
60010    	} else {
60011    		jticket.find('#pos-ticket-header-paid-amount').text('0');
60012    	}
60013    }
60014    function _getPaymentTitle(amountDue) {
60015    	var title = UTIL.displayMoney(_initialPayment, false, false, true);
60016		var lps = $('<ol>' + _paymentXml + '</ol>').find('lp');
60017		
60018		if (lps.length === 1) {
60019			title += _getPaymentDateTitle(lps.eq(0));
60020		} else if (lps.length > 1) {
60021			title = 'Total payment ' + title;
60022			
60023			for (var i=0; i < lps.length; i++) {
60024				title += ' | ';
60025				title += UTIL.displayMoney(lps.eq(i).attr('payment_mn'), false, false, true);
60026				title += _getPaymentDateTitle(lps.eq(i));
60027			}
60028		}
60029		
60030		if (amountDue > 0) {
60031			title = 'Due: ' + UTIL.displayMoney(amountDue, false, false, true) + ' | ' + title;
60032		}
60033		
60034		return title;
60035    }
60036    function _getPaymentDateTitle(lp) {
60037    	var dtPay = lp.attr('create_dt');
60038		var title = '';
60039		
60040		if (UTIL.isDate(dtPay)) {
60041			title = ' paid on ' + new Date(dtPay).toPrettyDate(true) + ' ' + new Date(dtPay).toGloTime();
60042		}
60043		
60044		return title;
60045    }
60046    function _loadPaymentRows(jd, h2) {
60047    	if (h2 && h2.attr) {
60048    		_initialPayment = UTIL.coalesceMoney(h2.attr('total_payment_mn'));
60049    	}
60050    	
60051    	if (jd.find('ol lp').length) {
60052    		_paymentXml = jd.find('ol').html();
60053    		//_initialPayment = 0;
60054    	} else if (h2 && h2.attr) {
60055	    	var pmeth = h2.attr('payment_method_cd');
60056	    	
60057	    	if (_initialPayment != 0 && !UTIL.isEmpty(pmeth)) {
60058    			var payXml = UserPortal.Price.getSinglePayment(h2, _initialPayment, pmeth);
60059    			_paymentXml = payXml;
60060    		}
60061    	}
60062    }
60063    function _loadProductRows() {
60064    	for (var p=0; p < _productXml.length; p++) {
60065    		var jp = _productXml.eq(p);
60066    		var iid = jp.attr('inventory_id');
60067    		var siid = jp.attr('schedule_inventory_id');
60068    		
60069    		var amount = UTIL.coalesceInt(jp.attr('amount_nr'), 1);
60070    		var price = UTIL.coalesceMoney(jp.attr('price_mn'));
60071    		//var tax = UTIL.coalesceMoney(jp.attr('tax_mn'));
60072    		//vendor_merchant_id
60073    		
60074    		var jline = SA.Ticket.addProductLine(iid, amount, price);
60075    		
60076    		if (UTIL.isEmptyObject(jline) && $('.pop-processing.glopop').length) {			//unable to add product (is-membership or deleted product)
60077    			return false;
60078    		}
60079    		
60080    		var mid = jp.attr('membership_id');
60081    		var cstaff = jp.attr('commission_staff_id');
60082			var ptype = jp.attr('inventory_purchase_type_cd');
60083			
60084			var tax = jp.attr('tax_mn');
60085			var taxRate = jp.attr('tax_rate_pct');
60086			var addOnFee = jp.attr('add_on_fee_mn');
60087    		var discount = jp.attr('discount_mn');
60088    		
60089    		var currSIIDs = jline.attr('schedule_inventory_ids');
60090    		
60091    		if (!UTIL.isEmpty(currSIIDs)) {
60092    			siid = currSIIDs + ',' + siid;
60093    		}
60094    		
60095    		jline.attr('schedule_inventory_ids', siid);
60096    		
60097    		if (!UTIL.isEmpty(mid)) { jline.attr('membership_id', mid); }
60098    		if (!UTIL.isEmpty(cstaff)) { jline.attr('commission_staff_id', cstaff); }
60099    		if (!UTIL.isEmpty(ptype)) { jline.attr('inventory_purchase_type_cd', ptype); }
60100    		
60101    		if (!UTIL.isEmpty(tax)) { jline.attr('tax_mn', tax); }
60102    		if (!UTIL.isEmpty(taxRate)) { jline.attr('tax_rate_pct', taxRate); }
60103    		if (!UTIL.isEmpty(addOnFee)) { jline.attr('add_on_fee_mn', addOnFee); }
60104    		if (!UTIL.isEmpty(discount)) { jline.attr('discount_mn', discount); }
60105    		
60106    		if (UTIL.parseBool(jp.attr('is_gift_card_fl'))) {
60107    			var giftNumber = $.trim(jp.attr('gift_number_vc'));
60108    			
60109    			jline.attr('is_gift_card_fl', '1');
60110    			jline.attr('gift_card_id', $.trim(jp.attr('gift_card_id')));
60111    			jline.attr('to_client_id', $.trim(jp.attr('to_client_id')));
60112    			jline.attr('gift_number_vc', giftNumber);
60113    			jline.attr('gift_original_mn', $.trim(jp.attr('gift_original_mn')));
60114    			jline.attr('gift_balance_mn', $.trim(jp.attr('gift_balance_mn')));
60115    			
60116    			if (!UTIL.isEmpty(giftNumber)) {
60117	    			var jname = jline.find('.line-item-name');
60118	    			jname.text(jname.text() + ' #' + giftNumber);
60119    			} 
60120    		} else {
60121    			jline.removeAttr('is_gift_card_fl').removeAttr('gift_card_id').removeAttr('to_client_id').removeAttr('gift_number_vc').removeAttr('gift_original_mn').removeAttr('gift_balance_mn');
60122    		}
60123    	}
60124    	
60125    	return true;
60126    }
60127    function _loadServiceRows() {
60128    	var faId, ticketResourceId, arrStaffId = [];
60129    	
60130    	if (_serviceXml && _serviceXml.length) {
60131    		if (_serviceXml.length === 1 && _serviceXml.attr && UTIL.isEmpty(_serviceXml.attr('service_id'))) {
60132    			var staffId = _serviceXml.attr('staff_id');
60133	    		_serviceXml = '';
60134	    		
60135	    		if (!UTIL.isEmpty(staffId) && !UserPortal.isFirstAvailable(staffId)
60135) {
60136		    		var sname = UserPortal.getStaffName(staffId);
60137	    			SA.POS.selectDefaultStaff(staffId, sname, false);
60138	    		}
60139	    		
60140	    		return;
60141	    	}
60142    		
60143	    	for (var s=0; s < _serviceXml.length; s++) {
60144	    		var jsvc = _serviceXml.eq(s);
60145	    		var scheduleId = jsvc.attr('schedule_id');
60146	    		var serviceId = jsvc.attr('service_id');
60147	    		var sgid = jsvc.attr('service_group_id');
60148	    		
60149	    		var staffId = jsvc.attr('staff_id');
60150	    		var isFA = UserPortal.isFirstAvailable(staffId);
60151	    		var price = UTIL.coalesceMoney(jsvc.attr('price_mn'));
60152	    		
60153	    		var jline = SA.Ticket.addServiceLine(serviceId, sgid, staffId, isFA, price, scheduleId);
60154	    		
60155	    		if (jline && jline.attr) {
60156	    			jline.attr('schedule_id', scheduleId);
60157	    		} else {
60158	    			return;
60159	    		}
60160	    		
60161	    		_loadServiceRowLen(jsvc, jline);
60162	    		_loadServiceRowOther(jsvc, jline, scheduleId);
60163	    		ticketResourceId = _setTicketResourceId(ticketResourceId, jsvc, s);
60164	    		
60165	    		if (isFA) {
60166	    			faId = staffId;
60167	    		} else if (UTIL.isNumber(staffId) && !arrStaffId.has(staffId)) {
60168	    			arrStaffId.push(staffId);
60169	    		}
60170	    	}
60171	    	
60172	    	_setTicketLabel(ticketResourceId);
60173	    	_setApptIcon(_serviceXml);
60174    	}
60175    	
60176    	if (!$('#pos-header-staff').hasClass('selected') && (arrStaffId.length === 1 || (arrStaffId.length === 0 && UTIL.isNumber(faId)))) {
60177    		if (arrStaffId.length === 1) {
60178    			var sid = arrStaffId[0], isFaStaff = false;
60179    		} else {
60180    			var sid = faId, isFaStaff = true;
60181    		}
60182    		
60183    		var sname = UserPortal.getStaffName(sid);
60184    		SA.POS.selectDefaultStaff(sid, sname, isFaStaff);
60185    	}
60186    }
60187    function _setApptIcon(_serviceXml) {
60188    	if (parseInt(_serviceXml.attr('schedule_multi_id')) > 0) {
60189    		var dtCreate = new Date(_conTicket.createDate);					//var dtCreate = new Date(_serviceXml.attr('create_dt'));
60190    		var jdt = $('#pos-ticket-datetime');
60191    		var day = jdt.find('#Ticket_day').val(), time = jdt.find('#Ticket_tm').val();
60192    		
60193    		if (UTIL.isDate(day) && UTIL.isValidTime(time)) {
60194    			var dtStart = new Date(day + ' ' + time);
60195	    		
60196		    	if ( (dtStart - dtCreate) / (60*60*1000) > 1) {
60197		    		var icon = '<b class="appt-icon pre-booked-appointment-icon"><a onclick="ClientProfile.openAppointmentActivity(true)"></a></b>';
60198		    	} else {
60199		    		var icon = '<span class="appt-icon walkin-icon"><b title="Walk-In">W</b></span>';
60200		    	}
60201		    	
60202		    	jdt.append(icon);
60203	    	}
60204    	}
60205    }
60206    function _setTicketLabel(ticketResourceId) {
60207    	var jlabel = $('#pos-header-staff-ticket-label');
60208    	
60209    	if (!UTIL.isEmpty(ticketResourceId)) {
60210    		var resourceName = UserPortal.getResourceName(ticketResourceId);
60211    		jlabel.addClass('ticket-resource-name').text(resourceName);
60212    	} else if (_conTicket.bookingNumber > 0) {
60213    		jlabel.addClass('ticket-booking-number').text('P' + _conTicket.bookingNumber);
60214    	}
60215    }
60216    function _setTicketResourceId(ticketResourceId, jsvc, s) {
60217    	var resourceId = jsvc.attr('service_resource_id');
60218    	
60219    	if (s === 0) {
60220    		return resourceId;
60221    	} else if (ticketResourceId == resourceId) {
60222    		return ticketResourceId;
60223    	} else {
60224    		return null;
60225    	}
60226    }
60227    function _loadServiceRowLen(jsvc, jline) {
60228    	if (UTIL.isDate($.trim(jsvc.attr('appt_dt') + ' ' + jsvc.attr('time_vc')))) {
60229			jline.attr('appt_dt', jsvc.attr('appt_dt'));
60230    		jline.attr('time_vc', jsvc.attr('time_vc'));
60231    		
60232    		jline.attr('end_dt', jsvc.attr('end_dt'));
60233		}
60234		
60235		jline.attr('service_length_nr', jsvc.attr('service_length_nr'));
60236		jline.attr('prep_nr', jsvc.attr('prep_nr'));
60237		jline.attr('prep_fl', jsvc.attr('prep_fl'));
60238		
60239		jline.attr('processing_nr', jsvc.attr('processing_nr'));
60240		jline.attr('processing_fl', jsvc.attr('processing_fl'));
60241		jline.attr('finish_out_nr', jsvc.attr('finish_out_nr'));
60242		jline.attr('finish_out_fl', jsvc.attr('finish_out_fl'));
60243    }
60244    function _loadServiceRowOther(jsvc, jline, scheduleId) {
60245    	var cr = UTIL.parseBool(jsvc.attr('client_request_fl'));
60246		var customD = UTIL.parseBool(jsvc.attr('custom_discount_fl'));
60247		var split = $.trim(jsvc.attr('commission_split_cd'));
60248		var splitPercent = $.trim(jsvc.attr('commission_split_pct'));
60249		
60250		var addOnFee = UTIL.coalesceMoney(jsvc.attr('add_on_fee_mn'));
60251		var discount = UTIL.coalesceMoney(jsvc.attr('discount_mn'));
60252		var discountNew = UTIL.coalesceMoney(jsvc.attr('new_discount_mn'));
60253		
60254		var resourceId = $.trim(jsvc.attr('service_resource_id'));
60255		var recurId = $.trim(jsvc.attr('schedule_recur_id'));
60256		var svcAttributeId = $.trim(jsvc.attr('service_attribute_id'));
60257		
60258		var price = UTIL.coalesceMoney(jsvc.attr('price_mn'));
60259		var tip = UTIL.coalesceMoney(jsvc.attr('tip_mn'));
60260		var tax = UTIL.coalesceMoney(jsvc.attr('tax_mn'));
60261		var isOutcall = UTIL.parseBool(jsvc.attr('outcall_fl'));
60262		var outcallFee = UTIL.coalesceMoney(jsvc.attr('outcall_fee_mn'));
60263		
60264		if (UTIL.isEmpty(scheduleId) && tax === 0 && GLO.serviceTax > 0) {
60265			tax = UTIL.coalesceMoney(GLO.serviceTax/100 * (price - discount + addOnFee));
60266		}
60267		
60268		if (discountNew !== 0) {
60269			jline.attr('new_discount_mn', discountNew);
60270		}
60271		
60272		jline.attr('client_request_fl', cr).attr('custom_discount_fl', customD).attr('commission_split_cd', split).attr('commission_split_pct', splitPercent);
60273		jline.attr('discount_mn', discount).attr('add_on_fee_mn', addOnFee);
60274		jline.attr('service_resource_id', resourceId).attr('schedule_recur_id', recurId).attr('service_attribute_id', svcAttributeId);
60275		jline.attr('tip_mn', tip).attr('tax_mn', tax).attr('outcall_fl', isOutcall).attr('outcall_fee_mn', outcallFee);
60276    }
60277    
60278    function _finishAddProductOrService() {
60279    	var jticket = $('#pos-ticket-order');
60280    	var jproducts = jticket.find('.pos-product-line-item');
60281    	var jproductLabelRow = jticket.find('#pos-product-label-row');
60282    	
60283    	if (jticket.find('.pos-service-line-item').length > 0 && jproducts.length > 0) {
60284    		if (jproductLabelRow.length == 0) {
60285    			var htm = '<div id="pos-product-label-row"><span id="pos-product-label">Products</span></div>';
60286    			jproducts.before(htm);
60287    		}
60288    	} else {
60289    		jproductLabelRow.remove();
60290    	}
60291    }
60292    
60293    function _setBookingNumber() {
60294    	var bkg = $.trim(_conTicket.bookingNumber);
60295    	var jbtn = $('#pos-ticket #btnViewTicket').removeClass('appt-status-no-show').removeClass('appt-status-late-cancel').removeClass('appt-status-checked-in').removeClass('appt-status-checked-out');
60296    	var abtn = jbtn.find('>a').removeClass('is-narrow')
60297    	
60298    	if (!UTIL.isEmpty(bkg)) {
60299    		if (bkg.length > 5 && innerWidth < 1680) {
60300    			abtn.addClass('is-narrow');
60301    		}
60302    		
60303    		abtn.text(SA.Resource.View + ' P' + bkg);
60304    	} else {
60305    		abtn.text(abtn.attr('original_text'));
60306    	}
60307    	
60308    	if (_apptStatus == 13) {							//_dtCheckin, _dtCheckout, _dtSignin
60309    		jbtn.addClass('appt-status-no-show');
60310    	} else if (_apptStatus == 14) {
60311    		jbtn.addClass('appt-status-checked-late-cancel');
60312    	} else if (_apptStatus == 21) {
60313    		jbtn.addClass('appt-status-checked-in');
60314    	} else if (_apptStatus == 22) {
60315    		jbtn.addClass('appt-status-checked-out');
60316    	}
60317    }
60318    
60319    _conTicket.initOpenFromDB = function(data) {
60320    	var returnData = $(data);
60321    	var ul = $(data).find('ul');
60322    	var lis = ul.find('>li');
60323    	var jPricePop = $('#appt-price-popup');
60324        var jtix = $('#pos-ticket');
60325        var jlines = jtix.find('.pos-product-line-item');
60326        
60327        var tixUpdateDate = jtix.attr('last_update_dt');
60328        var dataUpdateDate = returnData.find('h2').attr('update_dt');
60329        var dateDiff = 0;
60330        
60331        if (UTIL.isDate(tixUpdateDate) && UTIL.isDate(dataUpdateDate)) {
60332        	dateDiff = new Date(tixUpdateDate).getTime() - new Date(dataUpdateDate).getTime();
60333        }
60334        
60335        for (var l=0; l < jlines.length; l++) {
60336        	var iid = parseInt(jlines.eq(l).attr('inventory_id'));
60337        	var quantity = UTIL.coalesceInt(jlines.eq(l).find('.line-item-amount').val(), 0);
60338        	var price = UTIL.coalesceMoney(jlines.eq(l).find('.line-item-price').val(), 0);
60339        	var foundCount = 0;
60340        	
60341        	for (var q=0; q < quantity; q++) {
60342	        	for (var i=0; i < lis.length; i++) {
60343	        		if (iid === parseInt(lis.eq(i).attr('inventory_id'))) {
60344	        			if (price !== UTIL.coalesceMoney(lis.eq(i).attr('price_mn'))) {		//use price on pos-ticket (not from DB).
60345	        				var siid = lis.eq(i).attr('schedule_inventory_id');
60346	        				returnData.find('li[schedule_inventory_id="' + siid + '"]').attr('price_mn', price);
60347	        			}
60348	        			
60349	        			++foundCount;
60350	        			lis.eq(i).remove();
60351	        		}
60352	        	}
60353	        }
60354	        
60355	        if (quantity > foundCount) {			//add line from pos-ticket
60356	        	var newLis = _openAddLineItem(jlines.eq(l), foundCount);
60357	        	returnData.find('ul').append(newLis);
60358	        }
60359        }
60360        
60361        if (dateDiff === 0) {
60362        	lis = ul.find('>li');
60363        	
60364        	for (var i=0; i < lis.length; i++) {
60365        		var siid = lis.eq(i).attr('schedule_inventory_id');
60366				returnData.find('li[schedule_inventory_id="' + siid + '"]').remove();
60367				_deleteInventoryXml += '<li del_schedule_inventory_id="' + siid + '"/>';
60368        	}
60369        }
60370        
60371        return returnData.outerHTML();
60372    }
60373    
60374    function _matchingActiveLine(inventoryId, jtix) {
60375    	var activeRows = jtix.find('.pos-product-line-item');
60376    	
60377    	if (!_isLoading) {
60378	    	for (var i=0; i < activeRows.length; i++) {
60379	    		var jrow = activeRows.eq(i);
60380	    		
60381	    		if (inventoryId === parseInt(jrow.attr('inventory_id')) && !jrow.find('.line-item-amount').prop('readonly')) {		//= if gift card # generate is manual then only 1 gift card per row
60382	    			if (!jrow.hasClass('new-line-item')) {
60383	    				var lineId = jrow.attr('id');
60384	    				var clickCnt = jrow.attr('click_count_nr') + 1;
60385	    				
60386	    				jrow.addClass('new-line-item');
60387	    				jrow.attr('click_count_nr', clickCnt);
60388	    				
60389	    				setTimeout(function() {
60390	    					SA.Ticket.addLineEnd(lineId, clickCnt);
60391	    				}, 1500);
60392	    			}
60393	    			
60394	    			return jrow;
60395	    		}
60396	    	}
60397    	}
60398    	
60399    	return false;
60400    }
60401    
60402    function _incrementAmount(jActiveRow) {
60403    	var amt = parseInt(jActiveRow.find('.line-item-amount').val()) + 1
60404    	jActiveRow.find('.line-item-amount').val(amt);
60405    	
60406    	var clicks = parseInt(jActiveRow.attr('click_count_nr')) + 1;
60407    	jActiveRow.attr('click_count_nr', clicks);
60408    	
60409    	_conTicket.recalculate();
60410    }
60411    
60412    function _serviceLineLabel(serviceId, staffId, isFA) {
60413    	var svc = SA.POS.getServiceObject(serviceId);
60414    	var span = '<span class="line-item-name pos-service-label"';
60415    	
60416    	if (UTIL.isEmpty(svc)) {
60417    		var dsgid = $('#allServiceOptions option[value="' + serviceId + '"]').attr('default_service_group_id');
60418    		var divStart = '<div id="pop-warning-not-pos-ticket">';
60419    		
60420    		if (dsgid == 9 || dsgid == 1009) {
60421    			if (dsgid == 9) {
60422    				GLO.Popup.Warning.open(divStart + 'Cannot Process Staff\'s Off Time Ticket in P.O.S.</
60422div>', 'Ticket Not Allowed');
60423    			} else if (dsgid == 9) {
60424    				GLO.Popup.Warning.open(divStart + 'Cannot Process Timecard Ticket in P.O.S.</div>', 'Ticket Not Allowed');
60425    			}
60426    			
60427    			setTimeout(function() {
60428    				SA.Ticket.hideChangeDue();
60429    				SA.Ticket.reset();
60430    			}, 90);
60431    		} else {
60432	    		var msg = '<p>This Service Not Available in P.O.S.</p>';
60433	    		var smid = $('#pos-ticket').attr('schedule_multi_id');
60434	    		var day = $('#Ticket_day').val();							//var bkgNumber = _conTicket.bookingNumber;
60435	    		
60436	    		if (smid > 0 && UTIL.isDate(day)) {
60437	    			var url = GLO.Link.WebsiteDomain + 'provider/calendar#vw=resourceDay&dt=' + day + '&ticketid=' + smid;
60438	    			var btn = '<span id="btnViewInCal" class="btnAdd"><a onclick="GLO.Uri.gotoUri(\'' + url + '\', this, event, true)">View in Calendar</a></span>';
60439	    			
60440	    			msg += '<p style="text-align: center;">' + btn + '</p>';
60441	    		}
60442	    		
60443	    		var htm = divStart + '<div id="pop-warn-pos-add-service">' + msg + '</div></div>';
60444	    		GLO.Popup.Warning.open(htm, 'Service Not Found');
60445    		}
60446    		
60447    		return '';
60448    	}
60449    	
60450    	return span + '><b>' + svc.name + '</b></span>';
60451    	
60452    	/* if (isFA) {
60453    		return span + '><b>' + svc.name + '</b></span>';
60454    	} else {
60455    		var staffName = UserPortal.getStaffName(staffId);
60456    		
60457    		if ((staffName + svc.name).length > 25) {
60458    			return span + ' title="' + staffName + ' - ' + svc.name + '"><i>' + UTIL.maxString(staffName, 10, true) + '</i><b>' + svc.name + '</b></span>';
60459    		} else {
60460    			return span + '><i>' + staffName + '</i><b>' + svc.name + '</b></span>';
60461    		}
60462    	} */
60463    }
60464    _conTicket.addServiceLineAfterAddStaff = function(serviceId) {
60465    	if (serviceId > 0) {
60466    		var sgid = UserPortal.getServiceGroupId(serviceId);
60467    		
60468    		SA.Ticket.addServiceLine(serviceId, sgid);
60469    		SA.Ticket.ticketChanged();
60470    	}
60471    }
60472    _conTicket.addServiceLine = function(serviceId, sgid, staffId, isFA, price, scheduleId) {
60473    	serviceId = parseInt(serviceId);
60474    	
60475    	if (UTIL.isEmpty(staffId)) {
60476    		var jstaff = $('#btnSelectedStaff > a');
60477    		staffId = jstaff.attr('staff_id');
60478    		isFA = UTIL.parseBool(jstaff.attr('is_first_available_fl'));
60479    		
60480    		if (UTIL.isEmpty(staffId)) {
60481    			if (GLO.Data.provider.hasFirstAvailable) {
60482	    			staffId = UserPortal.getFirstAvailableStaffId();
60483	    			isFA = true;
60484    			} else {
60485    				SA.POS.openSelectStaff(null, serviceId);
60486    				return;
60487    			}
60488    		}
60489    	} else {
60490    		isFA = UserPortal.isFirstAvailable(staffId);
60491    	}
60492    	
60493    	if (UTIL.isEmpty(price)) {
60494    		var ojDefault = UserPortal.Booking.lookupDefault(serviceId, staffId, null, true);
60495    		price = UserPortal.Booking.parseDefaultPrice(ojDefault["price"]);
60496    	}
60497    	
60498    	if (false && UTIL.isEmpty(scheduleId)) {			//toDo: implement later
60499	    	var jtix = $('#pos-ticket-order');
60500	    	var activeRow = _matchingActiveServiceLine(serviceId, staffId, jtix);
60501		    	
60502	    	if (activeRow.length > 0) {
60503	    		_incrementAmount(activeRow);
60504	    		_addLineToHeader();
60505	    		return;
60506	    	}
60507    	}
60508    	
60509    	var name = _serviceLineLabel(serviceId, staffId, isFA);
60510    	return _conTicket.addLine(name, null, serviceId, sgid, 1, price, staffId, isFA, null);
60511    }
60512    _conTicket.addProductLine = function(inventoryId, amount, price) {
60513    	amount = UTIL.coalesceMoney(amount, 1);
60514    	inventoryId = parseInt(inventoryId);
60515    	
60516    	var jtix = $('#pos-ticket-order');
60517    	
60518    	if (SA.POS.inventory_json.manual_entry && SA.POS.inventory_json.manual_entry.id === inventoryId) {
60519    		var product = null, productName = '<span class="line-item-name">' + SA.Resource.ManualEntry + '</span>';
60520    		
60521    		if (!UTIL.isNumber(price)) {
60522    			price = UTIL.displayMoney($('#pos-enter-product-or-amount').val(), true, false, true);
60523    		}
60524    		
60525    		$('#pos-product-header-enter #pos-enter-product-or-amount').val('');
60526    		$('#pos-product-header-enter .btnAction2').addClass('hide');
60527    	} else {
60528	    	var activeRow = _matchingActiveLine(inventoryId, jtix);
60529	    	
60530	    	if (activeRow.length > 0) {
60531	    		_incrementAmount(activeRow);
60532	    		_addLineToHeader();
60533	    		return activeRow;
60534	    	}
60535	    	
60536	    	var product = SA.POS.getProductObject(inventoryId);
60537	    	
60538	    	if (product) {
60539	    		var productName = UTIL.maxStringHtml(product.label, 25, false, 'span', '', 'line-item-name', '');
60540	    		price = UTIL.coalesceMoney(price, product.price_mn);
60541	    	} else {
60542	    		var smid = $('#pos-ticket').attr('schedule_multi_id');
60543	    		var bkgNumber = _conTicket.bookingNumber;
60544	    		var msg = 'Tickets with a membership sale or deleted product must be opened as a ticket popup';
60545	    		var logMsg = msg + ', inventoryId = ' + inventoryId;
60546	    		
60547	    		SA.Ticket.clearTicket();
60548	    		UserPortal.getTicket(smid, bkgNumber, null, false, null, null, { "openInPopup": true, "processing_message_vc": msg });
60549	    		
60550	    		GLO.Log.insertSimple('POS Screen does NOT support Ticket', logMsg, 'warning');
60551	    		return;
60552	    	}
60553    	}
60554    	
60555    	return _conTicket.addLine(productName, inventoryId, null, null, amount, price, null, null, product);
60556    }
60557    function _getLineId(jtix) {
60558    	var jlines = jtix.find('.pos-ticket-line-item');
60559    	var maxNumber = 0;
60560    	
60561    	for (var i = jlines.length - 1; i >= 0; i--) {
60562    		var test = parseInt(jlines.eq(i).attr('id').replace('pos-line-', ''));
60563    		
60564    		if (test > maxNumber) {
60565    			maxNumber = test;
60566    		}
60567    	}
60568    	
60569    	return 'pos-line-' + (maxNumber + 1);
60570    }
60571    _conTicket.addLine = function(name, inventoryId, serviceId, sgid, amount, price, staffId, isFA, productBox) {
60572    	_conTicket.hideChangeDue();
60573    	
60574    	var jtix = $('#pos-ticket-order');
60575    	var lineId = _getLineId(jtix);
60576    	var ln = _lineHtm(lineId, name, inventoryId, serviceId, sgid, amount, price, staffId, isFA, productBox);
60577    	
60578    	ln = _addLineToPage(jtix, ln, lineId, staffId);
60579    	
60580    	if (!GLO.Info.isMobile(true) && UTIL.coalesceMoney(price) === 0) {
60581    		ln.find('.line-item-price').focus();
60582    	} else if (!GLO.Info.isMobile() && jtix[0].scrollHeight > jtix[0].clientHeight) {
60583    		UI.scrollToElement(jtix, ln);
60584    	}
60585    	
60586    	$("#pos-product-header-enter").removeClass('is-numeric');
60587    	
60588    	_conTicket.recalculate();
60589    	_addLineToHeader();
60590    	_finishAddProductOrService();
60591    	_conTicket.enableOrDisableTicketScroll();
60592    	
60593    	if (_isLoading) {
60594    		ln.removeClass('new-line-item');
60595    	} else {
60596    		setTimeout(function() {
60597    			SA.Ticket.addLineEnd(lineId, 1);
60598    		}, 1500);
60599    		
60600    		_addGiftCardToTicket(ln, productBox);
60601    	}
60602    	
60603    	return ln;
60604	}
60605	function _addLineToPage(jtix, ln, lineId, staffId) {
60606		var jline = $(ln);
60607		
60608		if (jline.hasClass('pos-service-line-item')) {
60609			var staffRow = _conTicket.getStaffTicketLastRow(jtix, staffId, jline);
60610			staffRow.after(ln);
60611		} else {
60612			jtix.append(ln);
60613    	}
60614    	
60615    	ln = jtix.find('#' + lineId);			//.new-line-item:last
60616    	ln.find('.pos-service-label').click(SA.POS.openSelectStaff);
60617    	return ln;
60618	}
60619	_conTicket.getStaffTicketLastRow = function(jtix, staffId, jline) {			//= get staff row (if no staff row -> add it)
60620		var rowStaff = jtix.find('.pos-staff-line-item[staff_id="' + staffId + '"]');
60621		
60622		if (rowStaff.length === 0) {
60623			if (staffId > 0) {
60624				var staffName = UserPortal.getStaffName(staffId);
60625				var rowId = 'staff-row-' + staffId;
60626				var htmLabel = '<span class="pos-staff-label">' + staffName + '</span>';
60627				var htm = '<div id="' + rowId + '" staff_id="' + staffId + '" class="pos-staff-line-item">' + htmLabel + '</div>';
60628				var trsvc = jtix.find('.pos-service-line-item:last');
60629				var isClientRequest = 0, tip = UTIL.coalesceMoney(jline.attr('tip_mn'));
60630				
60631				if (trsvc.length) {
60632					trsvc.after(htm);
60633				} else {
60634					jtix.append(htm);
60635				}
60636				
60637				rowStaff = jtix.find('#' + rowId);
60638				rowStaff.find('.pos-staff-label').click(SA.POS.openSelectStaff);
60639				
60640				if (staffId = jline.attr('staff_id')) {
60641					var isClientRequest = UTIL.parseBool(jline.attr('client_request_fl'));
60642				}
60643				
60644				_setStaffHeader2(jtix, staffId, tip, isClientRequest);
60645				return rowStaff;
60646			} else {
60647				return jtix.find('.pos-service-line-item:last');
60648			}
60649		} else {
60650			return jtix.find('.pos-service-line-item[staff_id="' + staffId + '"]:last');
60651		}
60652	}
60653	function _addGiftCardToTicket(ln, productBox) {
60654		if (GLO.Data.provider.gift_card_generate_cd == 20 && productBox && UTIL.parseBool(productBox.is_gift_card_fl)) {
60655			var gcnr = UTIL.cleanString(ln.attr('gift_number_vc'));
60656			
60657			if (UTIL.isEmpty(gcnr)) {
60658				var gcid = ln.attr('gift_card_id');
60659				var gcmn = ln.find('.line-item-price');
60660				
60661				ln.find('.line-item-amount').prop('readonly', true);
60662				UserPortal.Price.GiftCard.openEdit(gcid, gcnr, gcmn);
60663			}
60664		}
60665	}
60666	_conTicket.getIsClientRequest = function(staffId) {
60667		for (var s=0; s < _serviceXml.length; s++) {
60668    		if (staffId == _serviceXml.eq(s).attr('staff_id')) {
60669    			if (UTIL.parseBool(_serviceXml.eq(s).attr('client_request_fl'))) {
60670    				return true;
60671    			}
60672    		}
60673    	}
60674    	
60675    	return false;
60676	}
60677	function _lineHtm(lineId, name, inventoryId, serviceId, sgid, amount, price, staffId, isFA, productBox) {
60678		var divAttributes = 'id="' + lineId + '"';
60679		var numberInputType = "text", cssClass = '';
60680        
60681        if (!UTIL.isEmpty(inventoryId)) {
60682        	divAttributes += ' inventory_id="' + inventoryId + '"';
60683        	cssClass = ' pos-product-line-item';
60684        } else if (!UTIL.isEmpty(serviceId)) {
60685        	divAttributes += ' service_id="' + serviceId + '" service_group_id="' + sgid + '"';
60686        	cssClass = ' pos-service-line-item';
60687        } else {
60688        	var warnMsg = '_lineHtm(' + name + ', ' + price + ', ' + staffId + ')';
60689        	GLO.Log.insertSimple(warnMsg, JSON.stringify(productBox), 'warning');
60690        }
60691        
60692        if (!UTIL.isEmpty(staffId)) {
60693        	divAttributes += ' staff_id="' + staffId + '"';
60694        	
60695        	if (!isFA &&_conTicket.getIsClientRequest(staffId)) {
60696        		divAttributes += ' client_request_fl="1"';
60697        	}
60698        }
60699        
60700        if (isFA) { divAttributes += ' is_first_available_fl="1"'; }
60701        
60702        if (productBox) {
60703			if (!UTIL.isEmpty(productBox.tax_rate_pct)) {
60704	    		divAttributes += ' custom_tax_rate_pct="' + productBox.tax_rate_pct + '"';
60705	    	}
60706	    	
60707	    	if (UTIL.parseBool(productBox.is_gift_card_fl)) {
60708	    		divAttributes += ' is_gift_card_fl="1"';
60709	    	}
60710		}
60711		
60712		if (GLO.Info.isAndroid) { numberInputType = "number"; }
60713    	
60714    	price = UTIL.displayMoney(price, true, false, true);
60715    	
60716    	return '<div ' + divAttributes + ' class="pos-ticket-line-item new-line-item' + cssClass + '" click_count_nr="1">'
60717                    + '<span class="ticket-row-remove" onclick="SA.Ticket.removeLine(this)"> <span class="ui-icon ui-icon-circle-close"></span> </span>'
60718                    + name
60719                    + '<input type="' + numberInputType + '" class="line-item-amount" pattern="[0-9]*" maxlength="2" onkeypress="UI.numberOnly(event)" onkeyup="SA.Ticket.changeAmount(this)" value="' + amount + '">'
60720                    + '<span class="dollar-sign">$</span>'
60721                    + '<input type="' + numberInputType + '" class="line-item-price" pattern="[0-9]*" maxlength="9" onkeypress="UI.numberOnly(event)" onkeyup="SA.Ticket.changePrice(this)" onclick="SA.Ticket.clickPrice(this)" value="' + price + '">'
60722                + '</div>';
60723	}
60724    
60725    function _addLineToHeader() {
60726    	clearTimeout(_addLineToHeaderTimeout);
60727    	
60728    	var total = $('#pos-ticket-total-box > b').text();
60729    	var header = $('#header-ticket-info').addClass('lineAdded');
60730    	$('#header-ticket-total').text(total);
60731    	
60732		_addLineToHeaderTimeout = setTimeout(function() {
60733			$('#header-ticket-info').removeClass('lineAdded');
60734		}, 400);
60735    }
60736    
60737    _conTicket.addLineEnd = function(id, clickCnt) {
60738    	var ln = $('#pos-ticket-order #' + id);
60739    	var actualClicks = parseInt(ln.attr('click_count_nr'));
60740    	
60741    	if (actualClicks === clickCnt) {
60742    		ln.removeClass('new-line-item');
60743    	} else if (ln.length > 0) {
60744    		setTimeout(function() {
60745    			SA.Ticket.addLineEnd(id, actualClicks);
60746    		}, 900);
60747    	}
60748	}
60749	
60750	_conTicket.hasUnsavedChange = function() {
60751		return $('#pos-ticket #btnSaveTicket').find('>a').hasClass('unsaved-change');
60752	}
60753	_conTicket.ticketChanged = function() {
60754		$('#pos-ticket #btnSaveTicket').find('>a').addClass('unsaved-change');
60755		
60756		SA.Ticket.adjustMultiTicketTotal();
60757		SA.Ticket.applyDiscounts(null, true);
60758	}
60759	_conTicket.ticketSaved = function(smid) {
60760		$('#pos-ticket #btnSaveTicket').find('>a').removeClass('unsaved-change');
60761		//$('#pos-ticket').attr('schedule_multi_id', smid);
60762	}
60763	
60764	function _setDeleteXml(row) {
60765		if (row.hasClass('pos-service-line-item')) {
60766			var scheduleId = row.attr('schedule_id');
60767			
60768			if (!UTIL.isEmpty(scheduleId)) {
60769				if (!UTIL.isEmpty(_deleteScheduleIds)) {
60770					_deleteScheduleIds += ',' + scheduleId;
60771				} else {
60772					_deleteScheduleIds = scheduleId;
60773				}
60774			}
60775		} else {
60776			var siids = UTIL.cleanString(row.attr('schedule_inventory_ids')).split(',');
60777			
60778			for (var i=0; i < siids.length; i++) {
60779				if (!UTIL.isEmpty(siids[i])) {
60780					_deleteInventoryXml += '<li del_schedule_inventory_id="' + siids[i] + '"/>';
60781				}
60782			}
60783		}
60784	}
60785	
60786	_conTicket.getClientLoyaltyPoints = function() {
60787		return UTIL.coalesceInt(_clientLoyalty, 0);
60788	}
60789	
60790	_conTicket.viewClientProfile = function(clientId, clientName) {
60791		if (!UTIL.isNumber(clientId)) {
60792			clientId = _conTicket.clientId;
60793			clientName = _conTicket.clientName;
60794		}
60795		
60796		GLO.Popup.closeIfExist($('#pop-ticket-client-view').closest('.glopop'));
60797		GLO.Popup.closeIfExist($('#pop-edit-client-tag').closest('.glopop'));
60798		
60799		ClientProfile.goto(clientId, 1, UTIL.replaceQuotes(clientName));
60800	}
60801	_conTicket.addClientView = function() {
60802		var btnView = '<span class="btnAdd"><a onclick="SA.Ticket.viewClientProfile()">View Profile</a></span>';
60803		var btnChange = '<span class="btnAdd"><a onclick="SA.Ticket.addClient(true)">Change Client</a></span>';
60804		var htm = '<p style="margin: 8px; margin-left: 12px;">' + _conTicket.clientName + '</p>' + btnView + btnChange;
60805		var jpop = GLO.Popup.Custom.openSimple('<div id="pop-ticket-client-view">' + htm + '</div>', 'Client');
60806		GLO.Popup.Custom.singleButton(jpop, 'Close');
60807	}
60808	_conTicket.addClient = function(isForce) {
60809		var jbtn = $('#pos-add-client-button');
60810		
60811		if (!isForce && !UTIL.isEmpty(_conTicket.clientId)) {
60812			SA.Ticket.viewClientProfile();			//_conTicket.addClientView();
60813			return;
60814		}
60815		
60816		GLO.Popup.closeIfExist($('#pop-ticket-client-view').closest('.glopop'));
60817		
60818		var h1 = 'Enter Client Name or Phone Number';
60819		var htm = null, cssStyle = null;
60820		var uriClientSearch = GLO.Link.Object.Provider.ClientSearch + '?HasApptToday=1';
60821		var jclient = jbtn.find('input');
60822		
60823		var jkeypad = UI.Keypad.openKeypadCharacter(h1, htm, jclient, cssStyle, false, SA.Ticket.addClientNewOpen, true).addClass('sa-keypad-name');
60824		var jinput = jkeypad.find('input.sa-keypad');
60825		
60826		UI.initAutoComplete(jinput, uriClientSearch, UserPortal.importClientOpen, SA.Ticket.addClientSelected);
60827		
60828		/* tried to set cursor to end, but didn't work
60829		setTimeout(function() {
60830			var input = jclient[0];
60831			input.selectionStart = input.selectionEnd = input.value.length;
60832		}, 4500);
60833		
60834		jinput.focus(function() {
60835		  	var that = this;
60836		  	
60837		  	setTimeout(function() {
60838		  		that.selectionStart = that.selectionEnd = 10000;
60839		  	}, 0);
60840		}); */
60841	}
60842	
60843	function _getNoteLabel(cssClass, tagCount) {			//cssClass: appt-request, appt-staff-only, client-important-note, client-tag, client-tag-appt
60844		if (cssClass == 'appt-request') {
60845			var label = 'Appointment Request'
60846		} else if (cssClass == 'appt-staff-only') {
60847			var label = 'Appointment Staff Only'
60848		} else if (cssClass == 'client-important-note') {
60849			var label = 'Important Note'
60850		} else if (cssClass == 'client-tag') {
60851			var label = UTIL.pluralLabel(tagCount, 'Client Tag');
60852		} else {
60853			return '';
60854		}
60855		
60856		return '<b class="client-note-label">' + label + '</b>';
60857	}
60858	
60859	_conTicket.loadClientNote = function(cssClass, note, tagCount) {
60860		var htmLabel = _getNoteLabel(cssClass, tagCount);
60861		var htmNote = '<span class="client-note">' + note + '</span>';
60862		var htm = '<div class="client-note-row ' + cssClass + '">' + htmLabel + htmNote + '</div>';
60863		var jca = $('#pos-ticket-client-attributes').removeClass('hide');
60864		
60865		jca.find('.' + cssClass).html('');
60866		
60867		if (cssClass == 'client-tag' || cssClass == 'client-tag-appt' || cssClass == 'client-birthday' || cssClass == 'client-loyalty' || cssClass == 'client-gift') {
60868			jca.prepend(htm);
60869		} else {
60870			jca.append(htm);
60871		}
60872		
60873		var rowCount = jca.find('.client-note-row').length;
60874		$('#pos-container').removeClass('client-note1').removeClass('client-note2').removeClass('client-note3').removeClass('client-note4').addClass('client-note' + rowCount);
60875	}
60876	_conTicket.removeClient = function(smid, clientId, fnYes) {
60877		var jservices = $('#pos-ticket').find('.pos-ticket-line-item.pos-service-line-item');
60878		
60879		if (jservices.length) {
60880			UserPortal.Edit.removeClient(smid, clientId, fnYes);
60881		} else {
60882			UserPortal.Price.removeClient(smid, clientId, fnYes);
60883		}
60884	}
60885	
60886	_conTicket.clientReset = function() {
60887		_clientTagXml = _clientTagRelationshipXml = null;
60888		_conTicket.clientId = _conTicket.clientName = _conTicket.clientType = null;
60889		_clientLoyalty = _availableLoyalty = _referralDiscount = 0;
60890		
60891		_cftid = _membershipId = _birthDays = null;
60892		_giftBalance = 0;
60893		_providerReferral = null;
60894		
60895		_resetClientAttributes(true);
60896		_setClientName();
60897	}
60898	
60899	_conTicket.addClientReset = function(clientNameOrPhone) {
60900		var jbtn = $('#pos-add-client-button');
60901		var isNewClient = UTIL.isEmpty(clientNameOrPhone);
60902		
60903		clientNameOrPhone = UTIL.coalesceString(clientNameOrPhone, jbtn.find('input').val());
60904		
60905		var smid = $.trim($('#pos-ticket').attr('schedule_multi_id'));
60906		var clientId = _conTicket.clientId;
60907		
60908		if (!UTIL.isEmpty(smid)) {
60909			_setClientName();
60910			_conTicket.removeClient(smid, clientId, SA.Ticket.clientReset);
60911		} else {
60912			_conTicket.clientReset();
60913		}
60914		
60915		return isNewClient;
60916	}
60917	_conTicket.addClientSelected = function(element, event, ui) {
60918		$('#pos-container').removeClass('client-note1').removeClass('client-note2').removeClass('client-note3').removeClass('client-note4');
60919		$('#pos-ticket-client-attributes').html('').addClass('hide');		//.find('.client-note-row').remove()
60920		
60921		/* if (GLO.Data && GLO.Data.provider && UTIL.coalesceInt(ui.item.provider_id, GLO.Data.provider.id) != GLO.Data.provider.id) {
60922    		UserPortal.importClientOpen(jclient, event, ui);
60923    		return;
60924    	} */
60925		
60926		if (!UTIL.isEmpty(ui.item.smid)) {
60927			UserPortal.Create.Checkout.openEdit(element, event, ui);
60928		} else {
60929			var clientId = ui.item.id;
60930			var clientName = ui.item.value;			//ui.item.label
60931			var ctype = ui.item.client_type_cd;
60932			
60933			_conTicket.addClientCompleteFromAutoComplete(clientId, clientName, ctype, ui.item);
60934		}
60935		
60936		GLO.Popup.closeIfExist($('#pop-sa-keypad').closest('.glopop'));
60937		
60938		if ($('#pos-container').hasClass('display-staff-screen')) {
60939			_conTicket.displayTicket();
60940			$('#pos-staff-list-client').val('');
60941			
60942			setTimeout(function() {						//= necessary since delay in auto-complete populating input box
60943				$('#pos-staff-list-client').val('').removeAttr('autoid').removeAttr('autoname');
60944			}, 500);
60945		}
60946	}
60947	_conTicket.addClientNewOpen = function() {
60948		var clientNameOrPhone = $('#pos-add-client-button').find('input').val();
60949		
60950		if (SA.Ticket.addClientReset(clientNameOrPhone)) {
60951			return;
60952		}
60953		
60954		var clientResult = UTIL.getNameAndPhone(clientNameOrPhone);
60955		_conTicket.addClientNewOpen2(clientResult);
60956	}
60957	_conTicket.addClientNewOpen2 = function(clientResult) {
60958		GLO.ClientProfile.openSimpleAdd();
60959		var jpop = $('#simple-addclient').closest('.glopop');
60960		//var clientResult = UTIL.getNameAndPhone(clientNameOrPhone);
60961		
60962		if (clientResult || clientResult.phone) {
60963			if (UTIL.Validate.phone(clientResult.phone)) {
60964				jpop.find('#Mobile_Phone_vc').val(clientResult.phone).blur();
60965				
60966				if (clientResult.hasNameAndPhone) {
60967					jpop.find('#Client_Name_vc').val(clientResult.name);
60968				}
60969			} else {
60970				jpop.find('#Client_Name_vc').val(clientResult.text);
60971			}
60972		}
60973	}
60974	_conTicket.addClientLoad = function(clientId, clientName, jdata) {			//called when client imported from another location by auto-complete
60975		var ctype = jdata.attr('client_type_cd');
60976		var hasNote = jdata.attr('has_note_fl');
60977		
60978		var cftid = jdata.attr('cftid');
60979		var membershipId = jdata.attr('membership_id');
60980		var giftBalance = jdata.attr('gift_balance_mn');
60981		var clientLoyalty = jdata.attr('client_loyalty_sr');
60982		var tagCount = jdata.attr('tag_count_sr');
60983		var birthDays = jdata.attr('birth_sr');
60984		var referId = jdata.attr('provider_referral_id');
60985		
60986		_conTicket.addClientComplete(clientId, clientName, ctype, hasNote, cftid, membershipId, giftBalance, clientLoyalty, tagCount, birthDays, referId);
60987	}
60988	_conTicket.addClientFromPos = function(clientId, clientName, email, mobile, isNewUser, isOutcall) {
60989    	if (UTIL.parseBool(isNewUser)) {
60990    		var ctype = 1;
60991    	} else {
60992    		var ctype = 2;
60993    	}
60994    	
60995    	_conTicket.addClientComplete(clientId, clientName, ctype);
60996		_displayClientAttributes();
60997		
60998		if ($('#pos-container').hasClass('display-staff-screen')) {
60999			_conTicket.displayTicket();
61000			$('#pos-staff-list-client').val('');
61001			
61002			setTimeout(function() {						//= necessary since delay in auto-complete populating input box
61003				$('#pos-staff-list-client').val('');
61004			}, 500);
61005		}
61006    }
61007	_conTicket.addClientCompleteFromAutoComplete = function(clientId, clientName, ctype, uiItem) {
61008		if (uiItem) {
61009			ctype = UTIL.coalesce(ctype, uiItem.client_type_cd);
61010			var hasNote = uiItem.has_note_fl;
61011			
61012			var cftid = uiItem.cftid;
61013			var membershipId = uiItem.membership_id;
61014			var giftBalance = uiItem.gift_balance_mn;
61015			
61016			var clientLoyalty = uiItem.loyalty_points_nr;
61017			var tagCount = uiItem.tag_count_sr;
61018			var birthDays = uiItem.birth_sr;
61019			var referId = uiItem.provider_referral_id;
61020		} else {
61021			ctype = UTIL.coalesce(ctype, 1);
61022			var hasNote = false, cftid = null, membershipId = null, giftBalance = null, clientLoyalty = null, tagCount = null, birthDays = null, referId = null;
61023		}
61024		
61025		_conTicket.addClientComplete(clientId, clientName, ctype, hasNote, cftid, membershipId, giftBalance, clientLoyalty, tagCount, birthDays, referId);
61026		_displayClientAttributes();
61027	}
61028	_conTicket.addClientComplete = function(clientId, clientName, ctype, hasNote, cftid, membershipId, giftBalance, clientLoyalty, tagCount, birthDays, referId) {
61029		clientName = $.trim(clientName);
61030		
61031		_conTicket.clientName = clientName;
61032		_conTicket.clientId = $.trim(clientId);
61033		_conTicket.clientType = $.trim(ctype);
61034		
61035		_clientLoyalty = $.trim(clientLoyalty);
61036		_ticketLoyalty = _availableLoyalty = 0;
61037		
61038		_cftid = $.trim(cftid);
61039		_membershipId = $.trim(membershipId);
61040		_giftBalance = $.trim(giftBalance);
61041		_birthDays = $.trim(birthDays);
61042		_providerReferral = referId;
61043		
61044		if (!_isLoading) {
61045			_clientTagXml = _clientTagRelationshipXml = null;
61046			_referralDiscount = 0;
61047		}
61048		
61049		_addClientComplete2(hasNote, tagCount);
61050	}
61051	
61052	function _setClientName() {
61053		var clientName = _conTicket.clientName;
61054		
61055		//if (innerWidth < 1240) { clientName = UTIL.maxString(clientName, 24, true); }
61056		
61057		if (!UTIL.isEmpty(clientName)) {
61058			var jticket = $('#pos-ticket').addClass('has-client');
61059			jticket.find('#pos-add-client-button').attr('title', _conTicket.clientName).find('input').val(clientName);
61060		} else {
61061			var jticket = $('#pos-ticket').removeClass('has-client');
61062			jticket.find('#pos-add-client-button').removeAttr('title').find('input').val('');
61063		}
61064	}
61065	function _addClientComplete2(hasNote, tagCount) {
61066		_setClientName();
61067		
61068		if (UTIL.parseBool(hasNote)) {
61069			UserPortal.displayIfClientHasStaffNote(_conTicket.clientId, true);
61070		}
61071		
61072		if (tagCount > 0 && (UTIL.isEmpty(_clientTagXml) || _clientTagXml.length === 0)) {
61073			UserPortal.lookupClientTags(_conTicket.clientId);
61074		}
61075		
61076		if (!_isLoading && !UTIL.isEmpty(_conTicket.clientName)) {
61077			SA.Ticket.applyDiscounts(null, true);
61078		}
61079	}
61080	
61081	_conTicket.addClientAttributesToJson = function(json) {
61082		json.client_loyalty_nr = _clientLoyalty;
61083		json.available_loyalty_nr = _availableLoyalty;
61084		
61085		json.membership_id = _membershipId;
61086		json.birth_sr = _birthDays;
61087	}
61088	
61089	_conTicket.clearDeleteInventoryXml = function(smid) {
61090		//var smid = UTIL.cleanString($('#appt-price-popup').closest('.glopop').find('#price-header').attr('schedule_multi_id'));
61091		
61092        if (!_openTicketMatchesPOS(smid)) { return; }
61093        
61094        _deleteInventoryXml = '';
61095    }
61096	
61097	_conTicket.getDeleteInventoryXml = function(priceDeleteXml) {
61098		var smid = UTIL.cleanString($('#appt-price-popup').closest('.glopop').find('#price-header').attr('schedule_multi_id'));
61099		
61100        if (!_openTicketMatchesPOS(smid)) { return; }
61101		
61102		var li = $('<ul>' + priceDeleteXml + '</ul>').find('li');
61103		var posli = $('<ul>' + _deleteInventoryXml + '</ul>').find('li');
61104		
61105		for (var p=0; p < posli.length; p++) {
61106			var siid = posli.eq(p).attr('del_schedule_inventory_id');
61107			
61108			for (var i=0; i < li.length; i++) {
61109				if (siid == li.eq(i).attr('del_schedule_inventory_id')) {
61110					siid = null;
61111				}
61112			}
61113			
61114			if (siid !== null) {
61115				priceDeleteXml += '<li del_schedule_inventory_id="' + siid + '"/>';
61116			}
61117		}
61118		
61119		return priceDeleteXml;
61120	}
61121	
61122	_conTicket.removeLine = function(element) {
61123		if (!element) { element = this; }
61124		
61125		var row = $(element).closest('.pos-ticket-line-item');
61126		var staffId = row.attr('staff_id');
61127		var jticket = $('#pos-ticket-order');
61128		
61129		_setDeleteXml(row);
61130		row.remove();
61131		
61132		if (jticket.find('.pos-service-line-item[staff_id="' + staffId + '"]').length === 0) {
61133			jticket.find('#staff-row-' + staffId).remove();
61134		}
61135		
61136		_conTicket.recalculate();
61137		_conTicket.ticketChanged();
61138		_finishAddProductOrService();
61139		
61140		_conTicket.setStaffHeader();
61141		_conTicket.enableOrDisableTicketScroll()
61142	}
61143	
61144	_conTicket.enableOrDisableTicketScroll = function() {
61145		var jtix = $('#pos-ticket-order');
61146		var lineCount = jtix.find('.pos-ticket-line-item').length;
61147		var staffCount = jtix.find('.pos-staff-line-item').length;
61148		var productLabel = jtix.find('#pos-product-label-row').length;
61149		var allowedLines = parseInt(jtix.height()/40) - 1;				//"-1" just to be extra safe
61150		
61151		if (jtix.hasClass('scroll-active')) {
61152			if (lineCount + staffCount + productLabel < allowedLines) {
61153				jtix.removeClass('scroll-active');
61154			}
61155		} else {
61156			if (lineCount + staffCount + productLabel >= allowedLines) {
61157	    		jtix.addClass('scroll-active');
61158	    	}
61159		}
61160	}
61161    
61162    _conTicket.changeAmount = function(element) {
61163    	_conTicket.recalculate();
61164    	_conTicket.ticketChanged();
61165	}
61166	_conTicket.changePrice = function(element) {
61167		_conTicket.recalculate();
61168		_conTicket.ticketChanged();
61169	}
61170	_conTicket.clickPrice = function(element) {
61171		element.select();
61172		
61173		if (UI.Keypad.isButtonBased()) {
61174    		UI.Keypad.openKeypadPrice(element);
61175    	}
61176	}
61177	
61178	_conTicket.recalculate = function() {
61179		if (_isLoading) { return; }
61180		
61181    	var jtix = $('#pos-ticket');
61182    	var lns = jtix.find('.pos-ticket-line-item');
61183    	var hasCheckout = UserPortal.Price.isTicketHasCheckout();
61184    	var totalDiscount = 0, totalFee = 0, sub = 0, totalTax = 0, totalTip = 0;
61185    	
61186    	for (var i=0; i < lns.length; i++) {
61187    		var jline = lns.eq(i);
61188    		var lineTotal = UTIL.coalesceMoney(jline.find('.line-item-amount').val() * UTIL.coalesceMoney(jline.find('.line-item-price').val()));
61189    		var tip = UTIL.coalesceMoney(jline.attr('tip_mn'));
61190    		var addOnFee = UTIL.coalesceMoney(jline.attr('add_on_fee_mn'));
61191    		var discount = UTIL.coalesceMoney(jline.attr('new_discount_mn'), jline.attr('discount_mn'));
61192    		var tax = _getLineItemTax(jline, hasCheckout, lineTotal, discount);
61193    		
61194    		sub += lineTotal;
61195    		totalDiscount = UTIL.coalesceMoney(discount + totalDiscount);
61196    		totalFee = UTIL.coalesceMoney(addOnFee + totalFee);
61197    		totalTax = UTIL.coalesceMoney(tax + totalTax);
61198    		totalTip = UTIL.coalesceMoney(tip + totalTip);
61199    	}
61200    	
61201    	var totalRow = jtix.find('#pos-ticket-total-line');
61202    	var totalCell = totalRow.find('#pos-ticket-total-box b');
61203    	var jdiscount = totalRow.find('#pos-ticket-total-discount');
61204    	
61205    	var totalDiscount = UTIL.coalesceMoney(jdiscount.find('#pos-ticket-discount-amount').text().replace('$', ''));
61206    	var totalAddOnFee = UTIL.coalesceMoney(jdiscount.find('#pos-ticket-add-on-fee-amount').text().replace('$', ''));
61207    	var total = UTIL.displayMoney(UTIL.coalesceMoney(sub) + totalTax - totalDiscount + totalAddOnFee + totalTip, false, false, true);
61208    	
61209    	totalRow.find('#pos-ticket-total-sub b').html(UTIL.displayMoney(sub, false, false, true));
61210    	totalRow.find('#pos-ticket-total-tax b').html(UTIL.displayMoney(totalTax, false, false, true));		//if (tax > 0 && !hasCheckout) {
61211    	totalRow.find('#pos-ticket-total-tip b').html(UTIL.displayMoney(totalTip, false, false, true));
61212    	
61213    	if (totalTip == 0 && totalTax > 0) {
61214    		totalRow.find('#pos-ticket-total-tip').addClass('hide');
61215    		totalRow.find('#pos-ticket-total-tax').removeClass('hide');
61216    	} else {
61217    		totalRow.find('#pos-ticket-total-tax').addClass('hide');
61218    		totalRow.find('#pos-ticket-total-tip').removeClass('hide');
61219    	}
61220    	
61221    	totalCell.html(total);
61222    	//totalRow.find('.total-tip').html('');
61223    	
61224    	_styleTotalCell(totalCell);
61225	}
61226	
61227	function _getLineItemTax(jline, hasCheckout, lineTotal, discount) {
61228		if (hasCheckout) {
61229			return UTIL.coalesceMoney(jline.attr('tax_mn'));
61230		} else {
61231    		var customTaxRate = jline.attr('custom_tax_rate_pct');
61232			
61233			if (jline.hasClass('pos-service-line-item')) {
61234    			itemTaxRate = UTIL.coalesceFloat(customTaxRate, GLO.serviceTax, 0)/100;
61235    		} else {
61236    			itemTaxRate = UTIL.coalesceFloat(customTaxRate, GLO.inventoryTax, 0)/100;
61237    		}
61238		
61239    		if (itemTaxRate > 0) {
61240    			return UTIL.coalesceMoney(itemTaxRate * (lineTotal - discount));
61241			}
61242		}
61243		
61244		return 0;
61245	}
61246	
61247	function _styleTotalCell(jcell) {
61248		if (innerWidth > 1680) { return; }
61249		
61250		var totalLen = jcell.text().length;
61251    	
61252    	if (totalLen < 4) {
61253    		var css = { "margin-top": "-4px", "font-size": "30px" };
61254    	} else if (totalLen < 6) {
61255    		var css = { "font-size": "28px" };
61256    	} else if (totalLen < 8) {
61257    		var css = { "margin-top": "2px", "font-size": "24px" };
61258    	} else if (totalLen < 10) {
61259    		var css = { "margin-top": "4px", "font-size": "20px" };
61260    	} else if (totalLen < 11) {
61261    		var css = { "margin-top": "6px", "font-size": "16px" };
61262    	} else if (totalLen < 12) {
61263    		var css = { "margin-top": "8px", "font-size": "14px" };
61264    	} else {
61265    		var css = { "margin-top": "8px", "letter-spacing": "0", "font-size": "13px" };
61266    	}
61267    	
61268    	jcell.css(css);
61269    	SA.Ticket.adjustMultiTicketTotal();
61270	}
61271	
61272	_conTicket.processSave = function(jPricePop) {			//= when ticket opened by price.get from a save --> if matches POS ticket merge siid(s).
61273		var lis = $('<ul>' + UserPortal.Price.inventoryXml + '</ul>').find('li');
61274		var jticket = $('#pos-ticket');
61275		var jlines = jticket.find('.pos-ticket-line-item');
61276		var smidPOS = jticket.attr('schedule_multi_id');
61277		var smidPopup = jPricePop.find('#price-header').attr('schedule_multi_id');
61278		var iid, siid, line;
61279		
61280		if (lis.length === 0 || jlines.length === 0) { return; }
61281		if (smidPOS != smidPopup) { return; }
61282		
61283		for (var i=0; i < lis.length; i++) {
61284			iid = UTIL.cleanString(lis.eq(i).attr('inventory_id'));
61285			siid = UTIL.cleanString(lis.eq(i).attr('schedule_inventory_id'));
61286			line = _findLineByInventoryId(jlines, iid);
61287			
61288			if (line !== null) {
61289				_addToLine(line, siid);
61290			} else {
61291				_conTicket.addProductLine(iid);
61292			}
61293		}
61294		
61295		_conTicket.recalculate();
61296	}
61297	
61298	function _addToLine(line, siid, iid) {
61299		var siids = UTIL.cleanString(line.attr('schedule_inventory_ids'))
61300		var arr = siids.split(',');
61301		var amt = UTIL.coalesceInt(line.find('.line-item-amount').val(), 0);
61302		
61303		if (UTIL.isEmpty(siids)) {
61304			if (amt === 0) {
61305				return;
61306			} else {
61307				line.attr('schedule_inventory_id', siid);
61308				return true;
61309			}
61310		}
61311		
61312		for (var i=0; i < arr.length; i++) {
61313			if (arr[i] == siid) {
61314				return false;
61315			}
61316		}
61317		
61318		if (!UTIL.isEmpty(siids)) { siids += ',' + siid; }
61319		line.attr('schedule_inventory_id', siids);
61320		return true;
61321	}
61322	
61323	function _findLineByInventoryId(jlines, iid) {
61324		for (var i=0; i < jlines.length; i++) {
61325			if (jlines.eq(i).attr('inventory_id') == iid) {
61326				return jlines.eq(i);
61327			}
61328		}
61329		
61330		return null;
61331	}
61332	
61333	_conTicket.hideChangeDue = function() {
61334		$('#pos-ticket-change-due').removeClass('display').text('');
61335	}
61336	
61337	_conTicket.openKeypad = function(amountInCents) {
61338		if (GLO.isPOS && GLO.Sale.Keypad.isIncludeTax()) {
61339			GLO.Sale.Keypad.includeTax();
61340		}
61341		
61342		GLO.Sale.Keypad.openAsPopup();
61343		
61344		var li = '<li id=""> <span class="btnAdd" onclick="SA.Ticket.processKeypadAmount()"> <a>Complete Payment</a> </span> </li>';
61345		
61346		var jkeypad = $('#sale-keyboard').closest('#simplemodal-container');
61347		jkeypad.find('#sale-keyboard-options').addClass('keypad-single-button').html(li);
61348		
61349		if (innerWidth < 1400) {
61350			setTimeout(function() {
61351				jkeypad.css({ "top": "16px", "left": "inherit", "right": "14px" });
61352			}, 80);
61353		}
61354		
61355		if (amountInCents > 0) {
61356			var jtotal = $('#keyboard-running-total');
61357			var amt = String(amountInCents);
61358			var len = amt.length;
61359			
61360			if (parseInt(amountInCents) > 99) {
61361				amt = amt.substring(0, len-2) + '.' + amt.substring(len-2);
61362			} else if (amountInCents > 9) {
61363				amt = '.' + amt;
61364			} else {
61365				amt = '.0' + amt;
61366			}
61367			
61368			jtotal.text('$' + amt);
61369		}
61370	}
61371	
61372	_conTicket.processKeypadAmount = function() {
61373		var jmodal = $('#sale-keyboard').closest('#simplemodal-container');
61374		var price = jmodal.find('#keyboard-running-total').text().replace('$', '');
61375		var jproducts = $('#pos-ticket').find('.pos-ticket-line-item');
61376    	
61377    	if (jproducts.length === 0) {
61378    		SA.Ticket.addProductLine(SA.POS.inventory_json.manual_entry.id, 1, price);
61379    	}
61380		
61381		$.modal.close();
61382		SA.Ticket.openTicket(null, 1, price);
61383	}
61384	
61385	_conTicket.openCashPayment = function(btn, amount) {
61386		var json = { "open_keypad_if_no_ticket": true };
61387		
61388		_conTicket.openTicket(btn, 1, amount, null, null, json);
61389	}
61390	
61391	function _getTicketServiceById(jservices, scheduleId) {
61392		if (UTIL.isEmpty(scheduleId)) {
61393			return null;
61394		}
61395		
61396		for (var i=0; i < jservices.length; i++) {
61397			if (scheduleId == jservices.eq(i).attr('schedule_id')) {
61398				return jservices.eq(i);
61399			}
61400		}
61401		
61402		return null;
61403	}
61404	function _getServiceXml(jservices, isCheckout) {
61405		var xml = '', prevServiceId = null, serviceCount = jservices.length;
61406		var arrUniqueStaff = [];
61407        
61408		for (var a=0; a < _serviceXml.length; a++) {
61409			var svcXml = _serviceXml.eq(a);
61410			var scheduleId = svcXml.attr('schedule_id');
61411			var jsvc = _getTicketServiceById(jservices, scheduleId);
61412			
61413			if (jsvc && jsvc.length) {				//= if not found could add check to verify is in _deleteScheduleIds
61414				if (a > 0) {
61415					prevServiceId = _serviceXml.eq(a-1).attr('service_id');
61416				}
61417				
61418				xml += _getServiceXmlRow(svcXml, jsvc, arrUniqueStaff, isCheckout, serviceCount, prevServiceId);
61419			}
61420		}
61421		
61422		for (var b=0; b < jservices.length; b++) {
61423			var jsvc = jservices.eq(b);
61424			
61425			if (UTIL.isEmpty(jsvc.attr('schedule_id'))) {
61426				if (b > 0) {
61427					prevServiceId = jservices.eq(b-1).attr('service_id');
61428				}
61429				
61430				xml += _getServiceXmlRow(null, jsvc, arrUniqueStaff, isCheckout, serviceCount, prevServiceId);
61431			}
61432		}
61433		
61434		return $(xml);
61435	}
61436	function _getBasicServiceRow(scheduleId, price, isCheckout) {
61437		var scheduleUpdateType = 1;
61438		
61439		if (!UTIL.isEmpty(scheduleId)) {
61440			scheduleUpdateType = 9;
61441		}
61442		
61443		//appt_status_cd="22" 
61444		var xml = '<tr schedule_id="' + scheduleId + '" input_type_cd="6" sutype="' + scheduleUpdateType + '" price_mn="' + price + '"';
61445		
61446		if (isCheckout) {
61447			xml += ' quick_checkout_fl="1"';
61448		}
61449		
61450		return xml;
61451	}
61452	
61453	function _getServiceXmlRow(svcXml, jsvc, arrUniqueStaff, isCheckout, serviceCount, prevServiceId) {
61454    	var scheduleId = $.trim(jsvc.attr('schedule_id'));
61455		var count = UTIL.coalesceInt(jsvc.find('.line-item-amount').val(), 0);
61456		var price = UTIL.coalesceMoney(jsvc.find('.line-item-price').val());
61457		
61458		var xml = _getBasicServiceRow(scheduleId, price, isCheckout);
61459        
61460        xml += _clientLevelXml();
61461        xml += _bookingLevelXml(serviceCount);
61462        xml += _serviceLenXml(svcXml, jsvc, isCheckout, arrUniqueStaff, prevServiceId);
61463        xml += _serviceOtherXml(jsvc, scheduleId);
61464        xml += _attributeSummaryXml();
61465    	xml += '/>';
61466        
61467        if (count === 0) {
61468        	return '';
61469        } else if (count > 1) {
61470        	for (var i=1; i < count; i++) {
61471        		xml += xml;
61472        	}
61473        }
61474        
61475        return xml;
61476    }
61477    function _attributeSummaryXml() {
61478    	var attributes = '', productTotal = 0, paymentTotal = 0, discountTotal = 0, addOnFeeTotal = 0, discountCount = 0;
61479    	var lis = $(_productXml).find('li');
61480    	
61481    	for (var p=0; p < lis.length; p++) {
61482    		var j = lis.eq(p);
61483    		var price = UTIL.coalesceMoney(j.attr('price_mn')), tax = UTIL.coalesceMoney(j.attr('tax_mn'));
61484    		var discount = UTIL.coalesceMoney(j.attr('discount_mn')), addOnFee = UTIL.coalesceMoney(j.attr('add_on_fee_mn'));
61485    		
61486    		productTotal += UTIL.coalesceMoney(price + tax - discount + addOnFee);
61487    	}
61488    	
61489    	var lps = $('<ol>' + _paymentXml + '</ol>').find('lp');
61490    	
61491    	for (var p=0; p < lps.length; p++) {
61492    		paymentTotal += UTIL.coalesceMoney(lps.eq(p).attr('payment_mn'));
61493    	}
61494    	
61495    	if (lps.length > 1) {
61496    		attributes += ' payment_dt="' + lps.eq(0).attr('payment_dt') + '"';
61497    	}
61498    	
61499    	var dds = $('<dl>' + _discountXml + '</dl>').find('dd');
61500    	discountCount = dds.length;
61501	    
61502    	for (var d=0; d < dds.length; d++) {
61503    		var dAmt = UTIL.coalesceMoney(dds.eq(d).attr('amount_mn')), feeAmt = UTIL.coalesceMoney(dds.eq(d).attr('amount_mn'), dds.eq(d).attr('fee_amount_mn'));
61504    		
61505    		if (dAmt > 0) {
61506    			discountTotal += dAmt;
61507    		}
61508    		
61509    		if (feeAmt > 0) {
61510    			addOnFeeTotal += feeAmt;
61511    		} else if (dAmt < 0) {
61512    			addOnFeeTotal -= dAmt;
61513    		}
61514    	}
61515    	
61516    	return attributes + ' inventory_price_mn="' + UTIL.coalesceMoney(productTotal) + '" total_payment_mn="' + UTIL.coalesceMoney(paymentTotal)
61517    			+ '" total_addOnFee_mn="' + UTIL.coalesceMoney(addOnFeeTotal) + '" total_discount_mn="' + UTIL.coalesceMoney(discountTotal) + '" discount_count_sr="' + discountCount + '"';
61518    }
61519    function _serviceOtherXml(jsvc, scheduleId) {
61520    	var crequest = UTIL.parseBool(jsvc.attr('client_request_fl'));
61521    	
61522    	if (!crequest && UTIL.isEmpty(scheduleId) && UTIL.isEmpty(jsvc.attr('client_request_fl'))) {
61523    		var jstaff = $('#pos-ticket .pos-staff-line-item');
61524    		var staffId = jsvc.attr('staff_id');
61525    		
61526    		for (var i=0; i < jstaff.length; i++) {
61527    			if (jstaff.eq(i).attr('staff_id') == staffId) {
61528    				crequest = jstaff.eq(i).hasClass('is-client-request');
61529    				break;
61530    			}
61531    		}
61532    	}
61533    	
61534    	var customD = UTIL.parseBool(jsvc.attr('custom_discount_fl'));
61535    	var split = $.trim(jsvc.attr('commission_split_cd'));
61536    	var splitPercent = $.trim(jsvc.attr('commission_split_pct'));
61537    	
61538    	var resourceId = $.trim(jsvc.attr('service_resource_id'));
61539    	var recurId = $.trim(jsvc.attr('schedule_recur_id'));
61540    	var svcAttributeId = $.trim(jsvc.attr('service_attribute_id'));
61541    	
61542    	var addOnFee = UTIL.coalesceMoney(jsvc.attr('add_on_fee_mn'));
61543    	var discount = UTIL.coalesceMoney(jsvc.attr('discount_mn'));
61544    	var discountNew = UTIL.coalesceMoney(jsvc.attr('new_discount_mn'));
61545    	
61546    	var tip = UTIL.coalesceMoney(jsvc.attr('tip_mn'));
61547    	var tax = UTIL.coalesceMoney(jsvc.attr('tax_mn'));
61548    	var outcallFee = UTIL.coalesceMoney(jsvc.attr('outcall_fee_mn'));
61549    	var isOutcall = UTIL.parseBool(jsvc.attr('outcall_fl'));
61550    	
61551    	var attributes = ' client_request_fl="' + crequest + '" custom_discount_fl="' + customD + '" commission_split_cd="' + split + '" commission_split_pct="' + splitPercent
61552    			+ '" service_resource_id="' + resourceId + '" schedule_recur_id="' + recurId + '" service_attribute_id="' + svcAttributeId
61553    			+ '" tip_mn="' + tip + '" tax_mn="' + tax + '" outcall_fl="' + isOutcall + '" outcall_fee_mn="' + outcallFee + '"';
61554    	
61555    	if (addOnFee > 0) {
61556        	attributes += ' add_on_fee_mn="' + addOnFee + '"';
61557        }
61558        
61559        if (discount !== 0) {
61560        	attributes += ' discount_mn="' + discount + '"';
61561        }
61562        
61563        if (discountNew !== 0) {
61564        	attributes += ' new_discount_mn="' + discountNew + '"';
61565        }
61566    	
61567    	return attributes;
61568    }
61569    function _serviceLenXml(svcXml, jsvc, isCheckout, arrUniqueStaff, prevServiceId) {
61570    	var isFA = UTIL.parseBool(jsvc.attr('is_first_available_fl'));
61571    	
61572    	var staffId = $.trim(jsvc.attr('staff_id'));
61573		var serviceId = jsvc.attr('service_id');
61574		var sgid = jsvc.attr('service_group_id');
61575		 
61576    	var ojDefault = UserPortal.Booking.lookupDefault(serviceId, staffId, null, true);
61577        var svcLen = UTIL.coalesceInt(jsvc.attr('service_length_nr'), ojDefault.minutes_nr);
61578        var prepNR = UTIL.coalesceInt(jsvc.attr('prep_nr'), ojDefault.prep_nr, 0);
61579        var prepFL = UTIL.parseBool(jsvc.attr('prep_fl'), ojDefault.prep_fl);
61580        
61581        var processingNR = UTIL.coalesceInt(jsvc.attr('processing_nr'), ojDefault.processing_nr, 0);
61582        var processingFL = UTIL.parseBool(jsvc.attr('processing_fl'), ojDefault.processing_fl);
61583        var finishOutNR = UTIL.coalesceInt(jsvc.attr('finish_out_nr'), ojDefault.finish_out_nr, 0);
61584        var finishOutFL = UTIL.parseBool(jsvc.attr('finish_out_fl'), ojDefault.finish_out_fl);
61585        
61586    	var attributes = ' staff_id="' + staffId + '" service_id="' + serviceId + '" service_group_id="' + sgid 
61587    			+ '" service_length_nr="' + svcLen + '" prep_nr="' + prepNR + '" prep_fl="' + prepFL
61588    			+ '" processing_nr="' + processingNR + '" processing_fl="' + processingFL + '" finish_out_nr="' + finishOutNR + '" finish_out_fl="' + finishOutFL + '"';
61589    	
61590    	if (isFA) {
61591        	attributes += ' is_first_available_fl="1"';
61592        }
61593        
61594        var totalServiceLen = _serviceTotalLen(svcLen, processingNR, processingFL, finishOutNR, finishOutFL);
61595        var isSameStart = UTIL.isNumber(prevServiceId) && GLO.Template.RequestAppt.isSameStart(prevServiceId, serviceId);
61596        
61597        return attributes + _getStaffServiceDateTime(jsvc, isCheckout, arrUniqueStaff, staffId, isFA, totalServiceLen, isSameStart);
61598    }
61599    function _getStaffServiceDateTime(jsvc, isCheckout, arrUniqueStaff, staffId, isFA, totalServiceLen, isSameStart) {
61600    	var day = $.trim(jsvc.attr('appt_dt')), tm = $.trim(jsvc.attr('time_vc')), dtEnd = jsvc.attr('end_dt');
61601    	
61602    	if (UTIL.isDate($.trim(day + ' ' + tm))) {
61603        	var dtStart = new Date(day + ' ' + tm);
61604        	
61605        	if (UTIL.isDate(dtEnd)) {
61606        		dtEnd = new Date(dtEnd);
61607        	} else {
61608        		dtEnd = new Date(dtStart).addMinutes(totalServiceLen);
61609        	}
61610	    } else {
61611	    	if (isCheckout || (UTIL.isDate(_dtCheckout) && _dtCheckout > new Date())) {		//dtEnd must be <= _dtCheckout
61612				dtEnd = new Date(UTIL.coalesceDate(_dtCheckout, new Date())).toGloDateTime();
61613				var dtStart = new Date(dtEnd).addMinutes(-totalServiceLen);
61614			} else {
61615	        	var dtStart = _getNewServiceStartDate(arrUniqueStaff, staffId, isSameStart, isFA);
61616		        dtEnd = new Date(dtStart).addMinutes(totalServiceLen);
61617			}
61618			
61619			day = dtStart.toGloDate();
61620			tm = dtStart.toGloTime();
61621		}
61622    	
61623    	_addToUniqueStaff(arrUniqueStaff, staffId, dtStart, dtEnd, isSameStart);
61624    	return ' appt_dt="' + day + '" time_vc="' + tm + '" end_dt="' + dtEnd + '"';
61625    }
61626    function _getNewServiceStartDate(arrUniqueStaff, staffId, isSameStart, isFA) {
61627    	if (isSameStart && isFA) {
61628	    	return new Date(_lastServiceStart);
61629    	}
61630    	
61631    	var arrIndex = UTIL.isInObjectArray(arrUniqueStaff, 'staff_id', staffId);
61632    	
61633    	if (arrIndex !== -1) {
61634    		if (isSameStart && isFA) {
61635    			return new Date(arrUniqueStaff[arrIndex].start_dt);
61636    		} else {
61637    			return new Date(arrUniqueStaff[arrIndex].end_dt);
61638    		}
61639    	} else if (isSameStart && UTIL.isDate(_lastServiceStart)) {
61640    		return new Date(_lastServiceStart);
61641    	} else if (UTIL.isDate(_lastServiceEnd)) {
61642    		return new Date(_lastServiceEnd);
61643    	} else {
61644    		return _conTicket.getStartDate();
61645    	}
61646    }
61647    _conTicket.getStartDate = function() {
61648    	var jdt = $('#pos-ticket-datetime');					//_conTicket.startDate
61649    	var day = jdt.find('#Ticket_day').val();
61650    	var tm = UI.getTimeMaskValue(jdt.find('#Ticket_tm'));
61651    	
61652    	if (UTIL.isDate(day) && UTIL.isValidTime(tm)) {
61653    		return UTIL.joinDateAndTime(day, tm);
61654    	} else if (UTIL.isValidTime(tm)) {
61655    		return UTIL.joinDateAndTime(null, tm);
61656    	} else {
61657			return new Date(new Date().toGloDateTime());		//round to minute
61658		}
61659    }
61660    _conTicket.resetDate = function() {
61661    	var jdt = $('#pos-ticket-datetime');
61662    	jdt.find('#Ticket_tm').val('');
61663    	jdt.find('#Ticket_day').val('');
61664    	_time = null;
61665    }
61666    _conTicket.setStartDate = function(day, time) {
61667    	var hasChange = false, jdt = $('#pos-ticket-datetime');
61668    	var jtime = jdt.find('#Ticket_tm'), jday = jdt.find('#Ticket_day');
61669    	
61670    	if (!UTIL.isDate(day)) {
61671    		day = new Date();
61672    	} else {
61673    		day = new Date(day);
61674    	}
61675    	
61676    	if (!UTIL.isValidTime(time)) {
61677    		time = new Date().toGloTime();
61678    	}
61679    	
61680    	if (time != UI.getTimeMaskValue(jtime)) {
61681    		UI.setTimeMaskValue(jtime, time);
61682    		hasChange = true;
61683    		_time = time;
61684    	}
61685    	
61686    	if (day.toGloDate() != jday.val()) {
61687    		jday.val(day.toGloDate());
61688    		hasChange = true;
61689    	}
61690    	
61691    	_conTicket.changeDayTime();
61692    	return hasChange;
61693    }
61694    _conTicket.changeDay = function(element) {
61695    	_conTicket.changeDayTime();
61696    	_conTicket.ticketChanged();
61697    }
61698    _conTicket.changeTime = function(element) {
61699    	var jsvc = $('#pos-ticket').find('.pos-service-line-item');
61700    	_time = UI.getTimeMaskValue($('#pos-ticket-datetime #Ticket_tm'));
61701    	
61702    	_conTicket.changeDayTime();
61703    	_conTicket.ticketChanged();
61704    }
61705    _conTicket.changeDayTime = function() {
61706    	var jsvc = $('#pos-ticket').find('.pos-service-line-item');
61707    	
61708    	for (var i=0; i < jsvc.length; i++) {
61709    		jsvc.eq(i).removeAttr('appt_dt');
61710    		jsvc.eq(i).removeAttr('end_dt');
61711    		jsvc.eq(i).removeAttr('time_vc');
61712    	}
61713    }
61714    
61715    function _addToUniqueStaff(arrUniqueStaff, staffId, dtStart, dtEnd, isSameStart) {
61716    	var arrIndex = UTIL.isInObjectArray(arrUniqueStaff, 'staff_id', staffId);
61717    	
61718    	if (arrIndex === -1) {
61719    		arrUniqueStaff.push({ "staff_id": staffId, "start_dt": dtStart, "end_dt": dtEnd });
61720    	} else {
61721    		arrUniqueStaff[arrIndex].start_dt = dtStart;
61722    		arrUniqueStaff[arrIndex].end_dt = dtEnd;
61723    	}
61724    	
61725    	if (!UTIL.isDate(_lastServiceStart) || !isSameStart) {
61726	    	_lastServiceStart = new Date(dtStart);
61727	    	_lastServiceEnd = new Date(dtEnd);
61728    	}
61729    }
61730    function _serviceTotalLen(svcLen, processingNR, processingFL, finishOutNR, finishOutFL) {
61731    	var len = svcLen;
61732    	
61733    	if ((processingFL && processingNR > 0) || (finishOutFL && finishOutNR)) { svcLen += processingNR; }
61734		if (finishOutFL && finishOutNR > 0) { svcLen += finishOutNR; }
61735		
61736		return len;
61737    }
61738    function _clientLevelXml() {
61739    	if (UTIL.isEmpty(_conTicket.clientId)) { return ''; }
61740    	
61741    	var cname = UTIL.replaceQuotes(UTIL.cleanString(_conTicket.clientName));
61742    	var attributes = ' client_id="' + _conTicket.clientId + '" client_vc="' + cname + '" client_type_cd="' + _conTicket.clientType + '"';
61743    	
61744    	if (_ticketLoyalty > 0) { attributes += ' ticket_loyalty_nr="' + _ticketLoyalty + '"'; }
61745    	//if (_availableLoyalty > 0) { attributes += ' available_loyalty_nr="' + _availableLoyalty + '"'; }
61746    	if (_clientLoyalty > 0) { attributes += ' client_loyalty_nr="' + _clientLoyalty + '"'; }
61747    	
61748    	if (_cftid > 0) { attributes += ' card_on_file_tid="' + _cftid + '"'; }
61749    	if (_membershipId > 0) { attributes += ' membership_id="' + _membershipId + '"'; }
61750    	if (_giftBalance > 0) { attributes += ' gift_balance_mn="' + _giftBalance + '"'; }
61751    	if (_clientTagXml && _clientTagXml.length) { attributes += ' tag_count_sr="' + _clientTagXml.length + '"'; }
61752    	if (_birthDays > 0) { attributes += ' birth_sr="' + _birthDays + '"'; }
61753    	
61754    	return attributes;
61755    }
61756    function _bookingLevelXml(apptCount) {
61757    	var smid = $.trim($('#pos-ticket').attr('schedule_multi_id'));
61758    	var dtUpdate = $.trim(_conTicket.lastUpdateDate), dtCreate = _conTicket.createDate;
61759    	var bkg = $.trim(_conTicket.bookingNumber);
61760    	var mtid = _getMultiTicketId();
61761    	
61762    	var attributes = ' schedule_multi_id="' + smid + '" booking_nr="' + bkg + '" create_dt="' + dtCreate + '" last_update_dt="' + dtUpdate + '" multi_appt_count_sr="' + apptCount + '"';
61763    	
61764    	if (_imageCount > 0) { attributes += ' image_count_sr="' + _imageCount + '"'; }
61765    	if (!UTIL.isEmpty(_providerReferral)) { attributes += ' provider_referral_id="' + _providerReferral + '"'; }
61766    	
61767    	if (apptCount > 0) {
61768    		var apptStatus = _getApptStatus(smid, _apptStatus);
61769    		attributes += ' appt_status_cd="' + apptStatus + '"';
61770    		
61771    		if (UTIL.isDate(_dtCheckin)) {
61772    			attributes += ' checkin_dt="' + _dtCheckin + '"';
61773    		}
61774    		
61775	    	if (UTIL.isDate(_dtCheckout)) {
61776	    		attributes += ' checkout_dt="' + _dtCheckout + '"';
61777	    	//} else if (apptStatus == 22) {
61778	    	//	attributes += ' checkout_dt="' + new Date().toGloDateTime(); + '"';
61779	    	}
61780	    	
61781	    	if (UTIL.isDate(_dtSignin)) {
61782	    		attributes += ' signin_dt="' + new Date(_dtSignin).toGloDateTime() + '"';
61783	    	}
61784    	} else {
61785    		var day = $('#pos #Ticket_day').val();		//_dtDue
61786    		
61787    		if (UTIL.isDate(day)) {
61788    			attributes += ' due_dt="' + new Date(day).toGloDate() + '"';
61789    		}
61790    	}
61791    	
61792    	if (!UTIL.isEmpty(mtid)) {
61793			attributes += ' multi_ticket_id="' + mtid + '"';
61794		}
61795    	
61796    	if (!UTIL.isEmpty(_clientNote)) {
61797    		attributes += ' special_request_vcl="' + UTIL.htmlEncode2(UTIL.replaceQuotes(UTIL.cleanString(_clientNote))) + '"';
61798    	}
61799    	
61800        if (!UTIL.isEmpty(_staffNote)) {
61801        	attributes += ' staff_only_note_vc="' + UTIL.htmlEncode2(UTIL.replaceQuotes(UTIL.cleanString(_staffNote))) + '"';
61802        }
61803    	
61804    	return attributes;
61805    }
61806    
61807    function _getApptStatus(smid, apptStatus) {
61808    	var status = UTIL.coalesceInt(apptStatus, _apptStatus);
61809    	
61810    	if (UTIL.isEmpty(status)) {
61811    		if (!UTIL.isEmpty(smid)) {
61812    			return 11;
61813    		} else {
61814    			return 10;
61815    		}
61816    	}
61817    	
61818    	return status;
61819    }
61820    
61821    _conTicket.updateFromSave = function(editRow) {
61822		var smid = editRow.attr('schedule_multi_id'), bkg = editRow.attr('booking_nr'), dtUpdate = editRow.attr('last_update_dt');		//, dtEnd = editRow.attr('end_dt')
61823		$('#pos-ticket').attr('schedule_multi_id', smid);
61824		
61825		if (!UTIL.isEmpty(bkg)) {
61826			_conTicket.bookingNumber = bkg;
61827		}
61828		
61829		if (!UTIL.isDate(dtUpdate)) {
61830			_conTicket.lastUpdateDate = new Date().toGloDateTime();
61831		}
61832		
61833		_conTicket.createDate = UTIL.coalesceDate(_conTicket.createDate, jmain.attr('create_dt'));
61834    }
61835    
61836    _conTicket.displayStaffScreen = function() {
61837    	$('#pos-container').addClass('display-staff-screen');
61838    	
61839    	if (!GLO.Info.isMobile(true)) {
61840    		$('#pos-staff-list-client').focus();
61841    	}
61842    }
61843    _conTicket.displayTicket = function() {
61844    	$('#pos-container').removeClass('display-staff-screen');
61845	    SA.POS.resize();
61846    }
61847    
61848    _conTicket.openTicketEasy = function(smid, jsonPostOpen) {
61849    	var json = jQuery.extend(true, { "check_ticket_fl": true, "processing_message_vc": "Loading Ticket..." }, jsonPostOpen);
61850    	UserPortal.Edit.get(null, smid, true, false, true, json);
61851    }
61852    _conTicket.openExistingTicket = function(smid, jservices, payMeth, payAmt, payInfo, cardData, jsonPostOpen) {
61853    	var json = jQuery.extend(true, { "check_ticket_fl": true }, jsonPostOpen);
61854    	
61855		if (!UTIL.isEmpty(cardData)) {
61856			json.cards = cardData;
61857			json.open_after_save_fl = true;
61858		} else if (!UTIL.isEmpty(payMeth)) {
61859			json.payment_method_cd = payMeth;
61860			json.payment_mn = payAmt;
61861		}
61862		
61863		if (jservices.length > 0) {
61864			json.processing_message_vc = "Loading Appointment...";
61865			UserPortal.Edit.get(null, smid, true, false, true, json);
61866		} else {
61867			json.processing_message_vc = "Loading Ticket...";
61868			UserPortal.Price.get(smid, null, json);
61869		}
61870    }
61871    
61872    _conTicket.openTicketAndShowDiscount = function(element) {
61873    	var j = $('#pos-ticket-total-discount');
61874    	
61875    	if (!j.hasClass('processingColor')) {
61876    		j.addClass('processingColor');
61877    		SA.Ticket.openTicket(null, 0, null, null, null, { "highlight": ".price-discount-name" });
61878    		
61879    		setTimeout(function() {
61880    			j.removeClass('processingColor');
61881    		}, 1500);
61882    	}
61883    }
61884    _conTicket.openTicket = function(btnViewTicket, payMeth, payAmt, payInfo, cardData, jsonPostOpen, isQuickCheckin) {			//= when payMeth = 0 -> just means to open price-popup
61885		btnViewTicket = $(btnViewTicket);
61886		var isPrintTicket = jsonPostOpen && UTIL.parseBool(jsonPostOpen.isPrintTicket);
61887		
61888		if (btnViewTicket.length === 0) {
61889			if (isQuickCheckin) {
61890				var btnViewTicket = $('#pos-ticket #btnCheckinTicket');
61891			} else {
61892				var btnViewTicket = $('#pos-ticket #btnViewTicket');
61893			}
61894		}
61895		
61896		if (!btnViewTicket.hasClass('btnProcessing4')) {
61897			GLO.UI.Form.beginProcessing(btnViewTicket);
61898	    	UserPortal.Price.quit();
61899			jsonPostOpen = jQuery.extend(true, { "open_from_pos_fl": true }, jsonPostOpen);
61900	    	
61901	    	_conTicket.displayTicket();
61902	    	
61903			setTimeout(function() {		//= made async so spin view ticket button + for check above to avoid duplicate opening.
61904				SA.Ticket.openTicket2(payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket, isQuickCheckin);
61905				
61906				if (isPrintTicket) {
61907					if (jsonPostOpen && jsonPostOpen.isPrintReceipt) {
61908						UserPortal.Price.open(false);
61909						UserPortal.Price.Receipt.print(false);
61910					} else {								//print button should always print traveler -> if (GLO.Data.provider.traveler_cd > 0 && GLO.Data.provider.traveler_cd < 100)
61911						UserPortal.Edit.goCheckinPrint();
61912					}
61913				}
61914			}, 10);
61915		}
61916	}
61917	_conTicket.openTicket2 = function(payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket, isQuickCheckin) {
61918    	var jtix = $('#pos-ticket');
61919    	var jproducts = jtix.find('.pos-ticket-line-item:not(.pos-service-line-item)');		//.pos-product-line-item
61920    	var jservices = jtix.find('.pos-ticket-line-item.pos-service-line-item');
61921    	var smid = jtix.attr('schedule_multi_id');
61922    	var jd = _setTicketOpenXml(jproducts, jservices.length, payMeth, payAmt, payInfo, cardData);
61923    	
61924    	if (jservices.length > 0) {
61925    		_setApptStatus(payMeth, isQuickCheckin, jservices);
61926    		var isCheckout = _isCheckout(payMeth);
61927    		var serviceXml = _getServiceXml(jservices, isCheckout);
61928    		
61929    		if (!_isValidServiceXml(serviceXml)) {
61930    			GLO.UI.Form.resetProcessing(btnViewTicket);
61931    			return;
61932    		}
61933    		
61934    		_openAppt(serviceXml, smid, payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket);
61935    		var jedit = UserPortal.getEditAppt();
61936    		
61937    		if (UTIL.isEmpty(smid)) {
61938    			_openNewTicketRows(jedit, serviceXml);
61939    		} else if (jservices.length > 0) {
61940    			UserPortal.Booking.loadOriginalFromPos();
61941    		}
61942    		
61943    		var hasPayMethFee = (!UTIL.isEmpty(payMeth) && UserPortal.Price.Discount.hasPayMethRule());
61944    		UserPortal.Price.Discount.setMemberServiceXml(_conTicket.memberServiceXml);
61945    		
61946    		UserPortal.Edit.reloadAppt1(serviceXml, jd, false);
61947    		UserPortal.Edit.reloadAppt2(jedit, serviceXml, jd, true, jsonPostOpen, true, payMeth, isQuickCheckin);
61948    		UserPortal.Price.Discount.checkIfCanMoveDiscountToThisTicket();
61949    	} else if (jproducts.length === 0) {
61950    		_openSetEmptyTicket(jsonPostOpen, payAmt);
61951    	} else {
61952			UserPortal.Price.getOpen(jd, null, false, jsonPostOpen);
61953			UserPortal.Price.open(false, true);
61954		}
61955		
61956		GLO.UI.Form.resetProcessing(btnViewTicket);
61957		
61958		if (isQuickCheckin) {
61959			if (jservices.length > 0) {
61960				jedit.find('.btnSave > a').click();
61961	    		_conTicket.reset();
61962    		}
61963		} else {
61964			_conTicket.openFinishPricePopup(payMeth, payAmt, payInfo, cardData, jsonPostOpen);
61965		}
61966	}
61967	function _isCheckout(payMeth) {
61968		if (!UTIL.isEmpty(payMeth)) {
61969			var day = $('#pos-ticket-datetime #Ticket_day').val();
61970			var isToday = new Date(day).toGloDate() == new Date().toGloDate();
61971			
61972			if (!UTIL.isEmpty(day) && isToday) {
61973				return true;
61974			}
61975    	}
61976    	
61977    	return false;
61978	}
61979	function _setApptStatus(payMeth, isQuickCheckin, jservices) {
61980		var dtAppt = jservices.eq(0).attr('appt_dt');
61981		
61982		if (!UTIL.isDate(dtAppt) || UTIL.isToday(dtAppt)) {
61983			if (_apptStatus != 13 || _apptStatus != 14 || _apptStatus != 22) {
61984				if (!UTIL.isEmpty(payMeth)) {
61985					_apptStatus = 22;
61986				} else if (isQuickCheckin) {		//} else if (!UTIL.isDate(dtAppt)) {
61987					_apptStatus = 21;
61988				} else {
61989					var minuteDiff = (new Date(dtAppt) - new Date()) / (1000 * 60);
61990					
61991					if (minuteDiff > -31 && minuteDiff < 61) {			//= set to checked-in if appointment date is less than 30 minutes in future or less than 60 minutes in the past.
61992						_apptStatus = 21;
61993					}
61994				}
61995			}
61996		}
61997	}
61998	
61999	_conTicket.deleteTicket = function(btn) {
62000		UserPortal.Edit.deleteSignin();
62001	}
62002	_conTicket.printTicket = function(btn, isPrintReceipt) {
62003		var jsonPostOpen = { "isPrintTicket": true, "isPrintReceipt": isPrintReceipt };
62004		_conTicket.openTicket(btn, null, null, null, null, jsonPostOpen);
62005	}
62006	_conTicket.checkinTicket = function(btnViewTicket) {
62007    	if (GLO.Data.provider.resource_per_cd == 20 && SA.Data.resourceJson.length > 0) {
62008    		_openSetTicketResource()
62009    	} else {
62010    		SA.Ticket.openTicket(btnViewTicket, null, null, null, null, null, true);
62011    	}
62012    }
62013    _conTicket.checkinWithResource = function(resourceElement) {
62014    	var resourceId = UTIL.coalesceString($(resourceElement).attr('resource_id'));
62015    	var btnViewTicket = $('#pos-ticket-footer #btnCheckinTicket > a');
62016    	var jlines = $('#pos-ticket-order').find('.pos-service-line-item');
62017    	
62018    	for (var i=0; i < jlines.length; i++) {
62019    		jlines.eq(i).attr('service_resource_id', resourceId);
62020    	}
62021    	
62022    	for (var s=0; s < _serviceXml.length; s++) {
62023	    	_serviceXml.eq(s).attr('service_resource_id', resourceId);
62024    	}
62025    	
62026    	GLO.Popup.closeIfExist($('#pop-set-ticket-resource').closest('.glopop'));
62027    	SA.Ticket.openTicket(btnViewTicket, null, null, null, null, null, true);
62028    }
62029	function _openSetTicketResource() {
62030		var list = '', resourceId = null, rg = SA.Data.resourceJson;
62031        
62032        if (_serviceXml.length) {
62033        	resourceId = _serviceXml.eq(0).attr('service_resource_id');
62034        }
62035        	
62036    	for (var i=0; i < rg.length; i++) {
62037    		if (rg.length > 1 && rg[i].resources.length > 0) {
62038    			list += '<h3 class="ticket-resource-group" resource_group_id="' + rg[i].id + '">' + rg[i].name + '</h3>';
62039    		}
62040    		
62041    		list += _getResourceHtm(rg[i].resources, resourceId);
62042    	}
62043    	
62044    	var msg = '<p>Select service location or press <b style="color: rgb(0, 140, 255);">Close</b> to skip</p>';
62045    	var htm = '<div id="pop-set-ticket-resource">
62045' + msg + list + '</div>';
62046    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Set Ticket Resource');
62047    	GLO.Popup.Custom.singleButton(jpop, 'Close').click(SA.Ticket.checkinWithResource);
62048	}
62049	function _getResourceHtm(arrResource, resourceId) {
62050		var list = '';
62051		
62052		for (var i=0; i < arrResource.length; i++) {
62053    		var cssClass = 'ticket-resource-box';
62054    		
62055    		if (resourceId == arrResource[i].id) {
62056    			cssClass += ' is-selected';
62057    		}
62058    		
62059    		list += '<span resource_id="' + arrResource[i].id + '" default_staff_id="' + arrResource[i].default_staff_id + '" class="' + cssClass 
62060    				+ '" onclick="SA.Ticket.checkinWithResource(this)">' + arrResource[i].name + '</span>';
62061    	}
62062    	
62063    	return list;
62064    }
62065	
62066	function _isValidServiceXml(serviceXml) {
62067		for (var i=0; i < serviceXml.length; i++) {
62068			if (UTIL.isEmpty(serviceXml.eq(i).attr('staff_id'))) {
62069				var msg1 = '<p>Press Each Service in the Ticket to Add Staff to Each Service</p>';
62070				var msg2 = '<p style="text-align: center;">Or press <span class="btnAdd"><a onclick="SA.POS.openSelectStaff()">Select Staff</a></span> </p>';
62071				var htm = '<div id="pop-warnng-staff-required">' + msg1 + msg2 + '</div>';
62072				
62073				GLO.Popup.Warning.open(htm, 'Staff Required');
62074				
62075				/* SA.POS.filterBoxesHome();
62076				
62077				if (!GLO.POS.isDisplayServices()) {
62078					SA.POS.toggleList('services');
62079				} */
62080				
62081				return false;
62082			}
62083		}
62084		
62085		return true;
62086	}
62087	function _openNewTicketRows(jedit, serviceXml) {		//= if is new appt, only 1st row included on load edit-appt.
62088		UserPortal.Edit.isNewAppt = true;
62089		return;
62090		
62091    	var trsXml = $(serviceXml);
62092    	
62093    	for (var i=1; i < trsXml.length; i++) {
62094    		UserPortal.Edit.addService();
62095        	var trsvc = jedit.find('.editServiceRow:last'), trXml = trsXml.eq(i);
62096    		
62097    		UserPortal.Create.loadServiceRow(jedit, trsvc, trXml, i, i + 1);
62098    	}
62099	}
62100	function _getMultiTicketId() {
62101		if (_multiTicketXml && _multiTicketXml.attr) {
62102			return _multiTicketXml.attr('multi_ticket_id');
62103		} else {
62104			return '';
62105		}
62106	}
62107	function _setTicketOpenXml(jproducts, apptCount, smid, payMeth, payAmt, payInfo, cardData) {
62108		var inventoryXml = _getTicketInventoryXml(jproducts, true, apptCount);				//UserPortal.Price.inventoryXml
62109    	var discountXml = _getDiscountXml(true);											//UserPortal.Price.discountArray
62110    	var tagXml = _conTicket.getTagXml(false, true);
62111    	var pmt = UTIL.coalesceMoney(payAmt, _initialPayment);
62112		var multiTicketXml = '', mtid = _getMultiTicketId();
62113		
62114		var h2 = '<h2 product_tip_mn="' + $.trim(_productTip) + '"';
62115		h2 += _bookingLevelXml(apptCount);
62116		h2 += _attributeSummaryXml();
62117		h2 += _clientLevelXml();
62118		
62119		if (!UTIL.isEmpty(mtid)) {
62120			h2 += ' multi_ticket_id="' + mtid + '"';
62121			multiTicketXml = _multiTicketXml.outerHTML();
62122		}
62123		
62124		h2 += '/>';
62125		
62126		if (!UTIL.isEmpty(_paymentXml)) {
62127			var paymentXml = '<ol>' + _paymentXml + '</ol>';			//UserPortal.Price.paymentXml
62128		} else {
62129			var paymentXml = '';
62130		}
62131		
62132		return $('<div>' + h2 + inventoryXml + paymentXml + discountXml + multiTicketXml + tagXml + '</div>');
62133	}
62134	
62135	function _loadTagXml(jxmlAppt) {
62136		_clientTagXml = jxmlAppt.find('tags tag');
62137    	_clientTagRelationshipXml = jxmlAppt.find('rl li');
62138	}
62139	_conTicket.loadTagArray = function(tagArray) {
62140		var htm = '', tagXml = '<tags>';
62141		var cid = _conTicket.clientId, cname = _conTicket.clientName;
62142		
62143		for (var i=0; i < tagArray.length; i++) {
62144			tagXml += UTIL.jsonToXml(tagArray[i], 'tag');
62145			htm += GLO.ClientProfile.Tag.getTagHtm(tagArray[i], cid, cname, true);
62146		}
62147		
62148		_clientTagXml = $(tagXml + '</tags>').find('tag');
62149		_conTicket.loadClientNote('client-tag', htm, tagArray.length);
62150	}
62151	_conTicket.getTagXml = function(isReturnAsJQuery, isGetTagRelatedAppts) {
62152		if (_clientTagXml && _clientTagXml.length) {
62153			var tagXml = $('<tags>');
62154			
62155			for (var t=0; t < _clientTagXml.length; t++) {
62156				tagXml.append(_clientTagXml.eq(t));
62157			}
62158			
62159			if (isReturnAsJQuery) {
62160				return tagXml.find('tag');
62161			} else {
62162				var tagXml = tagXml.outerHTML();
62163				
62164				if (isGetTagRelatedAppts && _clientTagRelationshipXml && _clientTagRelationshipXml.length) {
62165		    		tagXml += '<rl>' + _clientTagRelationshipXml.outerHTML() + '</rl>';
62166		    	}
62167		    	
62168				return tagXml;
62169			}
62170		}
62171		
62172		return '';
62173	}
62174	_conTicket.editTagXml = function(tagObject) {
62175		if (_clientTagXml && _clientTagXml.length) { 
62176			var jtags = _conTicket.getTagXml(true);
62177			var tagXml = '', isUpdate = false;
62178			
62179			for (var t=0; t < tags.length; t++) {
62180				if (tagObject.tag_id == jtags.eq(i).attr('tag_id')) {
62181					jtags.eq(i).remove();
62182					isUpdate = true;
62183					tagXml += UTIL.jsonToXml(tagObject, 'tag');
62184				} else {
62185					tagXml += jtags.outerHTML();
62186				}
62187			}
62188			
62189			if (!isUpdate) {
62190				tagXml += UTIL.jsonToXml(tagObject, 'tag');
62191			}
62192			
62193			_clientTagXml = $(tagXml + '</tags>').find('tag');
62194		} else {
62195			_conTicket.loadTagArray([tagObject]);
62196		}
62197	}
62198	
62199	function _isPosQuickCheckout(jappt, payMeth) {
62200		if (!UTIL.isEmpty(payMeth)) {
62201			if (UTIL.isEmpty(UserPortal.Edit.scheduleMultiId)) {		//= is new appointment so is a quick checkout
62202				return true;
62203			}
62204			
62205			var apptDay = UserPortal.getApptDate(jappt.find('#Appt_dt, #Appointment_dt'));
62206			
62207			if (UTIL.isToday(apptDay) && UserPortal.Booking.service.length) {
62208				var start = new Date(UserPortal.Booking.service[UserPortal.Booking.service.length - 1].start_dt);
62209				var end = new Date(UserPortal.Booking.service[UserPortal.Booking.service.length - 1].end_dt);
62210				
62211				if (new Date().addMinutes(-5) > start) {				//= appointment has already started or starts within the next 5 minutes)
62212					if (end > new Date().addMinutes(-60)) {				//= appointment end time is in the future or less than 60 minutes in the past
62213						return true;
62214					}
62215				}
62216			}
62217		}
62218		
62219		return false;
62220	}
62221	_conTicket.finishOpenAppt = function(jappt, payMeth, isQuickCheckin) {
62222		//var jappt = UserPortal.getAppt();
62223		var isCreate = (jappt.attr('id') === 'ba-CreateAppointment');
62224		var isQuickCheckout = _isPosQuickCheckout(jappt, payMeth);
62225		
62226		UserPortal.Create.Checkout.loadEditAppt(jappt, isQuickCheckin, isQuickCheckout);
62227		UserPortal.Create.Checkout.calculateDateTime(jappt, isCreate, true);
62228		//UserPortal.Create.checkMoreButton();
62229		
62230		if (isQuickCheckout || !UTIL.isEmpty(payMeth)) {
62231			var jPricePop = UserPortal.getPricePop();						//if price-pop not open, this will try to open it.
62232		} else {
62233			var jPricePop = $('#appt-price-popup').closest('.glopop');
62234		}
62235		
62236		/* if (_clientTagXml && _clientTagXml.length) {
62237			var tagXml = $('<tags>');
62238			
62239			for (var t=0; t < _clientTagXml.length; t++) {
62240				tagXml.append(_clientTagXml.eq(t));
62241			}
62242			
62243			UserPortal.setTagJsonFromXml(tagXml, jPricePop, _conTicket.clientId);
62244			UserPortal.setTagIcon(jappt, _conTicket.clientId);
62245		} */
62246		
62247		return jPricePop;
62248	}
62249	
62250	function _openAppt(serviceXml, smid, payMeth, payAmt, payInfo, cardData, jsonPostOpen, btnViewTicket) {
62251		var note = '';
62252		
62253		if (true || !UTIL.isEmpty(smid)) {
62254			UserPortal.Price.resetOnOpen();
62255			UserPortal.Edit.open(serviceXml, false, jsonPostOpen);
62256			UserPortal.Edit.schedule_Multi_Del_ids = _deleteScheduleIds;
62257		} else {
62258			UserPortal.Create.open(serviceXml, false, note, true);
62259			
62260			if (serviceXml.length > 2) {
62261				//serviceXml = serviceXml.eq(0).remove();
62262				//serviceXml = serviceXml.eq(0).remove();
62263				
62264				UserPortal.Create.convertCreateToEdit(serviceXml, payMeth, payAmt, payInfo, cardData, jsonPostOpen);
62265				//UserPortal.Create.Checkout.setEditQuickCheckout();
62266			}
62267		}
62268		
62269		if (!btnViewTicket.hasClass('btnProcessing4')) {
62270			GLO.UI.Form.beginProcessing(btnViewTicket);
62271		}
62272	}
62273	function _openSetEmptyTicket(jsonPostOpen, payAmt) {
62274		if (jsonPostOpen && UTIL.parseBool(jsonPostOpen.open_keypad_if_no_ticket)) {
62275			_conTicket.openKeypad(payAmt * 100);
62276		} else if ($('#pos-container.services').length) {
62277			GLO.Popup.Warning.open('Please add service before opening', 'Empty Ticket');
62278		} else {
62279    		GLO.Popup.Warning.open(SA.Resource.PleaseAddProductsBeforePayment, 'Empty Ticket');
62280		}
62281	}
62282	function _openSetCashPayment(jPricePop) {
62283		var jchange = jPricePop.find('#appt-price-payment-table').find('.payment-good');
62284		
62285		if (jchange.length > 0) {
62286			jPricePop.find('.btnSave > a').click();
62287			
62288			if (jchange.hasClass('is-change')) {
62289				setTimeout(function() {
62290					$('#pos-ticket-change-due').addClass('display').html('Change Due<br/>' + jchange.text());
62291				}, 900);
62292			}
62293		}
62294	}
62295	function _openSetSwipe(cardData, jsonPostOpen) {
62296		var jPricePop = $('#appt-price-popup').closest('.glopop');
62297		var jccPop = $('#process-card-container').closest('.glopop');
62298		var jedit = UserPortal.getEditAppt();
62299		
62300		UserPortal.Price.Payment.MobileSwipe.processInvoice(cardData, jsonPostOpen, jccPop, jPricePop, jedit);
62301	}
62302	
62303	function _getTaxForProduct(jline, taxRate, productPrice) {
62304		var tax = UTIL.coalesceMoney(jline.attr('tax_mn'));
62305		
62306    	if (tax > 0) {
62307    		return tax;
62308    	} else if (taxRate > 0 && tax === 0) {
62309    		var jticket = $('#pos-ticket');
62310			var totalPrice = UTIL.coalesceMoney(jticket.find('#pos-ticket-total-box > b').text().replace('$', ''));
62311	    	var payment = UTIL.coalesceMoney(_initialPayment);
62312	    	
62313	    	if (totalPrice > payment) {
62314	    		var discount = UTIL.coalesceMoney(jline.attr('new_discount_mn'), jline.attr('discount_mn'));
62315	    		var addOnFee = UTIL.coalesceMoney(jline.attr('add_on_fee_mn'));
62316	    		var fullPrice = UTIL.coalesceMoney(productPrice - UTIL.coalesceMoney(discount) + UTIL.coalesceMoney(addOnFee));
62317	    		
62318	    		return UTIL.coalesceMoney(fullPrice * taxRate/100);
62319	    	}
62320    	}
62321    	
62322    	return '';
62323	}
62324	function _openAddLineItem(jline, foundCount) {
62325		var taxRate = jline.attr('custom_tax_rate_pct');
62326		if (UTIL.isEmpty(taxRate)) { taxRate = GLO.inventoryTax; }
62327		
62328		var amt = jline.find('.line-item-amount').val() - UTIL.coalesceInt(foundCount, 0);
62329		var price = jline.find('.line-item-price').val();
62330		var tax = _getTaxForProduct(jline, taxRate, price);
62331		
62332		var ixml = '', inventoryId = parseInt(jline.attr('inventory_id'));
62333		var arrSIID = _getSIIDs(jline, amt);
62334		
62335		if (SA.POS.inventory_json.manual_entry && SA.POS.inventory_json.manual_entry.id === inventoryId) {
62336			var product = SA.POS.inventory_json.manual_entry;
62337		} else {
62338			var product = SA.POS.getProductObject(inventoryId);
62339		}
62340		
62341		if (product) {
62342			var name = product.label;
62343			var vendorId = UTIL.cleanString(product.vendor_id);
62344			var plineId = UTIL.cleanString(product.product_line_id);
62345			var cost = UTIL.cleanString(product.cost_mn);
62346			//eprice = product.employee_price_mn;
62347		} else {
62348			var name = jline.find('.line-item-name').text();
62349			var vendorId = '', plineId = '', cost = 0;
62350		}
62351		
62352		var more = _getProductDiscountAndFee(jline);
62353		var gc = _openAddLineItemGiftCard(jline);
62354		
62355		if (!UTIL.isEmpty(vendorId)) {
62356			var vendor = SA.POS.getVendorObject(vendorId);
62357			
62358			if (vendor) {
62359				vmid = vendor.vendor_merchant_id;
62360				
62361				if (!UTIL.isEmpty(vmid)) {
62362					more += ' vendor_merchant_id="' + vmid + '"';
62363				}
62364			}
62365		}
62366		
62367		for (var s=0; s < arrSIID.length; s++) {
62368			ixml += '<li amount_nr="1" price_mn="' + price + '" tax_mn="' + tax + '" tax_rate_pct="' + taxRate			// + '" employee_price_mn="' + eprice
62369						+ '" schedule_inventory_id="' + arrSIID[s] + '" inventory_id="' + inventoryId + '" inventory_vc="' + name
62370						+ '" cost_mn="' + cost + '" vendor_id="' + vendorId + '" product_line_id="' + plineId + '"' + gc + more + '/>';
62371	    }
62372	    
62373	    return ixml;
62374	}
62375	
62376	function _getProductDiscountAndFee(jline) {
62377		var discount = jline.attr('discount_mn');
62378		var fee = jline.attr('add_on_fee_mn');
62379		var attributes = '';
62380		
62381		if (discount > 0) {
62382			attributes += ' discount_mn="' + discount + '" new_discount_mn="' + discount + '"';
62383		}
62384		
62385		if (fee > 0) {
62386			attributes += ' add_on_fee_mn="' + fee + '"';
62387		}
62388		
62389		return attributes;
62390	}
62391	
62392	function _openAddLineItemGiftCard(jline) {
62393		var output = '';
62394		var isgc = jline.attr('is_gift_card_fl');
62395		var gcid = jline.attr('gift_card_id');
62396		var gcnr = jline.attr('gift_number_vc');
62397		//var gcmn = jline.attr('gift_balance_mn');
62398		
62399		if (UTIL.parseBool(isgc) || !UTIL.isEmpty(gcid)) {
62400			var toCID = $.trim(jline.attr('to_client_id')), original = $.trim(jline.attr('gift_original_mn')), balance = $.trim(jline.attr('gift_balance_mn'));
62401			output += ' is_gift_card_fl="1"';
62402			
62403			if (!UTIL.isEmpty(gcid)) { output += ' gift_card_id="' + gcid + '"'; }
62404			if (!UTIL.isEmpty(gcnr)) { output += ' gift_number_vc="' + gcnr + '"'; }
62405			
62406			output += ' to_client_id="' + toCID + '" gift_original_mn="' + original + '" gift_balance_mn="' + balance + '"';
62407		} else {
62408			var inventoryId = jline.attr('inventory_id');
62409			var product = SA.POS.getProductObject(inventoryId);
62410			
62411			if (product && product.is_gift_card_fl) {
62412				output += ' is_gift_card_fl="1"';
62413			}
62414		}
62415		
62416		return output;
62417	}
62418	
62419	function _getSIIDs(jline, amt) {
62420		var arrSIID = UTIL.cleanString(jline.attr('schedule_inventory_ids')).split(',');
62421		var cnt = arrSIID.length;
62422		
62423		for (; cnt < amt; cnt++) {
62424			arrSIID.push('');
62425		}
62426		
62427		return arrSIID;
62428	}
62429	
62430	_conTicket.openFinishPricePopup = function(payMeth, payAmt, payInfo, cardData, jsonPostOpen) {
62431		var jPricePop = $('#appt-price-popup').closest('.glopop');
62432		var jPriceSaveBtn = jPricePop.find('.btnSave').find('a').text('Complete');
62433		var jappt = UserPortal.getAppt();
62434		
62435		var jticket = $('#pos-ticket').addClass('open-in-popup');
62436		var smid = jticket.attr('schedule_multi_id');    		
62437		var isSwipe = (!UTIL.isEmpty(smid) && !UTIL.isEmpty(cardData));
62438		
62439		UserPortal.Price.openFromPOS(_deleteInventoryXml);
62440		
62441		if (jticket.find('#btnSaveTicket > a.unsaved-change').length) {
62442			jappt.find('.btnSave > a').css({ "border": "3px solid red" });
62443			jPriceSaveBtn.css({ "border": "3px solid red" });
62444		}
62445		
62446		//if (UTIL.isEmptyObject(payInfo)) { jPricePop.find('#Is_Walkin_fl').prop('checked', true).change(); }
62447		
62448		if (!UTIL.isEmpty(payMeth)) {
62449			if (!UTIL.isEmpty(payAmt)) {
62450				jPricePop.find('#Payment_mn:last').val(UTIL.displayMoney(payAmt, true, true, true));
62451			}
62452			
62453			if (true || GLO.Info.isMobile(true) || UI.Keypad.isButtonBased()) {
62454				if (isSwipe) {
62455					UI.setMobileSelect($('#Mobile_Payment_Method_cd'), payMeth);
62456				} else if (payMeth > 0) {
62457					jPricePop.find('#Mobile_Payment_Method_cd').find('li[value="' + payMeth + '"]').click();
62458				}
62459			} else if (!isSwipe) {																			//swipe processed by _conPmt.MobileSwipe.processInvoice
62460				jPricePop.find('#Payment_Method_cd:last').val(payMeth).change();
62461				//if (payMeth == 10 && !isSwipe) { setTimeout(UserPortal.Price.Payment.openCreditCard, 600); }
62462			}
62463		}
62464		
62465		if (!UTIL.isEmpty(cardData)) {
62466			_openSetSwipe(cardData, jsonPostOpen);
62467		} else if ((payMeth == 1 || payMeth == 99) && UTIL.coalesceInt(payAmt, 0) === 0) {
62468			jPricePop.find('#appt-price-payment-table').find('.Payment_mn:last').focus();
62469		} else if (payMeth == 1 && UTIL.coalesceInt(payAmt, 0) > 0) {
62470			_openSetCashPayment(jPricePop);
62471		}
62472		
62473		/* if (!UTIL.isEmpty(smid)) {		//merge ticket from POS + DB
62474    		//jsonPostOpen = jQuery.extend(true, { "open_from_pos_fl": true }, jsonPostOpen);
62475    		//UserPortal.Edit.checkIfUpdated(smid, null, true, null, jsonPostOpen);
62476    		//_conTicket.openExistingTicket(smid, jservices, payMeth, payAmt, payInfo, cardData, jsonPostOpen);
62477    	} */
62478    	
62479    	if (jsonPostOpen && jsonPostOpen.save_and_reset_fl) {
62480    		if (jPriceSaveBtn.length) {
62481    			jPriceSaveBtn.click();
62482    		} else {
62483    			jappt.find('.btnSave > a').click();
62484    		}
62485    		
62486    		_conTicket.reset(null, true);
62487    	} else if (jsonPostOpen && jsonPostOpen.lookup_gift_card_fl) {
62488    		var giftCardId = jsonPostOpen.gift_card_id;
62489    		var jli = $('<li number_vc="' + jsonPostOpen.gift_number_vc + '" gift_card_id="' + jsonPostOpen.gift_card_id + '">' + jsonPostOpen.processing_mssage_vc + '</li>');
62490    		
62491    		UserPortal.Lookup.addGiftCardPayment(jPricePop, jli, giftCardId);
62492    	}
62493	}
62494    
62495    function _openTicketMatchesPOS(smid) {
62496    	var posSMID = UTIL.cleanString($('#pos-ticket').attr('schedule_multi_id'));
62497    	smid = UTIL.cleanString(smid);
62498    	
62499    	if (posSMID == smid || (posSMID.indexOf('tmp') !== -1 && UTIL.isEmpty(smid))) {
62500    		return true;
62501    	} else {
62502    		return false;
62503    	}
62504    }
62505    
62506    _conTicket.removeProduct = function(smid, inventoryId, siid) {
62507    	var jticket = $('#pos-ticket');
62508    	
62509    	if (_openTicketMatchesPOS(smid)) {
62510    		_removeProduct(jticket, inventoryId, siid);
62511    	}
62512    }
62513    
62514    function _removeProduct(jticket, inventoryId, siid) {
62515    	var jline = jticket.find('.pos-product-line-item[inventory_id="' + inventoryId + '"]');
62516    	var jPricePop = $('#appt-price-popup').closest('.glopop');
62517    	var amt = _getAmountOnOpenTicket(jPricePop, inventoryId);									//var amt = jline.find('.line-item-amount').val();
62518    	
62519    	if (UTIL.coalesceInt(amt, 0) === 0) {
62520			jline.find('.ui-icon-circle-close').click();
62521		} else {
62522			_changeProductAmount(jline, siid, amt, true);
62523			_conTicket.changeProductPriceFromOpenTicket(inventoryId);
62524		}
62525		
62526		_finishAddProductOrService();
62527		_conTicket.enableOrDisableTicketScroll();
62528    }
62529    
62530    function _changeProductAmount(jline, siid, amtNew, isRemove) {
62531    	jline.find('.line-item-amount').val(amtNew);
62532    	
62533		if (!UTIL.isEmpty(siid)) {
62534			var arrSIID = UTIL.cleanString(jline.attr('schedule_inventory_ids')).split(',');
62535			
62536			for (var i=0; i < arrSIID.length; i++) {
62537				if (arrSIID[i] == siid) {
62538					if (isRemove) {
62539						_deleteInventoryXml += '<li del_schedule_inventory_id="' + siid + '"/>';
62540						
62541						arrSIID.splice(i, 1);
62542						jline.attr('schedule_inventory_ids', arrSIID.join(','));
62543					}
62544					
62545					_conTicket.recalculate();
62546					return;
62547				}
62548			}
62549			
62550			if (!isRemove) {
62551				if (!UTIL.isEmpty(arrSIID[0])) { siid = arrSIID.join(',') + ',' + siid; }
62552				
62553				jline.attr('schedule_inventory_ids', siid);
62554			}
62555		}
62556		
62557		_conTicket.recalculate();
62558    }
62559    
62560    _conTicket.changeProductPriceFromOpenTicket = function(inventoryId) {
62561    	var jPricePop = $('#appt-price-popup').closest('.glopop');
62562    	var smid = UTIL.cleanString(jPricePop.find('#price-header').attr('schedule_multi_id'));
62563    	var price = _getPriceOnOpenTicket(jPricePop, inventoryId);
62564        
62565        if (!_openTicketMatchesPOS(smid)) { return; }
62566    	
62567    	$('#pos-ticket').find('.pos-product-line-item[inventory_id="' + inventoryId + '"]').find('.line-item-price').val(price);
62568    	_conTicket.recalculate();
62569    }
62570    
62571    _conTicket.inputOnFocus = function() {
62572    	var me = this;
62573    	
62574    	/* 		?? throws error on Android ??
62575    	setTimeout(function() {
62576    		me.selectionStart = me.selectionEnd = me.value.length;
62577    	}, 100);
62578    	*/
62579    }
62580    
62581    _conTicket.changeProductAmountFromOpenTicket = function(inventoryId) {
62582    	var jPricePop = $('#appt-price-popup').closest('.glopop');
62583    	var smid = UTIL.cleanString(jPricePop.find('#price-header').attr('schedule_multi_id'));
62584    	var amt = _getAmountOnOpenTicket(jPricePop, inventoryId);
62585        
62586        _conTicket.changeProductAmount(smid, inventoryId, null, amt);
62587    }
62588    
62589    function _getPriceOnOpenTicket(jPricePop, inventoryId) {
62590    	var tr = jPricePop.find('.appt-product-row');
62591    	var amt = 0, price = 0, rowPrice, rowAmt;
62592    	
62593    	for (var i=0; i < tr.length; i++) {
62594    		if (tr.eq(i).find('.booking-product').attr('inventory_id') == inventoryId) {
62595    			rowAmt = UTIL.coalesceInt(tr.eq(i).find('.booking-product-count').val(), 0);
62596    			rowPrice = UTIL.coalesceMoney(tr.eq(i).find('.booking-product-price').val(), 0);
62597    			
62598    			price += rowPrice * rowAmt;
62599    			amt += rowAmt;
62600    		}
62601    	}
62602    	
62603    	return UTIL.coalesceMoney(UTIL.coalesceMoney(price)/UTIL.coalesceMoney(amt));
62604    }
62605    
62606    function _getAmountOnOpenTicket(jPricePop, inventoryId) {
62607    	var tr = jPricePop.find('.appt-product-row');
62608    	var amt = 0;
62609    	
62610    	for (var i=0; i < tr.length; i++) {
62611    		if (tr.eq(i).find('.booking-product').attr('inventory_id') == inventoryId) {
62612    			amt += UTIL.coalesceInt(tr.eq(i).find('.booking-product-count').val(), 0);
62613    		}
62614    	}
62615    	
62616    	return amt;
62617    }
62618    
62619    _conTicket.changeProductAmount = function(smid, inventoryId, siid, amt) {
62620    	if (!_openTicketMatchesPOS(smid)) { return; }
62621    	
62622		var jticket = $('#pos-ticket');
62623		var jline = jticket.find('.pos-product-line-item[inventory_id="' + inventoryId + '"]');
62624		
62625		if (jline.length === 0) {
62626			_conTicket.addProductLine(inventoryId, amt);
62627			_conTicket.recalculate();
62628			
62629			if (!UTIL.isEmpty(siid)) {
62630				var jline = jticket.find('.pos-product-line-item[inventory_id="' + inventoryId + '"]');
62631			} else {
62632				return;
62633			}
62634		}
62635		
62636		_changeProductAmount(jline, siid, amt);
62637    }
62638    
62639    _conTicket.setClientAttributes = function(cid, cname, ctype, cftid, cpts, tpts, apts, membershipId, tagCount, giftBalance, birthDays) {
62640    	//tagCount
62641    	_cftid = cftid;
62642    	_membershipId = membershipId;
62643    	_giftBalance = giftBalance;
62644    	_birthDays = birthDays;
62645    	
62646    	_conTicket.clientId = UTIL.coalesceInt(_conTicket.clientId, cid);
62647    	_conTicket.clientType = UTIL.coalesceInt(_conTicket.clientType, ctype);
62648    	_conTicket.clientName = UTIL.coalesceString(_conTicket.clientName, cname);
62649    	
62650    	_clientLoyalty = cpts;
62651    	_ticketLoyalty = tpts;
62652    	_availableLoyalty = apts;
62653    }
62654    _conTicket.updateTicket = function(jdata) {
62655		var jticket = $('#pos-ticket');
62656		var smid = jdata.attr('schedule_multi_id');
62657		
62658		jticket.attr('schedule_multi_id', smid);
62659		//_initialPayment = 0, _originalTotal = 0, _productTip = 0;
62660    	_bookingNumber = jticket.attr('booking_nr');
62661    	_lastUpdateDate = jdata.attr('last_update_dt');
62662    	
62663    	$('#pos-ticket #btnViewTicket > a').removeClass('unsaved-change');
62664	}
62665    
62666    function _resetClientAttributes(isFullReset) {
62667    	$('#pos-ticket').removeClass('has-client');
62668		$('#pos-container').removeClass('client-note1').removeClass('client-note2').removeClass('client-note3').removeClass('client-note4');
62669		
62670		$('#pos-ticket-client-attributes').html('').addClass('hide');		//.find('.client-note-row').remove()
62671		$('#pos-ticket-client-header').find('.client-has-card-on-file, .client-membership-icon, .new-client-text-icon').remove();
62672		
62673		if (isFullReset) {
62674			$('#pos-add-client-button').removeAttr('title').find('input').val('');
62675		}
62676    }
62677    _conTicket.reset = function(smid, isGoHome) {
62678    	if (!UTIL.parseBool(GLO.isPOS)) { return; }
62679    	if (!UTIL.isEmpty(smid) && !_openTicketMatchesPOS(smid)) { return; }
62680    	
62681    	clearTimeout(_addLineToHeaderTimeout);
62682    	
62683		var jticket = $('#pos-ticket').removeClass('scroll-active').removeClass('open-in-popup').removeClass('has-client');
62684    	var jlns = jticket.find('.pos-ticket-line-item, .pos-staff-line-item');			//, .pos-ticket-discount-line, .pos-ticket-payment-line
62685    	
62686    	for (var i=0; i < jlns.length; i++) {
62687			jlns.eq(i).remove();
62688		}
62689    	
62690		jticket.removeAttr('schedule_multi_id');		//.removeAttr('last_update_dt').removeAttr('client_id').removeAttr('client_vc');
62691		jticket.find('#pos-ticket-total-discount > b').text('');
62692		jticket.find('#btnViewTicket').find('>a').text('Open Ticket');
62693		jticket.find('#btnSaveTicket').find('>a').removeClass('unsaved-change');
62694		
62695		jticket.find('#pos-header-staff-ticket-label').text('Ticket').removeClass('ticket-booking-number').removeClass('ticket-resource-name');
62696		jticket.find('#btnCheckinTicket, #btnPrintTicket').addClass('hide');
62697		jticket.find('#pos-ticket-paid, #pos-ticket-due').addClass('hide');
62698		jticket.find('#pos-ticket-header-paid-amount').text('0');
62699		
62700		$('#pos-product-header-enter #pos-enter-product-or-amount').val('');
62701		$('#pos-product-header-enter .btnAction2').addClass('hide');
62702		$('#pos #header-ticket-total').text('');
62703		$('#pos-header-staff').removeClass('selected').find('#btnSelectedStaff > a').removeAttr('staff_id').removeAttr('is_first_available_fl').text('');
62704		$('#pos-staff-list-client').val('');
62705		
62706		var jdt = $('#pos-ticket-datetime');
62707		jdt.find('#Ticket_day').val('');
62708		jdt.find('#Ticket_tm').val('');
62709		jdt.find('.appt-icon').remove();
62710		
62711		_time = null;
62712		_resetClientAttributes(true);
62713		_resetVariables();
62714		_setBookingNumber();
62715		
62716    	_conTicket.ticketSaved();
62717		_conTicket.recalculate();
62718		SA.POS.filterBoxesHome();
62719		
62720		if (isGoHome) {
62721			_conTicket.displayStaffScreen();
62722		}
62723    }
62724    function _resetVariables() {
62725    	clearTimeout(_timeoutApplyDiscounts);
62726    	
62727    	_addLineToHeaderTimeout = null;
62728    	_isLoading = false;
62729    	
62730    	_serviceXml = _productXml = _paymentXml = _discountXml = _multiTicketXml = '';
62731    	_clientTagXml = _clientTagRelationshipXml = null;
62732    	_deleteInventoryXml = _deleteScheduleIds = '';
62733	    _conTicket.discountDelArray = [];
62734	    
62735	    _conTicket.promoCode = _conTicket.bookingNumber = _conTicket.createDate = _conTicket.lastUpdateDate = _conTicket.waitId = null;
62736		_conTicket.clientId = _conTicket.clientName = _conTicket.clientType = null;
62737	    _conTicket.isCustomDiscount = false;
62738	    _conTicket.memberServiceXml = null;
62739	    
62740		_initialPayment = _originalTotal = _productTip = _giftBalance = _imageCount = 0;
62741	    _clientLoyalty = _ticketLoyalty = _availableLoyalty = _discountCount = _referralDiscount = 0;
62742	    _clientNote = _staffNote = '';
62743	    _lastServiceStart = _lastServiceEnd = null;
62744	    
62745	    _cftid = _membershipId = _birthDays = null;
62746	    _apptStatus = _dtCheckin = _dtCheckout = _dtSignin = _dtDue = _scheduleRecurId = _providerReferral = null;
62747	    
62748	    SA.Ticket.resetDate();
62749    }
62750    
62751    _conTicket.getOriginalServiceXml = function() {
62752    	return _serviceXml;
62753    }
62754    
62755    function check_for_phone() {
62756    	var message = document.getElementById("pos-staff-list-client").value;
62757      	var Regex = /\b[\+]?[(]?[0-9]{2,6}[)]?[-\s\.]?[-\s\/\.0-9]{3,15}\b/m; 
62758       	
62759       	if (Regex.test(message)) {
62760       		var matches = Regex.exec(message);
62761       		var phone = matches[0];						//       		matches.index
62762       		var name = message.replace(phone, '');
62763       		
62764       		
62765       	}
62766       	
62767      	//alert(Regex.test(message));       // This will alert 'true' if the textarea contains a phonenumber 
62768	}
62769    
62770    _conTicket.openSelectStaff = function(delay, serviceId) {
62771    	delay = UTIL.coalesceInt(delay, 500);
62772    	
62773    	setTimeout(function() {
62774    		SA.POS.openSelectStaff(null, serviceId);
62775    	}, delay);
62776    }
62777    _conTicket.newTicket = function(staffId, staffName, isFA) {
62778    	var clientInput = document.getElementById("pos-staff-list-client").value;
62779    	var clientResult = UTIL.getNameAndPhone(clientInput);
62780    	var isDefaultToProduct = false;
62781    	
62782    	SA.Ticket.reset();
62783    	GLO.Popup.closeIfExist($('#pop-staff-preview').closest('.glopop'));
62784    	
62785    	if (!UTIL.isEmpty(staffId)) {
62786    		SA.POS.setStaff(staffId, staffName, isFA);
62787    	} else {
62788    		staffId = UserPortal.getFirstAvailableStaffId();
62789    		
62790    		if (!UTIL.isEmpty(staffId)) {
62791    			staffName = UserPortal.getStaffName(staffId);
62792    			SA.POS.setStaff(staffId, staffName, true);
62793    		} else if (SA.POS.inventory_json.products.length < 30) {
62794    			_conTicket.openSelectStaff();
62795    		} else {
62796    			isDefaultToProduct = true;
62797    		}
62798    	}
62799    	
62800    	SA.Ticket.displayTicket();
62801    	
62802    	if (isDefaultToProduct) {
62803    		SA.POS.toggleList('products');
62804    	} else if (innerWidth > 970) {
62805    		$('#pos-service-group-list:visible').find('.pos-type-list').eq(0).click();
62806    	}
62807    	
62808    	_newTicketDateTime();
62809    	_newTicketAddClient(clientResult);
62810    }
62811    function _newTicketAddClient(clientResult) {
62812    	if (clientResult && (clientResult.hasNameAndPhone || (clientResult.fname.length > 1 && clientResult.lname.length > 1))) {
62813    		_conTicket.addClientNewOpen2(clientResult);
62814    	}
62815    }
62816    function _newTicketDateTime() {
62817    	var jday = $('#Ticket_day');
62818		var jtime = $('#Ticket_tm');
62819		
62820		var day = new Date().toGloDate();
62821		var tm  = new Date().toGloTime();
62822		
62823		jday.val(day);
62824		UI.setTimeMaskValue(jtime, tm);
62825		_time = tm;
62826    }
62827    _conTicket.newTicket_Original = function() {
62828    	if (_conTicket.hasUnsavedChange()) {
62829	    	var msg = '<div style="margin-left: 12px; margin-top: 12px; margin-bottom: 24px; letter-spacing: 1px; font-size: 116%;">' + SA.Resource.SaveTicketForLater + '?</div>';
62830	    	var jpop = GLO.Popup.Confirm.open(msg, 'Un-Saved Changes', SA.Ticket.saveForLater, SA.Ticket.reset).getPopup();
62831	    	var jbtns = jpop.find('.pop-buttons').css({ "margin-bottom": "12px" });
62832	    	
62833	    	var noCSS = { "padding": "8px 24px", "border": "none", "border-radius": "24px", "font-family": "arial", "font-size": "20px", "background-color": "black", "color": "white" };
62834	    	
62835	    	jbtns.find('.btnNo').css({ "margin": 0 }).find('> a').css(noCSS);
62836	    	jbtns.find('.btnYes').addClass('btnSave').find('> a').css({ "padding": "8px 24px", "font-family": "arial", "font-size": "20px" });
62837    	} else {
62838    		_conTicket.clearTicket();
62839    	}
62840	}
62841    _conTicket.clearTicket = function() {
62842    	GLO.UI.Form.resetProcessing();
62843    	
62844    	if ($('#pos-container').hasClass('edit-pos')) {
62845    		SA.POS.Edit.changeMode();
62846    	}
62847    	
62848    	_conTicket.hideChangeDue();
62849    	_conTicket.reset(null, true);
62850    	//_conTicket.displayStaffScreen();
62851    }
62852    _conTicket.saveForLater = function() {
62853    	var jsonPostOpen = { "save_and_reset_fl": true };
62854    	var btnSaveTicket = $('#pos-ticket-footer #btnSaveTicket');
62855    	
62856    	_conTicket.openTicket(btnSaveTicket, null, null, null, null, jsonPostOpen);
62857	}
62858    
62859    _conTicket.addClientToPosTicket = function(smid, cid, cnm, ctype, uiItem) {
62860    	if (!GLO.isPOS) { return; }
62861    	if (UTIL.isEmpty(cid)) { return; }
62862    	
62863    	var jticket = $('#pos-ticket');
62864		
62865    	if (smid != jticket.attr('schedule_multi_id')) {
62866    		return;
62867    	}
62868    	
62869    	var firstCharacter = UTIL.cleanString(cid).substring(0,1);
62870    	
62871    	if (firstCharacter === 'S') {
62872    		return;
62873    	} else if (firstCharacter === 'C') {
62874    		cid = UTIL.cleanString(cid.substring(1));
62875    	}
62876    	
62877    	if (uiItem && uiItem.id) {
62878    		SA.Ticket.addClientCompleteFromAutoComplete(cid, cnm, ctype, uiItem);
62879    	} else {
62880    		ctype = $.trim(ctype);
62881    		SA.Ticket.addClientComplete(cid, cnm, ctype);
62882    	}
62883    	
62884		//_conTicket.clientId = cid;
62885		//_conTicket.clientName = cnm;				//UTIL.htmlEncode2(cnm);
62886		//_conTicket.clientType = $.trim(ctype);
62887		
62888		//jticket.find('input').val(cnm);
62889    }
62890    
62891    _conTicket.ToggleInvoiceFields = function(clientId, clientName, clientType, uiItem) {
62892    	var hasNote = uiItem.has_note_fl, cftid = uiItem.cftid, mid = uiItem.membership_id, giftBalance = uiItem.gift_balance_mn;
62893		var pts = uiItem.loyalty_points_nr, tagCount = uiItem.tag_count_sr, birth = uiItem.birth_sr, referId = uiItem.provider_referral_id;
62894		var ctype = UTIL.coalesceInt(clientType, uiItem.client_type_cd);
62895		
62896		SA.Ticket.addClientComplete(clientId, clientName, ctype, hasNote, cftid, mid, giftBalance, pts, tagCount, birth, referId);
62897    }
62898    
62899	_conTicket.ToggleInvoiceFields = function() {
62900		var isInvoicePaymentRequired = $('#toggleInvoicePayment').is(':checked');
62901
62902		if (isInvoicePaymentRequired) {
62903			if ($('#invoice-payment-fields').hasClass('hide')) {
62904				$('#invoice-payment-fields').removeClass('hide');
62905				
62906				if (!UI.Keypad.isButtonBased()) {
62907					$('#add-invoice-due-date').css({'text-align':'center','margin-bottom':'10px','float':'','width':'100%'});
62908					$('#add-invoice-client-note').css({'text-align':'center','float':'','width':'100%'});
62909				}
62910				else {
62911					$('#add-invoice-due-date').css({'text-align':'center','width':'50%','float':'left','margin-bottom':''});
62912					$('#add-invoice-client-note').css({'text-align':'center','width':'50%','float':'right'});					
62913				}
62914			}
62915		} else {
62916			$('#invoice-payment-fields').addClass('hide');
62917		}
62918	}
62919
62920	_conTicket.VoidInvoice = function(smid, btn) {
62921		var uri = GLO.Link.Object.AppointmentAjax + 'voidinvoice';
62922		var invoiceData = { "smid": UTIL.coalesceInt(smid, UserPortal.Edit.scheduleMultiId) };
62923		var jsonInvoiceData = JSON.stringify(invoiceData);
62924		
62925		GLO.UI.Form.beginProcessing($(btn));
62926		
62927        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonInvoiceData, contentType: "application/json" })
62928            .success(function(data, textStatus, jqXHR) {
62929				window.onbeforeunload = null;
62930				
62931            	new GLO.Popup.Success('Invoice Voided.', 1000);
62932				
62933				GLO.Popup.closeIfExist($('#enter-email-invoice-payment-container').closest('.glopop'));
62934				GLO.Popup.closeIfExist($('#enter-text-invoice-payment-container').closest('.glopop'));
62935            })
62936            .error(function(jqXHR, textStatus, errorThrown) {
62937                GLO.UI.Form.resetProcessing();
62938                new GLO.Popup.Error('Unable to Void Invoice');
62939            });
62940	}	
62941
62942	 _conTicket.SendInvoiceToClient = function(pid,smid,amount,message,cid,duedate) {
62943		
62944		// var uri = GLO.Link.WebsiteDomain + 'api/PAX/ConnectPAXDevice';
62945		var uri = GLO.Link.Object.AppointmentAjax + 'sendinvoice';
62946
62947		// var jpop = $('#pax-wifi-setup').closest('.glopop');
62948		// var ipAddress = jpop.find('#pax-wifi-ip').val();
62949		// //remove leading zeros from ip
62950		// var cleanIPAddress = ipAddress.replace(/(^|\.)0+(?=[^.])/g, '.');
62951		// var jPricePop = $('#appt-price-popup').closest('.glopop');
62952		var invoiceTicket = {
62953			"ProviderId":GLO.Data.provider.id,
62954			"ScheduleMultiId":UserPortal.Edit.scheduleMultiId,
62955			"InvoiceAmount":$('#Invoice_Amount_vc').val(),
62956			"InvoiceNote": UTIL.htmlEncode4($('#Invoice_Client_note_vc').val()),
62957			"ClientId":UserPortal.Price.getClientId(),
62958			"InvoiceDueDate":$('#Invoice_due_dt').val()
62959		};
62960
62961		var jsonInvoiceTicket = JSON.stringify(invoiceTicket);
62962
62963        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: jsonInvoiceTicket, contentType: "application/json" })
62964            .success(function(data, textStatus, jqXHR) {
62965				window.onbeforeunload = null;
62966				//update the device list table
62967				// _pax.ShowSelectedWifiDeviceInDeviceList(data);
62968				//_pax.setvar(data.DeviceId);
62969            	new GLO.Popup.Success('Invoice Sent.', 1000);
62970				GLO.Popup.close($('#pop-invoice-header').closest('.glopop'));
62971            })
62972            .error(function(jqXHR, textStatus, errorThrown) {
62973                GLO.UI.Form.resetProcessing(); 		
62974                new GLO.Popup.Error('Unable to Send Invoice');
62975            });
62976	}
62977    
62978    return _conTicket;
62979})();
62980
62981SA.TicketCard = (function() {
62982    function _cTicketCard() { }
62983    var _cards = [], _smids = [], _staffSummary = [];
62984    
62985    _cTicketCard.openTicket = function(tr) {
62986    	var jtr = $(tr);
62987    	var jclient = _getSigninClient(jtr);
62988    	var isStaffPreview = jtr.closest('#pop-staff-preview').length;
62989    	
62990    	jclient = _addBookingAttributes(jtr, jclient, isStaffPreview);
62991    	
62992    	if (isStaffPreview) {
62993    		var bkgData = _getSigninServicesFromStaffPreview(jtr, jclient);
62994    	} else {
62995    		var bkgData = _getSigninServicesFromPosTicketCard(jtr, jclient);
62996    	}
62997    	
62998    	SA.Ticket.loadTicket(bkgData);
62999    	
63000    	if (UTIL.isNumber(jtr.attr('wait_id'))) {
63001        	UserPortal.waitListId = parseInt(jtr.attr('wait_id'));
63002        	SA.Ticket.waitId = UserPortal.waitListId;
63003        }
63004        
63005        if (isStaffPreview) {
63006        	GLO.Popup.closeIfExist($('#pop-staff-preview').closest('.glopop'));
63007        }
63008    }
63009    _cTicketCard.openSignin = function(waitId) {
63010    	var jpanel = $('#pos-panel-client-list');
63011    	jpanel.find('tr.pos-ticket-card[wait_id="' + waitId + '"]').click();
63012    }
63013    
63014    function _getSigninServicesFromStaffPreview(jtr, jclient) {
63015    	var faId = UserPortal.getFirstAvailableStaffId();
63016    	var staffId = null, staffName = '', arrSvc = [], bkgData = '';
63017    	var jservices  = jtr.find('.staff-preview-service .staff-preview-line-amount');
63018    	var jservices2 = jtr.find('.staff-preview-service .staff-preview-line-amount-other');
63019    	
63020    	for (var i=0; i < jservices.length; i++) {
63021    		var svcid = jservices.eq(i).attr('service_id');
63022    		var sid = jservices.eq(i).attr('staff_id');
63023    		var price = UTIL.coalesceMoney(jservices.eq(i).find('.line-total').text());
63024    		
63025    		arrSvc.push({ "service_id": svcid, "staff_id": sid, "price_mn": price });
63026    	}
63027    	
63028    	for (var i=0; i < jservices2.length; i++) {
63029    		var svcid = jservices2.eq(i).attr('service_id');
63030    		var sid = jservices2.eq(i).attr('staff_id');
63031    		var price = UTIL.coaleceMoney(jservices2.eq(i).attr('price_mn'));
63032    		
63033    		arrSvc.push({ "service_id": svcid, "staff_id": sid, "price_mn": price });
63034    	}
63035    	
63036    	for (var a=0; a < arrSvc.length; a++) {
63037    		if (a == 0) {
63038    			jclient.attr('multi_appt_count_sr', arrSvc.length);
63039    		} else {
63040				bkgData += jclient.outerHTML();
63041			}
63042    		
63043    		var sid = UTIL.coalesceString(arrSvc[a].staff_id, faId);
63044			//if (!UTIL.isEmpty(sid) && UTIL.isEmpty(staffId) && !UTIL.parseBool(jservices.eq(i).attr('is_first_available_fl'))) { staffId = sid; }
63045			
63046			if (sid > 0) {
63047				jclient.attr('staff_id', sid);
63048			}
63049			
63050			if (arrSvc[a].service_id > 0) {
63051				var osvc = UserPortal.Booking.lookupDefault(arrSvc[a].service_id, sid);
63052				var price = UTIL.coalesceMoney(arrSvc[a].price_mn, osvc.price);
63053				
63054				jclient.attr('service_id', arrSvc[a].service_id);
63055				jclient.attr('service_group_id', osvc.service_group_id);
63056				jclient.attr('price_mn', price);
63057			}
63058			
63059			if (!UTIL.isEmpty(sid) && sid != faId) {
63060				jclient.attr('client_request_fl', '1');
63061			} else {
63062				jclient.attr('client_request_fl', '0');
63063			}
63064    	}
63065    	
63066    	bkgData += jclient.outerHTML();
63067    	return bkgData;
63068    }
63069    function _getSigninServicesFromPosTicketCard(jtr, jclient) {
63070    	var faId = UserPortal.getFirstAvailableStaffId();
63071    	var staffId = null, staffName = '', arrSvc = [], bkgData = '';
63072    	var jspecialRequest = jtr.find('.pos-card-note');
63073    	var specialRequest = UTIL.coalesceString(jspecialRequest.attr('title'), jspecialRequest.text());
63074    	
63075    	if (!UTIL.isEmpty(specialRequest)) {
63076    		jclient.attr('special_request_vcl', specialRequest);
63077    	}
63078    	
63079    	var jstaff = jtr.find('.pos-card-staff-name');
63080    	var jservices = jtr.find('.pos-card-service-name');
63081    	
63082    	for (var i=0; i < jservices.length; i++) {
63083    		var svcid = jservices.eq(i).attr('service_id');
63084    		var sid = jservices.eq(i).attr('staff_id');
63085    		
63086    		if (!UTIL.isEmpty(svcid)) {
63087    			arrSvc.push({ "service_id": svcid, "staff_id": sid });
63088    		}
63089    		
63090    		if (!UTIL.isEmpty(sid) && UTIL.isEmpty(staffId) && !UTIL.parseBool(jservices.eq(i).attr('is_first_available_fl'))) {
63091    			staffId = sid;
63092    		}
63093    	}
63094    	
63095    	if (arrSvc.length == 0) {
63096    		for (var i=0; i < jstaff.length; i++) {
63097    			var sname = jstaff.eq(i).text();
63098    			var sid = jstaff.eq(i).attr('staff_id');
63099    			
63100    			if (!UTIL.isEmpty(sname) && faId != sid) {
63101    				staffId = sid;
63102    				staffName = sname;
63103    				
63104    				jclient.attr('client_request_fl', '1').attr('staff_id', sid);
63105    				break;
63106    			}
63107    		}
63108    	} else {
63109    		jclient.attr('multi_appt_count_sr', arrSvc.length);
63110    		
63111    		for (var i=0; i < arrSvc.length; i++) {
63112    			if (i > 0) {
63113    				bkgData += jclient.outerHTML();
63114    			}
63115    			
63116    			var sid = UTIL.coalesceString(arrSvc[i].staff_id, faId);
63117    			var osvc = UserPortal.Booking.lookupDefault(arrSvc[i].service_id, sid);
63118    			var price = UTIL.coalesceMoney(osvc.price);
63119    			
63120    			jclient.attr('price_mn', price);
63121    			jclient.attr('staff_id', sid);
63122    			jclient.attr('service_id', arrSvc[i].service_id);
63123    			jclient.attr('service_group_id', osvc.service_group_id);
63124    			
63125    			if (!UTIL.isEmpty(sid) && sid != faId) {
63126    				jclient.attr('client_request_fl', '1');
63127    			} else {
63128    				jclient.attr('client_request_fl', '0');
63129    			}
63130    		}
63131    	}
63132    	
63133    	bkgData += jclient.outerHTML();
63134    	return bkgData;
63135    }
63136    
63137    function _addBookingAttributes(jtr, jclient, isStaffPreview) {
63138    	var waitId = jtr.attr('wait_id');
63139    	var note = UTIL.cleanString(UTIL.coalesceString(jtr.find('.pos-card-note').text(), jtr.find('.special-request-icon').attr('title')));
63140    	
63141    	var day  = new Date().toGloDate();
63142    	var time = new Date().toGloTime();
63143    	
63144    	if (isStaffPreview) {
63145    		var signinDate = jtr.find('.staff-preview-signin-icon').attr('signin_dt');
63146    	} else {
63147    		var signinTime = UTIL.directTagOnly(jtr.find('.pos-card-start'));
63148    		
63149    		if (UTIL.isValidTime(signinTime)) {
63150	    		var signinDate = day + ' ' + signinTime;
63151	    		time = signinTime;
63152	    	} else {
63153	    		var signinDate = day + ' ' + new Date().toGloTime();
63154	    	}
63155    	}
63156    	
63157    	jclient.attr('wait_id', waitId).attr('provider_id', GLO.Data.provider.id);
63158    	jclient.attr('special_request_vcl', note);
63159    	
63160    	jclient.attr('appt_dt', day);
63161    	jclient.attr('time_vc', time);
63162    	
63163    	if (UTIL.isDate(signinDate)) {
63164    		jclient.attr('signin_dt', signinDate);
63165    	}
63166    	
63167    	return jclient;
63168    }
63169    function _getSigninClient(jtr) {
63170    	var jclient = jtr.find('.pos-card-client');
63171    	
63172    	if (jclient.length) {
63173    		var cid = jclient.attr('client_id'), ctype = UTIL.coalesceInt(jclient.attr('client_type_cd'), 1);
63174    		var cname = UTIL.replaceQuotes(jclient.text());
63175    	} else {
63176    		var jclient = jtr.find('.staff-preview-client');
63177    		var jcname = jclient.find('.staff-preview-client-name');
63178    		
63179    		var cid = jclient.attr('client_id'), ctype = UTIL.coalesceInt(jclient.attr('client_type_cd'), 1);
63180    		var cname = UTIL.replaceQuotes(UTIL.coalesceString(jcname.attr('title'), jcname.text()));
63181    	}
63182    	
63183    	var birth = jclient.attr('birth_sr');
63184    	var gift = jclient.attr('gift_balance_mn'), membershipId = jclient.attr('membership_id'), tagCount = jclient.attr('tag_count_sr');
63185    	var pts = jclient.attr('loyalty_points_nr'), cftid = jclient.attr('cftid');
63186    	var importantNote = jclient.attr('important_note_vc'), otherNote = jclient.attr('other_note_vc');
63187    	
63188    	var tr = $('<tr client_id="' + cid + '" client_vc="' + cname + '" client_type_cd="' + ctype + '"/>');
63189    	
63190    	if (birth > 0) {
63191    		 tr.attr('birth_sr', birth);
63192    	}
63193    	
63194    	if (gift > 0) {
63195			tr.attr('gift_balance_mn', gift);
63196		}
63197		
63198		if (membershipId > 0) {
63199			tr.attr('membership_id', membershipId);
63200		}
63201		
63202		if (tagCount > 0) {
63203			tr.attr('tag_count_sr', tagCount);
63204		}
63205		
63206		if (pts > 0) {
63207			tr.attr('client_loyalty_nr', pts);
63208		}
63209		
63210		if (cftid > 0) {
63211			tr.attr('cftid', cftid);
63212		}
63213		
63214		if (!UTIL.isEmpty(importantNote)) {
63215    		 tr.attr('staff_note_vcl', importantNote);
63216    	}
63217    	
63218		return tr;
63219    }
63220    
63221    _cTicketCard.displayCards = function() {
63222    	var htm = '';
63223    	var firstAvailableId = UserPortal.getFirstAvailableStaffId();
63224    	
63225    	for (var i=0; i < _cards.length; i++) {
63226    		if (_cards[i].status != 270) {									//= do NOT display no-show or late-cancel
63227    			htm += _getCardHtm(_cards[i], firstAvailableId);
63228    		}
63229    	}
63230    	
63231    	var jpanel = $('#pos-panel-client #pos-panel-client-list');
63232    	var trSignin = jpanel.find('tr.pos-ticket-walkin');
63233    	var htmSignin = _getCardSigninRows(trSignin);
63234    	var trhead = _getHeaderRow(trSignin.length);
63235    	
63236    	htm = '<table class="tablesorter">' + trhead + '<tbody>' + htmSignin + htm + '</tbody></table>';
63237    	
63238    	jpanel.html(htm);
63239    	var jtbl = jpanel.find('> table');
63240    	UI.initTableSorter(jtbl);
63241    	
63242    	if (_cards.length > 0) {
63243    		$('#pos-staff-list-header1 #pos-staff-list-header1-clientpanel').removeClass('hide');
63244    	} else {
63245    		$('#pos-staff-list-header1 #pos-staff-list-header1-clientpanel').addClass('hide');
63246    	}
63247    	
63248    	SA.POS.resetPanelHeight();
63249    }
63250    function _getHeaderRow(waitRowCount) {
63251    	if (waitRowCount == 0 && _cards.length === 0) {
63252    		return '';
63253    	} else {
63254    		return '<thead><tr>'
63255					    + '<th class="pos-card-staff">Staff</th>'
63256					    + '<th class="pos-card-start">Start</th>'
63257					    + '<th class="pos-card-client">Client</th>'
63258						
63259					    + '<th class="pos-card-service">Service</th>'
63260					    + '<th class="pos-card-update">Last Update</th>'
63261					    + '<th class="pos-card-price">Price</th>'
63262					+ '</tr></thead>';
63263    	}
63264    }
63265    function _getCardSigninRows(trSignin) {
63266    	var htm = '';
63267    	
63268    	for (var w=0; w < trSignin.length; w++) {
63269    		htm += trSignin.eq(w).outerHTML();
63270    	}
63271    	
63272    	return htm;
63273    }
63274    function _getCardHtm(card, firstAvailableId) {
63275    	var css = _getStatusCss(card.status);
63276    	var onclick = ' onclick="UserPortal.getTicket(' + card.schedule_multi_id + ', ' + card.booking_nr + ', null, false, true)"';
63277    	var htm = '<tr class="pos-ticket-appt pos-ticket-card ' + css + '" schedule_multi_id="' + card.schedule_multi_id + '"' + onclick + '>';
63278    	
63279    	htm += _getCardStaffHtm(card, firstAvailableId);
63280    	htm += _getCardStartHtm(card);
63281    	htm += _getCardClientHtm(card);
63282    	
63283    	htm += _getCardServiceHtm(card);
63284    	htm += _getCardLastUpdateHtm(card) + '</span>';
63285    	htm += _getCardPriceHtm(card);
63286    	
63287    	return htm + '</tr>';
63288    }
63289    function _getCardStartHtm(card) {
63290    	var htmDiff = '', htmIcon = '';
63291    	var htmStart = '<span class="pos-card-start-time">' + card.start_tm + '</span>';
63292    	
63293    	if (card.status == 5 || card.status == 29) {
63294    		var diffMinutes = UTIL.coalesceInt((new Date(card.start_dt).getTime() - new Date().getTime()) / 60 / 1000, 0);
63295    		
63296    		if (diffMinutes > 0) {
63297    			var label = 'early';
63298    		} else {
63299    			var label = 'late';
63300    		}
63301    		
63302    		css = 'pos-start-diff pos-card-' + label;
63303    		htmDiff = '<span class="' + css + '"><b>' + Math.abs(diffMinutes) + ' min ' + label + '</b></span>';
63304    	}
63305    	
63306    	if (card.schedule_multi_id > 0) {
63307	    	if ( (card.start_dt - card.create_dt) / (60*60*1000) > 1 ) {			//appt created > 1 hr before start
63308	    		var title = 'Appointment Created on ' + card.create_dt.toGloDateString();
63309	    		htmIcon = '<b class="pre-booked-appointment-icon" title="' + title + '"><span></span></b>';
63310	    	} else {
63311	    		//htmIcon = '<span class="walkin-icon"><b>walk-in</b></span>';
63312	    		//htmIcon = '<span class="walkin-icon" title="Walk-In"><b style="top: inherit; left: inherit; bottom: -14px; right: -90px;">W</b></span>';
63313	    	}
63314    	}
63315    	
63316    	return '<td class="pos-card-start">' + htmIcon + htmDiff + htmStart + '</td>';
63317    }
63318    function _getCardClientHtm(card) {
63319    	var icons = '', clientTitle = '', clientName = UTIL.cleanString(card.services[0].client_vc);
63320    	
63321    	if (clientName.length > 2 && card.services[0].client_type_cd == 1) {
63322    		icons += '<span class="new-client-text-icon" title="New Client"><b>new</b></span>';
63323    		
63324    		if (UTIL.startsWith(clientName, '* ')) {
63325    			clientName = clientName.substring(2);
63326    		}
63327    	}
63328    	
63329    	if (clientName.length > 20) {
63330    		clientTitle = ' title="' + UTIL.replaceQuotes(clientName) + '"';
63331    	}
63332    	
63333    	return '<td class="pos-card-client"' + clientTitle + '>' + UTIL.maxString(clientName, 20, true) + icons + '</td>';
63334    }
63335    function _getCardStaffHtm(card, firstAvailableId) {
63336    	var arrStaff = [], htm = '';
63337    	var start = new Date(card.start_dt).toGloDateTime();
63338    	
63339    	for (var i=0; i < card.services.length; i++) {
63340    		var staffId = card.services[i].staff_id;
63341    		
63342    		if (staffId && !arrStaff.has(staffId) && firstAvailableId != staffId) {			//&& start == new Date(card.services[i].start).toGloDateTime()
63343    			var staffTitle = '', htmRequested = '', staffName = card.services[i].staff_vc;
63344    			
63345    			if (UTIL.parseBool(card.client_request_fl)) {
63346		    		htmRequested = '<b class="checkmark-icon"></b>';
63347		    	}
63348		    	
63349    			if (UTIL.isEmpty(staffName)) {
63350    				staffName = UserPortal.getStaffName(staffId);
63351    			}
63352    			
63353		    	if (staffName.length > 10) {
63354		    		staffTitle = ' title="' + UTIL.replaceQuotes(staffName) + '"';
63355		    	}
63356		    	
63357    			arrStaff.push(staffId);
63358    			htm += '<span class="pos-card-staff-name pos-card-staff' + arrStaff.length + '"' + staffTitle + '>' + UTIL.maxString(staffName, 10, true) + '</span>';
63359    		}
63360    	}
63361    	
63362    	return '<td class="pos-card-staff">' + htm + '</td>';
63363    }
63364    function _getCardServiceHtm(card) {
63365    	var arrService = [], htm = '';
63366    	var start = new Date(card.start_dt).toGloDateTime();
63367    	
63368    	for (var i=0; i < card.services.length; i++) {
63369    		if (start == new Date(card.services[i].start).toGloDateTime() && !arrService.has(card.services[i].service_id)) {
63370    			var title = '', name = card.services[i].service_name_vc;
63371    			
63372    			if (name.length > 15) {
63373		    		title = ' title="' + UTIL.replaceQuotes(name) + '"';
63374		    	}
63375		    	
63376    			arrService.push(card.services[i].service_id);
63377    			htm += '<span class="pos-card-service-name pos-card-service' + arrService.length + '"' + title + '>' + UTIL.maxString(name, 15, true) + '</span>';
63378    		}
63379    	}
63380    	
63381    	return '<td class="pos-card-service">' + htm + '</td>';
63382    }
63383    function _getCardLastUpdateHtm(card) {
63384    	var htm = '', htmDue = '';
63385    	var lastUpdateDate = new Date(card.services[0].last_update_dt);
63386    	var lastUpdateBy = card.services[0].update_by_vc;
63387    	
63388    	for (var i=1; i < card.services.length; i++) {
63389    		if (new Date(card.services[i].last_update_dt) > lastUpdateDate) {
63390    			lastUpdateDate = new Date(card.services[i].last_update_dt);
63391    			lastUpdateBy = card.services[i].update_by_vc;
63392    		}
63393    	}
63394    	
63395    	var lastUpdateTitle = 'Last Update by ' + lastUpdateBy + ' at ' + lastUpdateDate.toGloTime() + ' on ' + lastUpdateDate.toGloDateString(true, true);
63396    	var hourDiff = UTIL.coalesceInt( (new Date() - lastUpdateDate) / (60*60*1000), 0);
63397    	
63398    	if (hourDiff < 2) {
63399    		var minuteDiff = UTIL.coalesceInt( (new Date() - lastUpdateDate) / (1000 * 60), 0);
63400    		updateLabel = UTIL.pluralLabel(minuteDiff, 'min') + ' ago';
63401    	} else if (hourDiff < 25) {
63402    		updateLabel = UTIL.pluralLabel(hourDiff, 'hour') + ' ago';
63403    	} else if (new Date().addDays(-1).toGloDate() == lastUpdateDate.toGloDate()) {
63404    		updateLabel = 'yesterday';
63405    	} else {
63406    		var dayDiff = UTIL.dayDiff(lastUpdateDate, new Date()) + 1;
63407    		updateLabel = UTIL.pluralLabel(dayDiff, 'day') + ' ago';
63408    	}
63409    	
63410    	if (card.price_mn > 0 && card.payment_mn > 0) {
63411    		var due = UTIL.coalesceMoney(card.price_mn - card.payment_mn);
63412    		var cssDue = 'pos-ticket-update-due';
63413    		var title = 'Price = ' + UTIL.displayMoney(card.price_mn);
63414    		
63415    		if (card.payment_mn > 0) {
63416    			title = 'Payment = ' + UTIL.displayMoney(card.payment_mn) + ' | ' + title;
63417    		}
63418    		
63419    		if (due > 0) {
63420    			due = '<small>Due</small> <span class="dollar-sign">$</span><span>' + UTIL.displayMoney(due, true) + '</span>';
63421    		} else {
63422    			due = 'PAID';
63423    			cssDue += ' pos-ticket-update-paid';
63424    		}
63425    		
63426    		htmDue = '<b class="' + cssDue + '" title="' + title + '">' + due + '</b>';
63427    	}
63428    	
63429    	var htmUpdate = '<i class="pos-ticket-update-label" title="' + lastUpdateTitle + '">' + updateLabel + '</i>';
63430    	return '<td class="pos-card-update"><span class="pos-card-update2">' + htmUpdate + htmDue + '</span></td>';
63431    }
63432    function _getCardPriceHtm(card) {
63433    	var price = UTIL.coalesceMoney(card.price_mn);
63434    	var tip = UTIL.coalesceMoney(card.tip_mn);
63435    	var payment = UTIL.coalesceMoney(card.payment_mn);
63436    	var css = '', htmPrice = '', htmTip = '';
63437    	
63438    	if (price > 0) {
63439    		if (payment >= price) {
63440    			css = ' appt-paid';
63441    		}
63442    		
63443    		htmPrice = '<b class="pos-card-client-price">' + UTIL.displayMoney(price) + '</b>';
63444    	}
63445    	
63446    	if (tip > 0) {
63447    		htmTip = '<i class="plus-sign">+</i><span class="dollar-sign">$</span><i>' + UTIL.displayMoney(tip, true) + '</i>';
63448    		htmTip = '<b class="pos-card-client-tip" title="Tip = $' + tip + '">' + htmTip + '</b>';
63449    	}
63450    	
63451    	return '<td class="pos-card-price' + css + '">' + htmPrice + htmTip + '</td>';
63452    }
63453    
63454    function _createStaffSummary() {
63455    	var arr = [];
63456    	
63457    	for (var i=0; i < GLO.staffResources.length; i++) {
63458    		if (!GLO.staffResources.is_first_available_fl) {
63459    			var ss = structuredClone(GLO.staffResources[i]);
63460    			
63461	    		ss.price_mn = 0;
63462	    		ss.service_sr = 0;
63463	    		ss.turn_sr = 0;
63464	    		ss.ticket_sr = 0;
63465	    		ss.smids = [];
63466	    		
63467	    		arr.push(ss);
63468    		}
63469    	}
63470    	
63471    	return arr;
63472    }
63473    function _updateStaffSummary(staffSummary, calEvent) {
63474		if (calEvent.appt_status_cd == 21 || calEvent.appt_status_cd == 22 || calEvent.appt_status_cd == 25) {
63475			for (var i=0; i < staffSummary.length; i++) {
63476	    		if (staffSummary[i].id == calEvent.staff_id) {
63477	    			staffSummary[i].price_mn = UTIL.coalesceMoney(staffSummary[i].price_mn, 0) + UTIL.coalesceMoney(calEvent.price_mn);
63478	    			
63479	    			staffSummary[i].service_sr = UTIL.coalesceInt(staffSummary[i].service_sr, 0) + 1;
63480	    			staffSummary[i].turn_sr = UTIL.coalesceInt(staffSummary[i].turn_sr, 0) + 1;
63481	    			
63482	    			if (!staffSummary[i].smids.has(calEvent.schedule_multi_id)) {
63483	    				staffSummary[i].smids.push(calEvent.schedule_multi_id);
63484	    				staffSummary[i].ticket_sr = UTIL.coalesceInt(staffSummary[i].ticket_sr, 0) + 1;
63485	    			}
63486	    			
63487	    			return;
63488	    		}
63489	    	}
63490	    }
63491    }
63492    _cTicketCard.getStaffSummary = function() {			//returns copy of staffSummary (so doesn't reload array during processing)
63493    	return _staffSummary.slice();
63494    }
63495    
63496	_cTicketCard.loadAppointments = function(calEvents) {
63497		var offHourSGID = UserPortal.getOffTimeServiceGroupId();
63498    	var internalSGID = UserPortal.getInternalServiceGroupId();
63499		var staffSummary = _createStaffSummary();
63500		_cards = [];
63501		_smids = [];
63502		
63503		if (calEvents) {
63504			for (var i=0; i < calEvents.length; i++) {
63505	    		var ev = calEvents[i];
63506	    		
63507	    		if (ev.service_group_id != offHourSGID && ev.service_group_id != internalSGID && !UTIL.parseBool(ev.is_finish_out_fl)) {
63508		    		if (_smids.has(ev.schedule_multi_id)) {
63509		    			_updateCard(ev);
63510		    		} else {
63511		    			_addCard(ev);
63512		    		}
63513		    		
63514		    		_updateStaffSummary(staffSummary, ev);
63515		    	}
63516		    }
63517		    
63518		    _cards.sort(_sortCards);
63519		}
63520		
63521		staffSummary.sort(_sortStaffSummary);
63522		_staffSummary = staffSummary;
63523		_cTicketCard.displayCards();
63524	}
63525	
63526	function _addCard(ev) {
63527		var status = _getStatus(ev);
63528		var dt = new Date(ev.start);
63529		var tm = dt.toGloTime();
63530		
63531		var pmt = UTIL.coalesceMoney(ev.total_payment_mn), tip = UTIL.coalesceMoney(ev.tip_mn);
63532		var price = UTIL.coalesceMoney(ev.price_mn) + UTIL.coalesceMoney(ev.tax_mn) + tip;			// - UTIL.coalesceMoney(ev.discount_mn) + UTIL.coalesceMoney(ev.add_on_fee_mn)
63533		price = UTIL.coalesceMoney(price + UTIL.coalesceMoney(ev.inventory_price_mn) - UTIL.coalesceMoney(ev.total_discount_mn) + UTIL.coalesceMoney(ev.total_AddOnFee_mn));
63534		
63535		var card = { 
63536					"schedule_multi_id": ev.schedule_multi_id, "booking_nr": ev.booking_nr, "price_mn": price, "tip_mn": tip, "payment_mn": pmt, "status": status
63537					, "client_request_fl": ev.client_request_fl, "start_dt": dt, "start_tm": tm, "start_sr": UTIL.timeToInt(tm), "create_dt": new Date(ev.create_dt), "services": []
63538				};
63539		
63540		card.services.push(ev);
63541		_cards.push(card);
63542		_smids.push(ev.schedule_multi_id);
63543	}
63544	function _updateCard(ev) {
63545		var card = _findCard(ev.schedule_multi_id);
63546		var tip = UTIL.coalesceMoney(ev.tip_mn);
63547		var price = UTIL.coalesceMoney(ev.price_mn) + UTIL.coalesceMoney(ev.tax_mn) + tip;		// - UTIL.coalesceMoney(ev.discount_mn) + UTIL.coalesceMoney(ev.add_on_fee_mn)
63548		
63549		if (card.create_dt > new Date(ev.create_dt)) {
63550			card.create_dt = new Date(ev.create_dt);
63551		}
63552		
63553		if (UTIL.parseBool(ev.client_request_fl)) {
63554			card.client_request_fl = 1;
63555		}
63556		
63557		card.tip_mn = UTIL.coalesceMoney(card.tip_mn + tip);
63558		card.price_mn = UTIL.coalesceMoney(card.price_mn + price);
63559		card.services.push(ev);
63560	}
63561	function _findCard(smid) {
63562		for (var i=0; i < _cards.length; i++) {
63563			if (smid == _cards[i].schedule_multi_id) {
63564				return _cards[i];
63565			}
63566		}
63567		
63568		return null;
63569	}
63570	
63571	function _sortStaffSummary(staff1, staff2) {
63572		if (staff1.turn_sr < staff2.turn_sr) {
63573			return -1;
63574		} else if (staff1.turn_sr > staff2.turn_sr) {
63575			return 1;
63576		
63577		} else if (staff1.price_mn < staff2.price_mn) {
63578			return -1;
63579		} else if (staff1.price_mn > staff2.price_mn) {
63580			return 1;
63581		
63582		} else {
63583			return 0;
63584		}
63585	}
63586	
63587	function _sortCards(card1, card2) {
63588		if (card1.status < card2.status) {
63589			return -1;
63590		} else if (card1.status > card2.status) {
63591			return 1;
63592		
63593		} else if (card1.start_sr < card2.start_sr) {
63594			return -1;
63595		} else if (card1.start_sr > card2.start_sr) {
63596			return 1;
63597		
63598		} else {
63599			return 0;
63600		}
63601	}
63602	
63603	function _getStatus(ev) {
63604		var dtStart = new Date(ev.start);
63605		
63606		if (ev.appt_status_cd == 22) {																				//= checked-out			 || UTIL.isDate(ev.checkout_dt)
63607			return 120;
63608		} else if (ev.appt_status_cd == 21) {																		//= checked-in			 || UTIL.isDate(ev.checkin_dt)
63609			return 21;
63610		} else if (ev.appt_status_cd == 13) {																		//= no-show or late-cancel
63611			return 130;
63612		} else if (ev.appt_status_cd == 14) {																		//= no-show or late-cancel
63613			return 140;
63614		} else if (ev.appt_status_cd == 25) {																		//= ready to pay
63615			return 25;
63616		} else if (UTIL.isDate(ev.signin_dt) && new Date(ev.signin_dt).toGloDate(
63616) == new Date().toGloDate()) {		//= client sign-in
63617			return 2;
63618		} else {
63619			var diffMinutes = (new Date().getTime() - dtStart.getTime()) / 60 / 1000;
63620			
63621			if (Math.abs(diffMinutes) < 16) {																		//= now
63622				return 5;
63623			} else if (diffMinutes > 0 && diffMinutes < 60) {														//= late (appt start time < 60 minutes in the past)
63624				return 29;
63625			} else if (dtStart > new Date()) {																		//= upcoming
63626				return 41;
63627			} else if (dtStart < new Date()) {																		//= past
63628				return 60;
63629			}
63630		}
63631		
63632		return 40;
63633	}
63634	function _getStatusCss(status) {
63635		var css = 'cardstatus' + status + ' ';
63636		
63637		if (status == 2) {											//= client sign-in
63638			css += 'card-signin';
63639		} else if (status == 5) {									//= now
63640			css += 'card-now';
63641		
63642		} else if (status == 21) {									//= checked-in
63643			css += 'card-checkin';
63644		} else if (status == 25) {									//= ready to pay
63645			css += 'card-ready';
63646		} else if (status == 29) {									//= late
63647			css += 'card-late';
63648		
63649		} else if (status >= 40 && status <= 49) {					//= upcoming
63650			css += 'card-upcoming';
63651		} else if (status >= 90 && status <= 99) {					//= past
63652			css += 'card-past';
63653		
63654		} else if (status == 120) {									//= checked-out
63655			css += 'card-checkout';
63656		} else if (status == 130) {									//= no-show
63657			css += 'card-noshow';
63658		} else if (status == 140) {									//= late-cancel
63659			css += 'card-late-cancel';
63660		}
63661		
63662		return css;
63663	}
63664	
63665	function _loadSigninData(data) {
63666		var jpanel = $('#pos-panel-client #pos-panel-client-list > table');
63667    	jpanel.find('tr.pos-ticket-walkin').remove();
63668		jpanel.prepend($(data).html());
63669		
63670		_cTicketCard.displayCards();
63671		_updateSigninCount(data);
63672	}
63673	
63674	function _updateSigninCount(data) {
63675		var jstaff = $('#pos-staff-screen').find('.pos-staff-cell');
63676		var trSignin = $(data).find('tr');
63677		var faid = UserPortal.getFirstAvailableStaffId();
63678		
63679		for (var a=0; a < trSignin.length; a++) {
63680			var jss = trSignin.eq(a).find('.pos-card-staff-name');
63681			
63682			if (jss.length == 0 && faid > 0) {
63683				for (var r=0; r < GLO.resourceHours.length; r++) {
63684					if (GLO.resourceHours[r].id == faid) {
63685						GLO.resourceHours[r].walkin_signin_sr = UTIL.coalesceInt(GLO.resourceHours[r].walkin_signin_sr, 0) + 1;
63686					}
63687				}
63688			} else {
63689				for (var b=0; b < jss.length; b++) {
63690					var staffId = jss.eq(b).attr('staff_id');
63691					
63692					for (var r=0; r < GLO.resourceHours.length; r++) {
63693						if (GLO.resourceHours[r].id == staffId) {
63694							GLO.resourceHours[r].walkin_signin_sr = UTIL.coalesceInt(GLO.resourceHours[r].walkin_signin_sr, 0) + 1;
63695						}
63696					}
63697				}
63698			}
63699		}
63700		
63701		for (var i=0; i < GLO.resourceHours.length; i++) {
63702			if (GLO.resourceHours[i].walkin_signin_sr > 0) {
63703				var jstaff = $('#pos-staff-screen').find('.pos-staff-cell[staff_id="' + GLO.resourceHours[i].id + '"]');
63704				var jicon = jstaff.find('.staff-appt-signin');
63705				
63706				if (jicon.length) {
63707					var jcnt = jicon.find('.staff-appt-signin-count');
63708					var count = parseInt(jcnt.text());
63709					var title = jcnt.attr('title') + ' with appointment | ' + GLO.resourceHours[i].walkin_signin_sr + ' sign-in without appointment';
63710					
63711					jcnt.text(parseInt(count + GLO.resourceHours[i].walkin_signin_sr)).attr('title', title);
63712				} else {
63713					var htmIcon = SA.POS.getSigninIcon(GLO.resourceHours[i].walkin_signin_sr);
63714					jstaff.prepend(htmIcon);
63715				}
63716				
63717				var jlabel = jstaff.find('.staff-box-label');
63718				var priority = UTIL.coalesceInt(jlabel.attr('priority_sr'), 99);
63719				
63720				if (priority > 9) {
63721					var css = 'label-status-2', title = '', label = 'SIGN-In <i>WALK-In</i>';
63722					var htmLabel = SA.POS.getLabelHtm(css, title, 2, 2, label);
63723					jlabel.replaceWith(htmLabel);
63724				}
63725			}
63726		}
63727	}
63728	
63729	function _loadExtraClockOutsOnStaffPreview(jpop, staffId) {
63730		var jStaffCard = $('#pos-staff-list .pos-staff-cell[staff_id="' + staffId + '"]');
63731		var jul = jStaffCard.find('#staff-prev-clock-out-list');
63732		var jStaffPreviewHeader = jpop.find('#staff-preview-header');
63733		
63734		jStaffPreviewHeader.find('#staff-prev-clock-out-list').remove();
63735		
63736		if (jul.length) {
63737			jStaffPreviewHeader.prepend(jul.outerHTML());
63738		}
63739	}
63740	_cTicketCard.loadExtraClockOutsOnStaffPreview = function() {
63741		var jpop = $('#pop-staff-preview').closest('.glopop');
63742		
63743		if (jpop.length) {
63744			var staffId = jpop.find('#pop-staff-preview').attr('staff_id');
63745			
63746			_loadExtraClockOutsOnStaffPreview(jpop, staffId);
63747		}
63748	}
63749	_cTicketCard.checkIfNeedReload = function(jpop, staffId, ticketCount) {
63750		if (_checkIfNeedReload2(jpop, staffId, ticketCount)) {
63751			SA.POS.refreshEvents(true);
63752		} else {
63753			_loadExtraClockOutsOnStaffPreview(jpop, staffId);
63754		}
63755	}
63756	function _checkIfNeedReload2(jpop, staffId, ticketCount) {
63757    	var jStaffCard = $('#pos-staff-list .pos-staff-cell[staff_id="' + staffId + '"]');
63758    	var jcnt = jStaffCard.find('.staff-appt-count > b');
63759    	var total = 0, diff = 0;
63760    	
63761    	for (var i=0; i < jcnt.length; i++) {
63762    		total += parseInt(jcnt.eq(i).text());
63763    	}
63764    	
63765    	if (total != ticketCount) {
63766    		return true;
63767    	} else {
63768    		if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-signin')) {
63769    			return true;
63770    		} else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-checkin')) {
63771    			return true;
63772    		} else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-checkout')) {
63773    			return true;
63774    		
63775    		} else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-now')) {
63776    			return true;
63777    		} else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-late')) {
63778    			return true;
63779    		
63780    		} else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-upcoming')) {
63781    			return true;
63782    		} else if (_hasTicketDiff(jpop, jStaffCard, 'staff-appt-past')) {
63783    			return true;
63784    		}
63785    	}
63786    }
63787    function _hasTicketDiff(jpop, jStaffCard, cssClass) {
63788    	var popCnt = UTIL.coalesceInt(jpop.find('.' + cssClass + ' .staff-appt-count > b').text());
63789    	var cardCnt = UTIL.coalesceInt(jStaffCard.find('.' + cssClass + ' > b').text());
63790    }
63791    
63792	_cTicketCard.refreshSigninList = function() {
63793		var url = GLO.Link.WebsiteDomain + 'pos/GetSignin?cdn=' + GLO.Data.cdnVersion;
63794		
63795		$.ajax({ type: "GET", url: url, "cache": false })
63796            .success(function(data, textStatus, jqXHR) {
63797                if ($(data).hasClass('warning')) {
63798					if (UTIL.parseBool($(data).attr('must_refresh'))) {
63799						setTimeout(function() {
63800							location.reload();
63801 						}, 450);
63802					}
63803					
63804					new GLO.Popup.Warning(data);
63805					return true;
63806				} else {
63807                	_loadSigninData(data);
63808                	SA.TicketCard.refreshFilterPanel();
63809                }
63810            }).error(function(jqXHR, textStatus, errorThrown) {
63811            	if (textStatus == 'abort' && event && event.currentTarget && event.currentTarget.id == 'btnNewTicketQuick') {
63812            		if (oj && oj.close) {
63813            			oj.close();
63814            		}
63815            		
63816            		SA.Ticket.newTicket(sid, sname, isFA);
63817            	}
63818            });
63819	}
63820	
63821	_cTicketCard.refreshFilterPanel = function() {
63822		var panelFilter = GLO.Uri.hash('panel');
63823		
63824		if (!UTIL.isEmpty(panelFilter)) {
63825			SA.TicketCard.filterPanel(panelFilter, null, true);
63826		}
63827	}
63828	
63829	_cTicketCard.filterPanel = function(status, btn, isRefresh) {
63830		GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop'));
63831		
63832		var jpanel = $('#pos-panel-client:visible');
63833		isRefresh = UTIL.parseBool(isRefresh);
63834		
63835		if (jpanel.length == 0 && !isRefresh) {
63836			if (status == 11) {											//= all appointments
63837				SA.Menu.openReportUpcomingAppointments(null, btn);
63838			} else if (status == 21 || status == 110 || status == 210) {					//= checked-in
63839				SA.Menu.openReportCheckedIn(null, btn);
63840			} else if (status == 22 || status == 120 || status == 220) {					//= checked-out
63841				SA.Menu.openReportCheckedOut(null, btn);
63842			} else if (status == 2) {									//= client sign-in
63843				GLO.WaitList.open();
63844			} else {													//= recent
63845				SA.Menu.openReportRecent(20, btn);
63846			}
63847			
63848			return;
63849		}
63850		
63851		jpanel.removeClass('narrow-filter').find('.pos-ticket-card').addClass('hide');
63852		$('#pos-card-filter-header').find('.btnAdd.selected').removeClass('selected');
63853		
63854		if (status == 1) {																							//= all
63855			jpanel.find('.pos-ticket-card').removeClass('hide');
63856		} else if (status == 2) {																					//= sign-ins
63857			jpanel.find('.card-signin').removeClass('hide');
63858		} else if (status == 11) {																					//= all appointments: now, late, upcoming / other, past
63859			jpanel.find('.cardstatus5,.cardstatus29, .cardstatus40,.cardstatus41,.cardstatus42, .cardstatus90,.cardstatus91,.cardstatus92').removeClass('hide');
63860		} else if (status == 110) {																					//= checked-in | ready to pay | late
63861			jpanel.find('.cardstatus21, .cardstatus25, .cardstatus29').removeClass('hide');
63862		} else if (status == 220) {																					//= completed
63863			jpanel.find('.cardstatus22, .cardstatus130, .cardstatus140').removeClass('hide');
63864		} else {																									// is either: sign-in, now, or checked-out	
63865			jpanel.addClass('narrow-filter').find('.cardstatus' + status).removeClass('hide');
63866		}
63867		
63868		if (!isRefresh) {
63869			document.location.hash = 'panel=' + status;
63870			
63871			if (btn) {
63872				$(btn).addClass('selected');
63873			}
63874		}
63875	}
63876	
63877	_cTicketCard.openScanQRCode = function() {
63878    	var msg = '<p><label for="Ticket_QR_or_Number_vc" style="margin: 0; padding: 8px;">Scan Ticket\'s QR Code or Enter Ticket Number</label></p>';
63879    	var input = '<input type="text" id="Ticket_QR_or_Number_vc" maxlength="20" onkeyup="SA.TicketCard.enterTicketNumber(this)" autocomplete="off"/>';
63880    	var htmCards = _getCardInProgress();
63881    	
63882    	var htm = '<div id="pop-scan-qr">' + msg + input + htmCards + '</div>';
63883    	var jpop = GLO.Popup.Custom.openSimple(htm, 'Scan QR Code');
63884    	
63885    	GLO.Popup.Custom.singleButton(jpop, 'Close');
63886    	SA.POS.refreshEvents(true);
63887    }
63888    _cTicketCard.enterTicketNumber = function(element) {
63889    	var test = $.trim(element.value);
63890    	var testOriginal = test, isFullQRTicketNumber = false;
63891    	
63892    	if (!UTIL.isEmpty(test)) {
63893    		if (test.length > 1 && test.substring(0,2) == '#p' || test.substring(0,2) == '#P') {
63894    			test = test.substring(2);
63895    		} else if (test.substring(0,1) == 'p' || test.substring(0,1) == 'P') {
63896    			test = test.substring(1);
63897    		}
63898    		
63899    		if (test.length > 2 && test.endsWith('-qr') || test.endsWith('-QR')) {
63900    			test = test.substring(0, test.length - 3);
63901    			isFullQRTicketNumber = true;
63902    		} else if (test.length > 1 && test.endsWith('qr') || test.endsWith('QR')) {
63903    			test = test.substring(0, test.length - 2);
63904    			isFullQRTicketNumber = true;
63905    		}
63906    	}
63907    	
63908    	if (!UTIL.isEmpty(test)) {
63909	    	for (var i=0; i < _cards.length; i++) {
63910	    		if (_cards[i].booking_nr == test) {
63911	    			UserPortal.getTicket(_cards[i].schedule_multi_id, _cards[i].booking_nr, null, false, true);
63912	    			GLO.Popup.closeIfExist($('#pop-scan-qr').closest('.glopop'));
63913	    			
63914	    			return;
63915	    		}
63916	    	}
63917    	}
63918    	
63919    	if (isFullQRTicketNumber) {
63920	    	var jelement = $(element);
63921	    	var jdiv = jelement.closest('div');
63922	    	var msg = 'Ticket P' + test + ' Not Found';
63923	    	
63924	    	if (jelement.closest('#pop-scan-qr')) {
63925	    		var btn = '<span class="btnAdd" style="margin-left: 8px;">
63925<a onclick="UserPortal.Lookup.scanTicketLookup(' + test + ')">Lookup P' + test + ' on any date</a></span>';
63926	    		msg += ' as a Ticket Today ' + btn;
63927	    	}
63928	    	
63929	    	jdiv.find('.ticket-not-found').remove();
63930	    	jelement.before('<p class="ticket-not-found">' + msg + '</p>');
63931	    	element.value = '';
63932    	}
63933    	
63934    	//console.log('SA.TicketCard.enterTicketNumber: ' + testOriginal + ' -> ' + test);
63935    }
63936    
63937    function _getCardInProgress() {
63938    	var htmCards = '', styleUL = '', signinCount = 0, checkinCount = 0;
63939    	var trSignin = $('#pos-panel-client-list').find('tr.pos-ticket-walkin');
63940    	
63941    	for (var i=0; i < _cards.length; i++) {
63942    		if (_cards[i].status == 2 || _cards[i].status == 21) {
63943    			if (_cards[i].status == 2) {
63944    				var css = 'card-signin';
63945    				++signinCount;
63946    			} else {
63947    				var css = 'card-checkin';
63948    				++checkinCount;
63949    			}
63950    			
63951    			var smid = _cards[i].schedule_multi_id, bkg = _cards[i].booking_nr;
63952    			var clientName = UTIL.cleanString(_cards[i].services[0].client_vc);
63953    			
63954    			if (UTIL.startsWith(clientName, '* ')) {
63955	    			clientName = clientName.substring(2);
63956	    		}
63957    			
63958    			var htmBookingAndName = '<b>P' + bkg + '</b> <span>' + UTIL.maxString(clientName, 20, true) + '</span>';
63959    			var onClick = ' onclick="UserPortal.getTicket(' + smid + ', ' + bkg + ', null, false, true)"';
63960    			
63961    			htmCards += '<li class="' + css + '" smid="' + smid + '"' + onClick + '>' + htmBookingAndName + '</li>';
63962    		}
63963    	}
63964    	
63965    	for (var w=0; w < trSignin.length; w++) {
63966    		var waitId = trSignin.eq(w).attr('wait_id');
63967    		var clientName = trSignin.eq(w).find('.pos-card-client').text();
63968    		var htmBookingAndName = '<b></b> <span>' + UTIL.maxString(clientName, 20, true) + '</span>';
63969    		var onClick = ' onclick="SA.TicketCard.openSignin(' + waitId + ')"';
63970    		
63971    		htmCards += '<li class="signin-only card-signin" waitid="' + waitId + '"' + onClick + '>' + htmBookingAndName + '</li>';
63972    	}
63973    	
63974    	var msgHelp = _getCardInProgressSummary(signinCount, checkinCount);
63975    	var endDiv = '<div style="clear: both; min-height: 32px;"></div>';
63976    	
63977    	if (signinCount + checkinCount < 12) {
63978    		styleUL = 'max-width: 640px;';
63979    	}
63980    	
63981    	return msgHelp + '<ul id="simple-client-cards" style="' + styleUL + '">' + htmCards + '</ul>' + endDiv;
63982    }
63983    function _getCardInProgressSummary(signinCount, checkinCount) {
63984    	var msgHelp = '<p class="card-progress-summary">';
63985    	var bSignin = '<b class="card-signin">', bCheckin = '<b class="card-checkin">';
63986    	
63987    	if (signinCount > 0 && checkinCount > 0) {
63988    		msgHelp += bSignin + UTIL.pluralLabel(signinCount, 'Sign-In') + '</b> + ' + bCheckin + UTIL.pluralLabel(checkinCount, 'Check-In') + '</b>';
63989    	} else if (signinCount > 0) {
63990    		msgHelp += bSignin + UTIL.pluralLabel(signinCount, 'Sign-In') + '</b>';
63991    	} else if (checkinCount > 0) {
63992    		msgHelp += bCheckin + UTIL.pluralLabel(checkinCount, 'Check-In') + '</b>';
63993    	}
63994    	
63995    	return msgHelp + '</p>';
63996    }
63997    _cTicketCard.getCardSummary = function() {
63998    	var signinCount = 0, checkinCount = 0, checkoutCount = 0, readyToPayCount = 0;
63999    	var noShowCount = 0, lateCancelCount = 0;
64000    	var nowCount = 0, lateCount = 0, upcomingCount = 0, pastCount = 0;
64001    	var htm = '', header = '<h3>Today\'s Summary</h3>';
64002    	
64003    	for (var i=0; i < _cards.length; i++) {
64004    		if (_cards[i].status == 2) {
64005    			++signinCount;
64006    		} else if (_cards[i].status == 21) {
64007    			++checkinCount;
64008    		} else if (_cards[i].status == 22 || _cards[i].status == 120) {
64009    			++checkoutCount;
64010    		} else if (_cards[i].status == 25) {
64011    			++readyToPayCount;
64012    		
64013    		} else if (_cards[i].status == 13 || _cards[i].status == 130) {
64014    			++noShowCount;
64015    		} else if (_cards[i].status == 14 || _cards[i].status == 140) {
64016    			++lateCancelCount;
64017    		
64018    		} else if (_cards[i].status == 5) {
64019    			++nowCount;
64020    		} else if (_cards[i].status == 29) {
64021    			++lateCount;
64022    		} else if (_cards[i].status == 41) {
64023    			++upcomingCount;
64024    		} else if (_cards[i].status == 90) {
64025    			++pastCount;
64026    		}
64027    	}
64028    	
64029    	htm += _getCardSummary('Sign-In', signinCount, 'card-signin');
64030    	htm += _getCardSummary('Check-In', checkinCount, 'card-checkin');
64031    	htm += _getCardSummary('Check-Out', checkoutCount, 'card-checkout');
64032    	htm += _getCardSummary('Ready To Pay', readyToPayCount, 'card-ready');
64033    	
64034    	htm += _getCardSummary('No Show', noShowCount, 'card-noshow');
64035    	htm += _getCardSummary('Late Cancel', lateCancelCount, 'card-late-cancel');
64036    	
64037    	htm += _getCardSummary('Now Appointment', nowCount, 'card-now', 'within 20 minutes of now');
64038    	htm += _getCardSummary('Late Appointment', lateCount, 'card-late');
64039    	htm += _getCardSummary('Upcoming Appointment', upcomingCount, 'card-upcoming');
64040    	htm += _getCardSummary('Past Appointment', pastCount, 'card-past');
64041    	
64042    	var endDiv = '<div style="clear: both; min-height: 12px;"></div>';
64043    	return '<div id="pop-report-pos-summary" class="pop-report-box">' + header + '<ul>' + htm + '</ul>' + endDiv + '</div>';
64044    }
64045    function _getCardSummary(label, count, cssClass, title) {
64046    	var onclick = ' onclick="';
64047    	
64048    	if (cssClass == 'card-checkin') {
64049			onclick += 'SA.Menu.openReportCheckedIn(null, this)"';
64050		} else if (cssClass == 'card-checkout') {
64051			onclick += 'SA.Menu.openReportCheckedOut(null, this)"';
64052		} else if (cssClass == 'card-signin') {
64053			onclick += 'GLO.WaitList.open()"';
64054		} else if (cssClass == 'card-ready') {
64055			onclick += '"';
64056		
64057		} else if (cssClass == 'card-noshow') {
64058			onclick += 'SA.TicketCard.filterPanel(130, this)"';
64059		} else if (cssClass == 'card-late-cancel') {
64060			onclick += 'SA.TicketCard.filterPanel(140, this)"';
64061		
64062		} else if (cssClass == 'card-now') {
64063			onclick += 'SA.TicketCard.filterPanel(5, this)"';
64064		} else if (cssClass == 'card-late') {
64065			onclick += 'SA.TicketCard.filterPanel(29, this)"';
64066		} else if (cssClass == 'card-upcoming') {
64067			onclick += 'SA.Menu.openReportUpcomingAppointments(null, this)"';
64068		} else if (cssClass == 'card-past') {
64069			onclick += 'SA.TicketCard.filterPanel(90, this)"';
64070		}
64071    	
64072    	if (count > 0) {
64073    		return '<li class="' + cssClass + '" title="' + UTIL.cleanString(title) + '"' + onclick + '><b>' + UTIL.pluralLabel(count, label) + '</b></li>';
64074    	} else {
64075    		return '';
64076    	}
64077    }
64078    
64079    return _cTicketCard;
64080})();
64081
64082
64083SA.Kiosk = (function() {
64084    function _conKiosk() { }
64085    
64086    _conKiosk.init = function() {
64087    	if (innerWidth < 600 || !UTIL.parseBool($.cookies.get('kioskmode'))) { return; }
64088    	
64089    	GLO.Mobile.initKiosk();
64090    	
64091    	var dot = '<a class="nohover" style="display: inline-block; margin-top: -2px; border:none; font-size: 108%; font-family: Verdana;">&#9679;</a>';
64092    	var ft = $('#ft');
64093    	var ft_help = ft.find('li:first');
64094    	var ft_sa = ft.find('#footer-powered-by');
64095    	var css = '', color = ft.find('ul li a:last').css('color');
64096    	
64097    	if (!UTIL.isEmpty(color)) {
64098    		css = 'color: ' + color + ';';
64099    	}
64100    	
64101    	var aExit = '<a onclick="SA.Kiosk.exit()" tabindex="-1" title="' + SA.Resource.CloseWindow.toLowerCase() + '" style="' + css + '">' + SA.Resource.Exit + '</a>';
64102    	var li = '<li style="' + css + '">' + aExit + ' &#149; </li>';
64103    	
64104    	//GLO.Popup.Info.open('I Am here at Kiosk Init', 'Where are you?');
64105    	
64106    	if (ft.length == 0) {
64107			$('#pos-footer').addClass('iskiosk').find('#btnExitFooter').removeClass('hideX');
64108    		return;
64109    	}
64110    	
64111    	ft.find('ul').prepend(li);
64112    	
64113    	if (ft_sa.length) {
64114	    	var ft_sa_htm = ft_sa.html().replace('Powered by ', '');					//.replace('|', dot);
64115	    	ft_sa.remove();
64116	    	ft_help.prepend(ft_sa_htm);
64117    	}
64118    	
64119    	if (ft.width() < 300) {
64120    		ft.width(320);
64121    	}
64122    }
64123    
64124    _conKiosk.exit_DOES_NOT_WORK = function() {
64125    	var e = jQuery.Event("keydown");
64126	    e.keyCode = e.which = 115;       		//= F4.
64127	    e.altKey = true;
64128	    $(window).trigger(e);
64129    	
64130    	/*
64131    	var e = jQuery.Event("keypress");
64132		var e2 = $.extend({}, e, { which: 115, altKey: true });
64133		$(window).trigger(e2);
64134    	*/
64135    	
64136    	//setTimeout(SA.Kiosk.exit2, 900);
64137    }
64138    
64139    _conKiosk.exit = function() {
64140    	if (window.history.length === 1) {
64141    		window.close();
64142    	} else {
64143    		var msg1 = '<p>' + SA.Resource.Press + ' <b>ALT + F4</b> ' + SA.Resource.ExitConfirm + '</p>';
64144    		var msg2 = '<p style="margin: auto; margin-top: 12px; text-align: center;">(hold the <b>ALT</b> key + press the <b>F4</b> key)</p>';
64145    		var msg3 = '<p style="margin: auto; text-align: center; font-size: smaller;">(or hold the <b>ALT</b> + <b>FN</b> keys + press the <b>F4</b> key)</p>';
64146    		
64147    		var htm = '<div id="pop-info-kiosk-close">' + msg1 + msg2 + msg3 + '</div>';
64148    		var header = 'Instructions to Close ' + GLO.Info.getScheduleAnyoneHtm(true);
64149    		
64150    		GLO.Popup.Info.open(htm, header);
64151    	}
64152    }
64153	
64154	return _conKiosk;
64155})();
64156
64157
64158SA.Menu = (function() {
64159    function _conMenu() { }
64160    
64161    _conMenu.init = function() {
64162		$('#easySearch_text').focus(SA.Menu.activateSearch);
64163		_initMenuUrlActions();
64164	}
64165	
64166	function _initMenuUrlActions() {
64167    	var open = UTIL.cleanString(GLO.Uri.url('open')).toLowerCase();
64168    	
64169    	if (!UTIL.isEmpty(open)) {
64170    		if (open === 'main-menu-help') {
64171    			var step = GLO.Uri.url('step');
64172    			var icon = $('#header-sa-logo')[0];
64173    			
64174    			SA.Menu.openNewestFeatureHelp(icon, step);			//$('#hd .circle-spacer .morph-icon').click();
64175    		}
64176    	}
64177	}
64178	
64179	_conMenu.clickHeader = function(event, element, functionOrLink) {
64180		if (true || GLO.Info.isIPad) {
64181			var li = $(element).closest('li');
64182			
64183			if (li.hasClass('menu-is-open')) {
64184				li.removeClass('menu-is-open');
64185				$(window).off('click.closeHeaderMenu', SA.Menu.closeHeaderMenu);
64186			} else {
64187				$('#header-navigation-links li.menu-is-open').removeClass('menu-is-open');
64188				
64189				window.setTimeout(function() {
64190					li.addClass('menu-is-open');
64191					
64192					if ($('li.menu-is-open').length > 0) {
64193						$(window).on('click.closeHeaderMenu', SA.Menu.closeHeaderMenu);
64194					}
64195				}, 50);
64196			}
64197		} else {
64198			setTimeout(function() {
64199				document.location = functionOrLink;
64200			}, 200);
64201		}
64202	}
64203	
64204	_conMenu.closeHeaderMenu = function(event, li) {
64205		if (event) {
64206			var target = (event.target || event.srcElement || event.originalTarget);
64207		 	
64208		 	if ($(target).closest('.header-drop-menu').length > 0) {
64209		 		return;
64210		 	}
64211		 }
64212		
64213		$('li.menu-is-open').removeClass('menu-is-open');
64214		$(window).off('click.closeHeaderMenu', SA.Menu.closeHeaderMenu);
64215	}
64216	
64217	_conMenu.createClient = function() {
64218		//var fn = function(clientId, clientName, email, phone, isNewUser) { if (isNewUser) { new GLO.Popup.Success('Client Created'); } }
64219		GLO.Popup.Profile();
64220    }
64221    
64222    _conMenu.closeSearchOverlay = function() {
64223    	$('#search-overlay:visible').remove();
64224    }
64225    
64226    _conMenu.activateSearch = function() {
64227    	if ($('#search-overlay').length > 0) { return; }
64228    	if ($('.pop-black_overlay:visible').length > 0) { return; }			//glopop is open.
64229    	if ($('#pop-sa-keypad').closest('.glopop').length > 0) { return; }
64230    	
64231    	_displaySearchTipOverlay();
64232        UI.Keypad.openKeypadSearch('Search', GLO.Link.Object.Provider.UserSearch + '?include-inventory=1', 'sa-main-search');
64233    }
64234    function _displaySearchTipOverlay() {
64235    	if (UTIL.parseBool($.cookies.get('search-overlay-hide'))) { return false; }
64236    	
64237    	var css = '';
64238        if (GLO.Info.isMobile()) { css += ' width: ' + $(document).width() + ', height: ' + $(document).height() + ';'; }
64239    	
64240    	var overlay = '<div id="search-overlay" class="pop-black_overlay" style="' + css + '">' + _activateSearchHtm() + '</div>';
64241        $('body').append(overlay);
64242        
64243        var joverlay = $('#search-overlay').css('display', 'block');
64244        
64245        if ($('#staffFilter').length > 0) {
64246        	joverlay.css({ "top": "64px" });
64247        }
64248        
64249        setTimeout(function() {
64250	        $(window).bind('click.activateSearch, touchstart.activateSearch', function() {
64251	        	$('#search-overlay').remove();
64252	        	$(window).unbind('click.activateSearch, touchstart.activateSearch');
64253	        	
64254	        	if (event.target.id == 'search-overlay-hide' || event.target.id == 'Hide_Search_Overlay_fl') {
64255	        		SA.Menu.hideSearchOverlay();
64256	        	}
64257	        });
64258        }, 500);
64259        
64260        return true;
64261    }
64262    _conMenu.hideSearchOverlay = function() {
64263    	var dtExpire = new Date().addDays(180);
64264        
64265        UTIL.setCookieWithExpire('search-overlay-hide', '1', dtExpire);
64266    }
64267    function _getHideOverlayCheckbox() {
64268    	//if (GLO.Data && GLO.Data.provider && UTIL.isDate(GLO.Data.provider.last_payment_dt)) {
64269		var box = '<input type="checkbox" id="Hide_Search_Overlay_fl" onclick="SA.Menu.hideSearchOverlay(this)" onchange="SA.Menu.hideSearchOverlay(this)"/>';
64270		var label = '<label for="Hide_Search_Overlay_fl">Hide These Search Tips</label>';
64271		
64272		return '<div id="search-overlay-hide">' + box + label + '</div>';
64273    }
64274    function _activateSearchHtm() {
64275    	var closeIcon = '<a class="x-close-img sa-sprite" onclick="SA.Menu.closeSearchOverlay()" style="float: right; border-bottom: none;"></a>';
64276    	var msgStreet = '', msg = '<div>';
64277    	
64278    	if (GLO.Data && GLO.Data.provider && (GLO.Data.provider.new_client_address_cd > 14)) {		// || UTIL.isEmpty(GLO.Data.provider.relationship
64279    		msgStreet = '<li>' + SA.Resource.StreetAddress + '</li>';
64280    	}
64281    	
64282    	if (GLO.Info.providerPackage > 1 && GLO.Provider.isPaidAccount(true)) {
64283    		msg += SA.Resource.SearchHelp1;
64284    		
64285    		if (GLO.Info.providerPackage == 2) { msg += ' ' + SA.Resource.SearchHelp2; }
64286    	} else {
64287    		msg += SA.Resource.SearchHelp3;
64288    	}
64289    	
64290    	msg += '</div>';
64291    	msg += '<div id="search-overlay-message-line2">' + SA.Resource.SearchHelpBelow + '</div>';
64292    	
64293    	var forExample = '<small style="letter-spacing: 0;">' + SA.Resource.for_example_enter + '</small>';
64294    	var htm = '<div>'
64295	    			+ '<div id="search-overlay-header">' + SA.Resource.Search + closeIcon + '...</div>'
64296	    			+ _getHideOverlayCheckbox()
64297	    			+ '<div id="search-overlay-text">'
64298	    				+ '<div id="search-overlay-message">' + msg + '</div>'
64299	    				+ '<h5>' + SA.Resource.Client + '</h5>'
64300	    				+ '<ul>'
64301		    				+ '<li style="margin-bottom: 0;">' + SA.Resource.PhoneNumber + '</li>'
64302		    				+ '<li class="search-overlay-text2b search-phone-help">' + SA.Resource.PhoneWithAreaCode + '</li>'
64303		    				+ '<li class="search-overlay-text2b search-phone-help">' + SA.Resource.PhoneWithoutAreaCode + '</li>'
64304		    				+ '<li class="search-overlay-text2b search-phone-help">' + SA.Resource.PhoneLast4Digits + '</li>'
64305		    				+ msgStreet
64306		    				+ '<li>' + SA.Resource.FirstName + '</li>'
64307		    				+ '<li>' + SA.Resource.FullName + '</li>'
64308		    				+ '<li>' + SA.Resource.First2CharactersHelp + '</li>'
64309		    				+ '<li>' + SA.Resource.EmailAddress + '</li>'
64310		    			+ '</ul>'
64311		    			+ '<h5>' + SA.Resource.Ticket + '</h5>'
64312		    			+ '<ul> <li class="search-overlay-text">' + forExample + ' &quot;<b>P1</b>&quot;</li> </ul>';
64313	    
64314	    if (GLO.Info.providerPackage > 1 && GLO.Provider.isPaidAccount(true)) {
64315	    	htm += '<h5>Gift Card</h5> <ul id="gift-card-help"> <li>' + forExample + ' &quot;<b>#</b>GC1&quot; <i style="font-size: 12px;">( "#" + gift card number )</i></li> </ul>';
64316	    	
64317	    	if (GLO.Info.providerPackage == 2) {
64318	    		htm += '<h5>' + SA.Resource.Order + '</h5> <ul> <li class="search-overlay-text">' + forExample + ' &quot;<b>O1</b>&quot;<i style="font-size: 12px;">( "O" + order number )</i></li> </ul>';
64319	    	}
64320	    	
64321	    	htm += '<h5>' + SA.Resource.Product + '</h5> <ul>'
64322	    				+ '<li>' + SA.Resource.ProductName + '</li>'
64323	    				+ '<li>' + SA.Resource.Product + ' ' + SA.Resource.Brand + '</li>'
64324	    				+ '<li>' + SA.Resource.ProductType + '</li>'
64325	    				+ '<li>' + SA.Resource.ProductSku + '</li>'
64326	    				+ '<li>' + SA.Resource.ProductUPC + '</li>'
64327	    			+ '</ul>';
64328	    }
64329    	
64330    	return htm + '</div> </div>';
64331    }
64332    
64333    _conMenu.gotoContact = function(event, element) {
64334    	if (GLO.Info.isMobile(true)) {
64335    		if (GLO.Info.isMobile()) {
64336    			GLO.Mobile.Header.closeMenu();
64337    		}
64338    		
64339    		//GLO.UI.animate(2);
64340    	} else if (element) {
64341    		//$(element).addClass('is-loading');
64342    	}
64343    	
64344    	setTimeout(function() {
64345	    	SA.App.openContactSAPopup();
64346	    	
64347	    	/*
64348	    	var url = GLO.Link.WebsiteDomain + 'log/contact';
64349	    	
64350	    	if (typeof event != 'undefined' && event.ctrlKey) {
64351				UI.openChildWindow(url, '', true);
64352				
64353				if (element) { setTimeout(function() { $(element).removeClass('is-loading'); }, 2500); }
64354			} else {
64355	    		document.location = url;
64356	    	}
64357	    	*/
64358	    }, 200);
64359    }
64360    
64361    _conMenu.gotoInventory = function(event, element, url) {
64362    	var j = $('#manage-inventory');
64363    	
64364    	if (j.length > 0) {
64365    		if (GLO.Info.isMobile() && !GLO.Mobile.isTablet) {
64366    			GLO.Mobile.Header.closeMenu();
64367    		} else {
64368    			var test = url.toLowerCase();
64369    			
64370    			if (test.indexOf('order-create') !== -1) {
64371    				GLO.Inventory.gotoHash('order');
64372    			} else if (test.indexOf('order-list') !== -1) {
64373    				GLO.Inventory.gotoHash('order-list');
64374    			} else {
64375    				if (j.find('#inventory-table').find('tr').length > 20) {
64376    					GLO.Inventory.updateHash('product-list-intro');
64377    				} else {
64378    					GLO.Inventory.updateHash('product-list');
64379    				}
64380    			}
64381    		}
64382    		
64383    		$(element).addClass('is-loading');
64384			
64385			setTimeout(function() {
64386				$(element).removeClass('is-loading');
64387				SA.Menu.hideMenuTemporarily();
64388			}, 600);
64389    	} else {
64390    		return _conMenu.gotoReport(event, element, url, true);
64391    	}
64392    }
64393    
64394    _conMenu.gotoInventoryReports = function(event, element, url) {
64395    	var jTabContainer = $('#inventory-report-portal');
64396    	
64397    	if (jTabContainer.length > 0) {
64398    		if (GLO.Info.isMobile()) {
64399    			GLO.Mobile.Header.closeMenu();
64400    		} else {
64401    			$('#header-navigation-links .menu-is-open').removeClass('menu-is-open');
64402    			//document.location = url;			// document.location = document.location.protocol + '//' + document.location.host + url;
64403    			var test = url.toLowerCase();
64404    			
64405    			if (test.indexOf('product-history') !== -1) {
64406    				jTabContainer.find('#report-tab-product-history').click();
64407    			} else if (test.indexOf('order-and-restock') !== -1) {
64408    				jTabContainer.find('#report-tab-shipment-history').click();
64409    			} else if (test.indexOf('audit-history') !== -1) {
64410    				jTabContainer.find('#report-tab-audit-history').click();
64411    			} else {
64412    				jTabContainer.find('#report-tab-returns-exchanges').click();
64413    			}
64414    		}
64415    		
64416    		$(element).addClass('is-loading');
64417			
64418			setTimeout(function() {
64419				$(element).removeClass('is-loading');
64420				SA.Menu.hideMenuTemporarily();
64421			}, 600);
64422    	} else {
64423    		return _conMenu.gotoReport(event, element, url, true);
64424    	}
64425    }
64426    
64427    _conMenu.gotoPopularReport = function(event, element, url) {
64428    	var jTabContainer = $('#popular-report-portal');
64429    	
64430    	if (jTabContainer.length > 0) {
64431    		if (GLO.Info.isMobile()) {
64432    			GLO.Mobile.Header.closeMenu();
64433    		} else {
64434    			$('#header-navigation-links .menu-is-open').removeClass('menu-is-open');
64435    			//document.location = '/' + url;						// document.location = document.location.protocol + '//' + document.location.host + url;
64436    			var test = url.toLowerCase();
64437    			
64438    			if (test.indexOf('popular-services') !== -1) {
64439    				jTabContainer.find('#report-tab-popular-service').click();
64440    			} else {
64441    				jTabContainer.find('#report-tab-popular-product').click();
64442    			}
64443    			
64444    			$(element).addClass('is-loading');
64445    			
64446    			setTimeout(function() {
64447					$(element).removeClass('is-loading');
64448					SA.Menu.hideMenuTemporarily();
64449				}, 600);
64450    		}
64451    	} else {
64452    		return _conMenu.gotoReport(event, element, url, true);
64453    	}
64454    }
64455    
64456    _conMenu.gotoReportSimple = function(element, url) {
64457    	return _conMenu.gotoReport(event, element, url, true);
64458    }
64459    _conMenu.gotoReport2 = function(event, element, url) {
64460    	return _conMenu.gotoReport(event, element, url, true);
64461    }
64462    
64463    _conMenu.gotoReportConfirmed = function(url, isOpenChildWindow, element) {
64464    	var fnFinishLoad = function() {};
64465    	
64466    	if (GLO.Info.isMobile(true)) {
64467    		if (GLO.Info.isMobile()) {
64468    			GLO.Mobile.Header.closeMenu();
64469    		}
64470    		
64471    		GLO.UI.animate(2);
64472    	} else if (element) {
64473    		$(element).addClass('is-loading');
64474    		
64475    		if (_isSamePage(url)) {
64476    			fnFinishLoad = function() { setTimeout(function() {
64477    																$(element).removeClass('is-loading');
64478    																SA.Menu.hideMenuTemporarily();
64479    															  }, 900); };
64480    		} else {
64481    			fnFinishLoad = function() { setTimeout(function() { $(element).removeClass('is-loading'); }, 2500); };
64482    		}
64483    	}
64484    	
64485    	if (GLO.isPOS) {
64486    		url = GLO.Uri.addQueryKeyAndValue(url, 'helloback=pos');			//GLO.Uri.query('helloback', 'pos');
64487    	}
64488    	
64489    	setTimeout(function() {
64490	    	url = GLO.Link.WebsiteDomain + url;
64491	    	
64492	    	if (isOpenChildWindow) {
64493				UI.openChildWindow(url, '', true);
64494				fnFinishLoad();
64495			} else {
64496	    		document.location = url;
64497	    	}
64498	    }, 200);
64499    }
64500    function _getReportQueryString(url, ignoreQueryString) {
64501    	if (!ignoreQueryString) {
64502	    	var sfilter = GLO.Uri.query('sfilter');
64503	    	
64504	    	if ((UTIL.isEmpty(sfilter) && GLO.Info.isMobile() && GLO.Info.roleType < 219) || GLO.Info.roleType < 210) {
64505	    		sfilter = GLO.Info.StaffId;
64506	    	}
64507	    	
64508	    	if (!UTIL.isEmpty(sfilter)) {
64509	    		if (url.indexOf("?") !== -1) { url += '&'; } else { url += '?'; }
64510	    		url += 'sfilter=' + sfilter;
64511	    	}
64512    	}
64513    	
64514    	return url;
64515    }
64516    
64517    
64518    _conMenu.gotoReport = function(event, element, url, ignoreQueryString) {
64519    	url = _getReportQueryString(url, ignoreQueryString);
64520    	var isOpenChildWindow = (typeof event != 'undefined' && event.ctrlKey);
64521    	
64522    	if (!isOpenChildWindow) {
64523	    	var jpop = $(element).closest('.glopop');
64524	    	
64525	    	if (jpop.find('#pop-manager-report').length) {
64526	    		GLO.Popup.close(jpop);
64527	    	}
64528    	}
64529    	
64530    	if (_isRequirePIN()) {
64531    		_conMenu.openRequirePIN(url, isOpenChildWindow, element);
64532    	} else {
64533    		_conMenu.gotoReportConfirmed(url, isOpenChildWindow, element);
64534    	}
64535    }
64536    _conMenu.isRequirePIN = function(url, element, event, isPopup, header) {
64537    	if (_isRequirePIN()) {
64538    		if (GLO.Report.isReport(url)) {
64539    			if (UTIL.isEmpty($.cookies.get('pinsession'))) {
64540    				var isOpenChildWindow = (typeof event != 'undefined' && event.ctrlKey);
64541    				
64542    				_conMenu.openRequirePIN(url, isOpenChildWindow, element, isPopup, header);
64543    				return true;
64544    			}
64545    		}
64546    	}
64547    	
64548    	return false;
64549    }
64550    function _getUrl(uri) {
64551    	if (uri && uri.length > 3) {
64552			var test4 = uri.toLowerCase().substring(0,4);
64553			
64554			if (test4 !== 'http' && test4 !== 'www.') {
64555				if (uri.indexOf('/') !== 0) {
64556	    			uri = '/' + uri;
64557	    		}
64558				
64559				uri = GLO.Info.http + document.location.host + uri;
64560			}
64561		}
64562		
64563		return uri;
64564    }
64565    function _isRequirePIN() {
64566    	return (UTIL.coalesceInt(GLO.Info.roleTypeOriginal, GLO.Info.roleType) == 200 || (GLO.Data.Staff.role_report_cd > 199 && GLO.Data.Staff.role_report_cd < 249));
64567    }
64568    _conMenu.openRequirePIN = function(url, isOpenChildWindow, element, isOpenInPopup, message) {
64569    	var msg = '<p>Please Enter Password or PIN to View Report</p>';
64570    	
64571    	if (!UTIL.isEmpty(message)) {
64572    		msg += '<div class="pop-enter-pin-custom-message">' + message + '</div>';
64573    	}
64574    	
64575    	var input = '<div><input type="password" id="Pasword_Or_Pin_vc"/></div>';
64576    	var htm = '<div id="pop-require-pin" report_page_vc="' + url + '">' + msg + input + '</div>';
64577    	
64578    	var fnSave = function() {
64579    		SA.Menu.verifyPIN(url, isOpenChildWindow, element, isOpenInPopup);
64580    	};
64581    	
64582    	var ojpop = GLO.Popup.Custom.openSimple(htm, 'Enter Password or PIN', fnSave, null, true);
64583    	var jpop = ojpop.getPopup()
64584    	var cssYes = { "position": "absolute", "right": "8px", "width": "140px", "font-size": "16px" };
64585    	
64586    	jpop.find('.btnSave').attr('id', 'btnOpenReport').addClass('btnYes').addClass('btnAdd').removeClass('btnSave').css(cssYes).find('>a').text('Open Report');
64587    	jpop.find('.btnCancel').css({ "font-size": "16px" });
64588    	
64589    	ojpop.saveOnEnter();
64590    	SA.Menu.hideMenuTemporarily(true);
64591    }
64592    _conMenu.verifyPIN = function(url, isOpenChildWindow, element, isOpenInPopup) {
64593    	var jpop = $('#pop-require-pin').closest('.glopop');
64594    	var verifyUrl = GLO.Link.WebsiteDomain + 'provider/ajax/VerifyPasswordForReport';
64595    	
64596    	if (jpop.length) {
64597	    	var page = jpop.find('#pop-require-pin').attr('report_page_vc');
64598	    	var jpass = jpop.find('#Pasword_Or_Pin_vc');
64599	    	var pass = jpass.val();
64600	    	
64601	    	GLO.UI.Form.beginProcessing(jpop.find('#btnOpenReport'));
64602    	} else {
64603    		var jcontainer = $('#report-password-container');
64604    		var page = document.location.pathname.substring(1);
64605	    	var jpass = jcontainer.find('#Report_Password_vc');
64606	    	var pass = jpass.val();
64607	    	
64608	    	GLO.UI.Form.beginProcessing(jcontainer.find('.btnSearchWithReportPassword'));
64609    	}
64610		
64611        var jqxhr = $.ajax({ "type": "POST", "url": verifyUrl, "cache": false, "data": { "password": pass, "page": page } })
64612            .success(function(data, textStatus, jqXHR) {
64613                var jdata = $(data);
64614                var fnOk = function() {
64615                	jpass.focus();
64616                };
64617                
64618                if (!UTIL.isEmpty(jdata.attr('warning_cd')) || !UTIL.isEmpty(jdata.attr('error_cd'))) {
64619                	if (jpop.css('z-index') == 251001) {				// hideMenuTemporarily increases z-index
64620                		jpop.css('z-index', 5002);
64621                	}
64622                	
64623                	var htmWarn = '<div id="pop-warn-pin-not-accepted">' + jdata.html() + '</div>';
64624                	
64625                	GLO.Popup.closeIfExist($('#pop-warn-pin-not-accepted').closest('.glopop'));
64626                	GLO.UI.Form.resetProcessing();
64627                	
64628                	var jwarn = GLO.Popup.Warning.open(htmWarn, 'PIN Not Accepted', fnOk);
64629                	var jPopEnterPin = $('#pop-require-pin').closest('.glopop');
64630                	var zindex = jPopEnterPin.css('z-index');
64631                	
64632                	//if (jPopEnterPin.length && zindex > 0) { jwarn.getPopup().css('z-index', zindex); }
64633                } else if (!UTIL.isEmpty(jdata.attr('success_cd'))) {
64634                	url = _getUrl(url);		//var reportUrl = document.location.origin + page;
64635                	_completeLoadReport(url, isOpenChildWindow, isOpenInPopup, element, jdata, jpop);
64636                } else {
64637                	GLO.UI.Form.resetProcessing();
64638                	GLO.Popup.Warning.open('Unable to find this PIN or Password', 'Unable to Process PIN', fnOk);
64639                }
64640            })
64641            .error(function(jqXHR, textStatus, errorThrown) {
64642                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
64643            });
64644    }
64645    function _completeLoadReport(url, isOpenChildWindow, isOpenInPopup, element, jdata, jpop) {
64646    	var pinGuid = jdata.attr('pinsession');
64647        var dtExpire = new Date().addMinutes(5);
64648        
64649        //sessionStorage.setItem('pinsession', pinGuid);				//= think sessionStorage is a better solution, but to make it easier to implement to work with existing code for now use cookie mainly to check pinsession
64650        UTIL.setCookieWithExpire('pinsession', pinGuid, dtExpire);
64651        
64652        GLO.Popup.Success.open(jdata.html(), 'PIN / Password Accepted');
64653        
64654        setTimeout(function() {
64655        	if (isOpenChildWindow) {
64656        		GLO.Popup.closeIfExist(jpop);
64657        		UI.openChildWindow(url, 'Report', true);
64658        	} else if (isOpenInPopup) {
64659        		GLO.Popup.closeIfExist(jpop);
64660        		var pinGuid = $.cookies.get('pinsession');			//if staff just entered PIN in popup, then won't be in request cookie sent to server
64661        		
64662        		//if (pinGuid && UTIL.isEmpty(GLO.Uri.getQueryStringValueFromUrl('pinguid', url))) { url += '&pinguid=' + pinGuid; }
64663        		
64664        		if (url.toLowerCase().indexOf('report/payrolldays?') !== -1) {
64665        			var h1 = 'Payroll Today', popupId = 'report-payroll-days-full-page', msg = null, fnOnload = SA.POS.printTodayCommissionDisplay;
64666        		} else {
64667        			//must implement for other reports
64668        		}
64669        		
64670        		_openPopupReport(null, element, url, h1, popupId, msg, fnOnload);
64671        	} else if (document.location.href.toLowerCase() == url.toLowerCase()) {
64672        		location.reload();
64673        	} else {
64674        		document.location = url;
64675        	}
64676        }, 100);
64677    }
64678    
64679    function _isSamePage(url) {
64680    	if (url.indexOf('#') !== -1) {
64681    		url = url.substring(0, url.indexOf('#'));
64682    	}
64683    	
64684    	var newUrl = url.toLowerCase();
64685    	var currentUrl = document.location.href.replace(document.location.hash, '').toLowerCase();
64686    	
64687    	if (newUrl == currentUrl) {
64688    		return true;
64689    	} else {
64690    		return false;
64691    	}
64692    }
64693    
64694    _conMenu.hideMenuTemporarily = function(isPopup) {
64695    	var jmenu = $('#hd-reports-menu');
64696    	
64697    	if (isPopup && GLO.isPOS) {
64698			GLO.Popup.closeIfExist(jmenu.closest('.glopop'));
64699		} else if (isPopup) {
64700    		$('.msg').closest('.glopop').css({ "z-index": 251001 });
64701    		return;
64702    	} else {
64703	    	if (jmenu.find('li.menu-is-open').length > 0) {
64704	    		jmenu.find('li.menu-is-open').removeClass('menu-is-open');
64705	    	} else {
64706	    		jmenu.css({ "visibility": "hidden" });
64707	    		
64708	    		setTimeout(function() {
64709	    			$('#hd-reports-menu').css({ "visibility": "" });
64710	    		}, 1500);
64711			}
64712		}
64713    }
64714    
64715    _conMenu.clearPinSession = function() {
64716    	UTIL.setCookieWithExpire('pinsession', null);
64717        document.cookie = "pinsession=a1;expires=Thu, 01 Jan 1970 00:00:00 GMT";	//for some reason occasionally get duplicate cookie records, this line removes the duplicate!
64718    }
64719    
64720    _conMenu.openPopupReport = function(btn, url, h1, popupId, msg, fnOnload) {
64721    	_openPopupReport(null, btn, url, h1, popupId, msg, fnOnload);
64722    }
64723    function _openPopupReport(rowCount, btn, url, h1, popupId, msg, fnOnload) {
64724    	GLO.Popup.closeIfExist($('.popup-report').closest('.glopop'));
64725    	
64726    	if (UTIL.coalesceInt(rowCount, 0) > 0) {
64727    		url += '&rows=' + rowCount;
64728    	}
64729    	
64730    	url += '&search=1';
64731    	var throbber = UI.getBlueThrobber('margin: 32px auto;');
64732    	var htm = '<div id="' + popupId + '" class="popup-report"><div class="friendly-msg2" style="min-width: 280px; padding: 0 12px;">' + $.trim(msg) + throbber + '</div> </div>';
64733    	
64734    	var ojpop = GLO.Popup.Custom.openSimple(htm, h1, null, null, true);
64735        var jpop = ojpop.getPopup().css({ "padding-bottom": "0" });
64736        var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" });				//.addClass('pop-buttons2');
64737		//jbtns.find('.btnSave').remove();
64738		
64739		GLO.Popup.Custom.singleButton(jpop, 'Close');
64740		_conMenu.hideMenuTemporarily(true);
64741		GLO.UI.Form.beginProcessing($(btn));
64742		
64743    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
64744            .success(function(data, textStatus, jqXHR) {
64745                var htm = data;			//var htm = $.trim(msg) + data;
64746                jpop.addClass('quick-report').find('#' + popupId).html(htm);
64747                
64748                if (jpop.find('#enter-report-password').length) {
64749                	ojpop.close();
64750                	
64751                	if (!UTIL.isEmpty($.cookies.get('pinsession'))) {
64752                		GLO.Popup.Processing.open('Re-loading for Report Access...', h1);
64753                		GLO.Log.insertSimple('PIN Session in Browser but NOT Server', msg, 'warning');				//GLO.Log.processWarning(msg)
64754                		
64755                		setTimeout(function() {
64756                			location.reload();
64757                		}, 100);
64758                		
64759                		_conMenu.clearPinSession();
64760                		return;
64761                	}
64762                	
64763                	url = url.replace('&search=1', '');
64764                	_conMenu.openRequirePIN(url, false, btn, true, msg);
64765                	return;
64766                }
64767                
64768                jbtns.find('.btnCancel').addClass('btnOk').find('> a').css({ "margin": 0, "padding": "4px 8px 2px", "color": "#4F81BD" }).text(SA.Resource.Close).focus();
64769                jpop.find('#report-header-help-text').css({ "padding": "0 8px", "font-size": "" });
64770                
64771                if ($('.glopop').length === 1) {
64772                	jpop.css({ "z-index": "501" });
64773                	$('#pop-overlay1').css({ "z-index": "501" });
64774                }
64775                
64776                if (fnOnload) {
64777                	fnOnload(url);
64778                } else {
64779	                var jtbl = jpop.find('table.tablesorter:visible');
64780	                UI.initTableSorter(jtbl);
64781	                
64782	                GLO.Report.CellSummary.initReport(jtbl, true, true);
64783					GLO.Report.initIcons(jtbl);
64784					GLO.Report.TicketHistory.loadColumns(jtbl);
64785				}
64786				
64787				ojpop.realign();
64788				GLO.UI.Form.resetProcessing();
64789				
64790				setTimeout(ojpop.realign, 100);
64791            })
64792            .error(function(jqXHR, textStatus, errorThrown) {
64793                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
64794            });
64795    }
64796    _conMenu.openReportTicketHistory = function(rowCount, btn, apptStatus, payMethod) {
64797    	var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?';
64798    	var h1 = '', msg = '', msgSmall = '', popupId = 'pop-appt-ticket-history';
64799    	
64800    	if (!UTIL.isEmpty(apptStatus)) {
64801    		url = GLO.Uri.addQueryKeyAndValue(url, 'appt-status=' + apptStatus);
64802    		
64803    		if (apptStatus == 13) {
64804    			h1 = SA.Resource.NoShow;
64805    			msg = 'No Show';
64806    			msgSmall = 'client missed their appointment';
64807    		} else if (apptStatus == 14) {
64808    			h1 = 'Late Cancellation';
64809    			msg = 'Late Cancel';
64810    			msgSmall = 'Client cancelled appointment at the last minute';
64811    		} else if (apptStatus == 21) {
64812		    	h1 = SA.Resource.CheckIn_dash;
64813		    	popupId = 'pop-appt-checkedin';
64814		    	msg = 'Tickets where the client is currently On-Site';
64815		    	msgSmall = '(ticket is checked-in but not yet checked-out)';
64816	    	} else if (apptStatus == 22) {
64817	    		h1 = SA.Resource.CheckOut_dash;
64818	    		popupId = 'pop-appt-checkedout';
64819		    	msg = 'Completed Ticket';
64820		    	msgSmall = '(ticket is checked-out)';
64821	    	}
64822    	}
64823    	
64824    	if (!UTIL.isEmpty(payMethod)) {
64825    		url = GLO.Uri.addQueryKeyAndValue(url, 'pay-method=' + payMethod);
64826    		var msgPay = UserPortal.Price.paymentMethodLabel(payMethod);
64827    		
64828    		if (!UTIL.isEmpty(h1)) {
64829    			msg += ' | and ' + msgPay;
64830    		} else {
64831    			h1 = UserPortal.Price.paymentMethodLabel(payMethod);
64832    			msg = msgPay;
64833    		}
64834    	}
64835    	
64836    	var msgClick = '<p> <small>click date to open ticket</small> </p>';
64837    	var htm = '<p>' + msg + '<small style="white-space: nowrap; letter-spacing: 0;">' + msgSmall + '</small></p>' + msgClick;
64838    	
64839    	_openPopupReport(rowCount, btn, url, h1, popupId, htm);
64840    }
64841    _conMenu.openReportCheckedIn = function(rowCount, btn) {
64842    	GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop'));
64843    	
64844    	var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?appt-status=21';
64845    	var popupId = 'pop-appt-checkedin';
64846    	
64847    	var headerLeft = '<a class="quietest quietest-left" onclick="SA.Me
64847nu.openReportCheckedOut(' + rowCount + ', this)" style="margin: 0; font-stretch: condensed;">Checked-Out</a>';
64848    	var h1 = headerLeft + '<b>Checked-In</b>';			//SA.Resource.CheckIn_dash;
64849    	
64850    	var msg1 = '<p>Tickets where the client is currently On-Site <small style="white-space: nowrap; letter-spacing: 0;">( ticket is checked-in but not yet checked-out )</small> </p>';
64851    	var msg2 = '<div> <small>click date to open ticket</small> </div>';
64852    	var msg = msg1 + msg2;
64853    	
64854    	_openPopupReport(rowCount, btn, url, h1, popupId, msg);
64855    }
64856    _conMenu.openReportCheckedOut = function(rowCount, btn) {
64857    	GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop'));
64858    	
64859    	var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?appt-status=22';
64860    	var popupId = 'pop-appt-checkedin';
64861    	
64862    	var headerLeft = '<a class="quietest quietest-left" onclick="SA.Menu.openReportCheckedIn(' + rowCount + ', this)" style="margin: 0; font-stretch: condensed;">Checked-In</a>';
64863    	var h1 = headerLeft + '<b>Checked-Out</b>';
64864    	
64865    	var msg1 = '<p>Tickets where the client is currently On-Site <small style="white-space: nowrap; letter-spacing: 0;">( ticket is checked-in but not yet checked-out )</small> </p>';
64866    	var msg2 = '<div> <small>click date to open ticket</small> </div>';
64867    	var msg = msg1 + msg2;
64868    	
64869    	_openPopupReport(rowCount, btn, url, h1, popupId, msg);
64870    }
64871    _conMenu.openReportUpcomingAppointments = function(rowCount, btn, eventCode, htmHeader) {
64872    	GLO.Popup.closeIfExist($('#pop-manager-report').closest('.glopop'));
64873    	
64874    	var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?appt-status=11';
64875    	var popupId = 'pop-appt-upcoming';
64876    	
64877    	var headerLeft = '<a class="quietest quietest-left" onclick="GLO.Uri.gotoUriWithSpinner(\'provider/calendar\', this, event, true)" style="margin: 0;">Calendar</a>';
64878    	var h1 = headerLeft + '<b>Upcoming Appointments Today</b>';
64879    	
64880    	var msg1 = '<p>Upcoming Appointments Scheduled Today <small style="white-space: nowrap; letter-spacing: 0;">(and not checked-in, checked-out, or marked as a no-show)</small></p>';
64881    	var msg2 = '<div> <small>click date to open ticket</small> </div>';
64882    	var msg = msg1 + msg2;
64883    	
64884    	_openPopupReport(rowCount, btn, url, h1, popupId, msg);
64885    }
64886    _conMenu.openReportRecent = function(rowCount, btn) {
64887    	var jpos = $('#pos-container');
64888    	
64889    	if (jpos.hasClass('services')) {
64890    		SA.Menu.recentApptEdits(rowCount, btn);
64891    	} else {
64892    		SA.Menu.recentSales(rowCount, null, null, btn);
64893    	}
64894    	
64895    	//GLO.UI.Form.beginProcessing($(btn));
64896    }
64897
64898	_conMenu.printTodaySales = function(event, element) {
64899		GLO.Report.Sales.printByReceptionistFromMenu();
64900    }
64901
64902    _conMenu.recentSales = function(rowCount, eventCode, htmHeader, btn) {
64903    	GLO.Popup.closeIfExist($('.appt-list-sheet, .popup-report').closest('.glopop'));
64904    	
64905    	var url = 'reports/saleshistory?isfullpage=1&paymethod=0&start=' + new Date().toGloDate();
64906    	
64907    	if (GLO.isPOS) {
64908    		url += '&helloback=pos';
64909    	}
64910    	
64911    	var rptLinkRight = 'GLO.Report.CellSummary.gotoReport(\'' + url + '\', this, event)';
64912    	
64913    	if (eventCode > 0) {
64914    		var url = GLO.Link.WebsiteDomain + 'report/TicketHistory?isrecentsale=1&search=1&eventcode=' + eventCode + '&rows=' + UTIL.coalesceInt(rowCount, 10);
64915    		var rptLinkLeft = 'SA.Menu.recentSales(' + rowCount + ', null, null, this)';
64916    		var rptLabel = 'Sales';
64917    	} else {
64918    		var url = GLO.Link.WebsiteDomain + 'report/RecentSales?rows=' + UTIL.coalesceInt(rowCount, 10);
64919    		var rptLinkLeft = 'SA.Menu.recentApptEdits(' + rowCount + ', this)';
64920    		var rptLabel = 'Appointments';
64921    	}
64922    	
64923    	if (innerWidth > 979) {
64924    		rptLinkLeft = '<a class="quietest quietest-left" onclick="' + rptLinkLeft + '"><span>Recent </span>' + rptLabel + '</a>';
64925    		
64926    		if (GLO.Info.roleType == 200) {
64927    			rptLinkRight = '';
64928    		} else {
64929    			rptLinkRight = '<a class="quietest quietest-right" onclick="' + rptLinkRight + '"><span>Payments </span>Today</a>';
64930    		}
64931    	} else {
64932    		rptLinkLeft = rptLinkRight = '';
64933    	}
64934    	
64935    	var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + UI.getBlueThrobber('margin: 120px auto;') + '</div>';
64936    	var h1Label = '<b id="report-recent-popup-header-inner">' + SA.Resource.RecentSales + '</b>';
64937    	var h1 = '<h1 id="report-recent-popup-header" class="friendly-msg2">' + rptLinkLeft + h1Label + rptLinkRight + '</h1>';
64938    	var htm = $('<div id="pop-recent-sales" class="popup-report">' + h1 + '<div>' + throbber + '</div></div>');
64939        
64940        var ojpop = new GLO.Popup.Custom(htm);
64941        var jpop = ojpop.getPopup().addClass('no-persist').css({ "padding-bottom": "0" });
64942		var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" });				//.addClass('pop-buttons2');
64943		GLO.Popup.Custom.singleButton(jpop, 'Close');
64944		
64945		jbtns.find('.btnSave').remove();
64946		_conMenu.hideMenuTemporarily(true);
64947		GLO.UI.Form.beginProcessing($(btn));
64948		
64949		var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
64950            .success(function(data, textStatus, jqXHR) {
64951                jbtns.find('.btnCancel').addClass('btnOk').find('> a').css({ "margin": 0, "padding": "4px 8px 2px", "color": "#4F81BD" }).text(SA.Resource.Close).focus();
64952                
64953                var htm = $.trim(htmHeader) + data;
64954                
64955                jpop.addClass('quick-report').find('#pop-recent-sales').html(htm);
64956                
64957                if (true || !GLO.isPOS) {
64958                	jpop.css({ "z-index": "501" });
64959                	$('.pop-black_overlay').css({ "z-index": "501" });
64960                }
64961                
64962                var jtbl = jpop.find('table.tablesorter:visible');
64963                UI.initTableSorter(jtbl);
64964                
64965                GLO.Report.CellSummary.initReport(jtbl, true, true);
64966				GLO.Report.initIcons(jtbl);
64967				GLO.Report.TicketHistory.loadColumns(jtbl);
64968				ojpop.realign();
64969				GLO.UI.Form.resetProcessing();
64970            })
64971            .error(function(jqXHR, textStatus, errorThrown) {
64972                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
64973            });
64974    }
64975    
64976    _conMenu.recentApptEdits = function(rowCount, btn) {
64977    	GLO.Popup.closeIfExist($('.appt-list-sheet, .popup-report').closest('.glopop'));
64978    	
64979    	var url = GLO.Link.Page.Provider.Home + 'report/RecentApptEdit?rows=' + UTIL.coalesceInt(rowCount, 10);
64980    	var urlActivity = 'provider/apptportal';
64981    	
64982    	if (GLO.isPOS) {
64983    		urlActivity += '?helloback=pos';
64984    	}
64985    	
64986    	var rptLinkLeft = 'SA.Menu.recentSales(' + rowCount + ', null, null, this)';
64987    	var rptLinkRight = 'GLO.Uri.gotoUriWithSpinner(\'' + urlActivity + '\', this, event, true)';
64988    	
64989    	if (innerWidth > 979) {
64990    		rptLinkLeft = '<a class="quietest quietest-left" onclick="' + rptLinkLeft + '"><span>Recent </span>Sales</a>';
64991    		
64992    		if (GLO.Data.Staff.defaultScreenOnly) {
64993    			rptLinkRight = '';
64994    		} else {
64995    			rptLinkRight = '<a class="quietest quietest-right" onclick="' + rptLinkRight + '">All Activity</a>';
64996    		}
64997    	} else {
64998    		rptLinkLeft = rptLinkRight = '';
64999    	}
65000    	
65001    	var throbber = '<div class="friendly-msg2" style="min-width: 300px;">' + UI.getBlueThrobber('margin: 120px auto;') + '</div>';
65002    	//var throbber = $('.loadingDiv').clone().find('img').css({"margin": "120px auto"}).outerHTML();
65003    	var h1Label = '<b id="report-recent-popup-header-inner">' + SA.Resource.RecentAppointmentUpdates + '</b>';
65004    	var h1 = '<h1 id="report-recent-popup-header" class="friendly-msg2">' + rptLinkLeft + h1Label + rptLinkRight + '</h1>';
65005    	var htm = $('<div class="friendly-msg2" style="min-width: 300px;">' + h1 + '<div>' + UI.getBlueThrobber('margin: 120px auto;') + '</div></div>');
65006        
65007        var ojpop = new GLO.Popup.Custom(htm);
65008        var jpop = ojpop.getPopup().addClass('no-persist');
65009		var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" });				//.addClass('pop-buttons2');
65010		jbtns.find('.btnSave').remove();
65011		GLO.Popup.Custom.singleButton(jpop, 'Close');
65012		
65013		_conMenu.hideMenuTemporarily(true);
65014		GLO.UI.Form.beginProcessing($(btn));
65015		
65016    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
65017            .success(function(data, textStatus, jqXHR) {
65018                jbtns.find('.btnCancel').addClass('btnOk').find('> a').css({ "margin": 0, "padding": "4px 8px 2px", "color": "#4F81BD" }).text(SA.Resource.Close);
65019                jpop.addClass('quick-report').find('.msg').html(data);
65020                jpop.find('.appt-list-search, .appt-list-line').remove();
65021                
65022                if (!GLO.isPOS) {
65023                	jpop.css({ "z-index": "501" });
65024                	$('#pop-overlay1').css({ "z-index": "501" });
65025                }
65026                
65027                UI.initTableSorter( jpop.find('table.tablesorter:visible') );
65028                ojpop.realign();
65029                GLO.UI.Form.resetProcessing();
65030            })
65031            .error(function(jqXHR, textStatus, errorThrown) {
65032                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65033            });
65034    }
65035    
65036    _conMenu.print = function() {
65037    	if (GLO.Calendar !== undefined) {
65038    		UserPortal.Calendar.beforePrint();
65039    	} else if ($('#report-sales-history').length > 0) {
65040    		GLO.Report.Sales.printScreen();
65041    	} else {
65042    		UI.Print.printOnDevice();
65043    	}
65044    }
65045    
65046    function _openLoadingReportHelpPopup() {
65047    	var htmGreen = '<span style="font-weight: bold; letter-spacing: 0;
65047 font-family: Verdana, Tahoma, Helvetica;  color: rgb(20,240,80) !important;">Green</span>';
65048    	var msg1 = '<p style="color: #444;">Start with the reports highlighted in ' + htmGreen + ' on the <a onclick="SA.Menu.openReportMenu()">Reports</a> menu</p>';
65049    	var msg2 = '<p style="margin-top: 28px; margin-bottom: 0;">All reports in <span class="sa-brand"><i>Schedule</i><b>Anyone</b></span> are interactive</p>'
65050    	var ul = '<ul style="margin: 0; margin-left: 16px; margin-bottom: 8px;">'
65051	                + '<li>Press any value in the report for more information</li>'
65052	                + '<li>Press any report header to sort by that column</li>'
65053	                + '<li>'
65054	                    + '<span class="help-icon-text">For help, press a blue question mark on the report<b>&#10132;</b></span>'
65055	                    + '<span class="help-icon-parent"> <span class="helpIcon2 sa-sprite" onclick="GLO.Provider.Advanced.Help.openAboutQuestionMark()"></span> </span>'
65056	                + '</li>'
65057	            + '</ul>';
65058    	var blueThrobber = '<div class="blue-throbber"><img id="imgThrobber" src="' + GLO.Data.cdnDirectory + 'image/icon/throbber-blue.gif" style="height: 64px; margin: 32px;"/></div>';
65059    	var htm = '<div>' + msg1 + msg2 + ul + blueThrobber + '</div>';
65060    	var ojpop = GLO.Popup.Processing.open(htm, 'Loading Report Help');
65061    	
65062    	ojpop.getPopup().attr('id', 'pop-processing-loading-report-help');
65063    	return ojpop;
65064    }
65065    
65066    _conMenu.openReportHelp = function(step) {
65067    	var jhelp = $('#help-report-overview');
65068    	step = UTIL.coalesceInt(step, 0);
65069    	
65070    	if (jhelp.length) {
65071    		_conMenu.openReportHelp2(step);
65072    		return;
65073    	}
65074    	
65075    	var url = GLO.Link.WebsiteDomain + 'info/ReportHelp';
65076    	var ojLoading = _openLoadingReportHelpPopup();
65077    	
65078    	var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
65079            .success(function(data, textStatus, jqXHR) {
65080                ojLoading.close();
65081                var jcontainer = $('#staff-popups');
65082                
65083                if (jcontainer.length) {
65084                	jcontainer.append(data);
65085                } else {
65086                	$('body').append('<div class="hideX">' + data + '</div>');
65087                }
65088                
65089                _conMenu.openReportHelp2(step);
65090            })
65091            .error(function(jqXHR, textStatus, errorThrown) {
65092                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65093            });
65094    }
65095    
65096    _conMenu.openReportHelp2 = function(stepNumber, popid) {
65097    	var ojpop = SA.Help.openReportHelp('#help-report-overview', stepNumber, 'info/ReportHelp');
65098    	
65099    	_conMenu.hideMenuTemporarily(true);
65100    }
65101    
65102    _conMenu.toggleReportMenu = function() {
65103    	$('#hd-reports-menu-text').click();
65104    }
65105    _conMenu.openReportMenu = function() {
65106    	$('#hd #hd-reports-menu.header-drop-menu-trigger > li').addClass('menu-is-open');
65107    	GLO.Popup.close($('#sa-message').closest('.glopop'));
65108    }
65109    
65110    function _openLoading(subject) {
65111    	var throbber = $('.loadingDiv').clone().find('img').css({"margin": "40px auto"}).outerHTML();
65112    	
65113    	var h1 = '<h1>' + UTIL.coalesce(subject, 'New Features') + '</h1>';
65114    	var msg = '<div style="padding: 4px 20px;">Loading New Feature Overview...</div>';
65115    	var htm = $('<div>' + h1 + '<div class="friendly-msg2" style="min-width: 240px;">' + msg + throbber + '</div> </div>');
65116        
65117        var ojpop = new GLO.Popup.Custom(htm);
65118        var jpop = ojpop.getPopup().addClass('no-persist');
65119		var jbtns = jpop.find('.pop-buttons').css({ "width": "80px", "margin": "auto", "letter-spacing": "1px" });				//.addClass('pop-buttons2');
65120		jbtns.find('.btnSave').remove();
65121		return ojpop;
65122    }
65123    
65124    _conMenu.openNewestFeatureHelp = function(icon, stepNumber) {		//SA.Help.openMtoHelp('report-version3-1', 'New Feature: Interactive Reports');
65125    	var jicon = $(icon).parent().find('.morph-icon');				//.parent() because may have clicked on '.help-indicator'
65126    	jicon.parent().find('.help-indicator').remove();				//do NOT need indicator displayed after open (indicator there so user opens)
65127    	jicon.parent().find('#main-header-help').remove();				//ensures not loaded multiple times
65128		
65129		var ojThrob = _openLoading();		//GLO.Popup.Processing.open('<div style="padding: 4px 20px;">Loading New Feature Overview...</div>', 'New Features');
65130		var url = GLO.Link.WebsiteDomain + 'log/NewFeatures';
65131		
65132		if (GLO.Info.isMobile()) { GLO.Mobile.Header.closeMenu(); }
65133		
65134		var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
65135            .success(function(data, textStatus, jqXHR) {
65136                ojThrob.close();
65137                stepNumber = UTIL.coalesceInt(stepNumber, $(data).find('.wizard-step').length - 1);
65138                data = _addSaHeader(data);
65139                
65140                if (GLO.Info.isMobile()) {
65141                	SA.Help.openReportHelpAsMorph('#main-header-help', stepNumber, data);
65142                } else {
65143	                jicon.removeAttr('onclick');					//using same icon to load help + open morph popup (this is NOT required by morph popup - just doing in this instance)
65144	                jicon.parent().append(data);					//must load help data in same parent as icon (so have effect where popup morphs in/out of icon)
65145	                
65146	                var mp = new UI.MorphPopup('#main-header-help', null, null, { "visibleIcon": true, "stepNumber": stepNumber });
65147	                jicon.click();
65148                }
65149            })
65150            .error(function(jqXHR, textStatus, errorThrown) {
65151                //GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65152            });
65153    }
65154    function _addSaHeader(data) {
65155    	var logoPrefix = UTIL.coalesceString(GLO.Data.VAR.prefix_vc, '');
65156    	var sa = '<img class="sa-logo" src="' + GLO.Data.cdnDirectory + 'image/marketing/logo/' + logoPrefix + 'logo.png"/>';
65157        
65158        if (!GLO.Info.isMobile()) {
65159        	sa += ' ' + GLO.Info.getScheduleAnyoneHtm(true);
65160        }
65161        
65162        var htmSaHeader = '<span id="main-help-last-step-top"> <b class="sa-brand-header">' + sa + '</b> <b class="help-new-features">New Features</b></span>';
65163        var jd = $(data);
65164        var jsteps = jd.find('.wizard-step');
65165        
65166        for (var i=0; i < jsteps.length; i++) {
65167        	var h1 = jsteps.eq(i).find('> h1');
65168        	var height = UTIL.coalesceInt(jsteps.eq(i).attr('height')) + 34;
65169        	
65170        	jsteps.eq(i).attr('height', height);
65171        	h1.css({ "padding": 0 }).html(htmSaHeader + '<span id="main-help-last-step-header-text">' + h1.html() + '</span>');
65172        }
65173        
65174        return jd.outerHTML();
65175    }
65176    
65177    return _conMenu;
65178})();
65179
65180
65181GLO.RequestApptSetting = (function() {
65182	function _cRequestApptSetting() { }
65183	
65184	_cRequestApptSetting.init = function() {
65185		var j = $('#request-appt-setting');
65186		var jBtnSave = $('#wizBody').find('.btnSave > a');
65187		GLO.UI.initSaveButton(j, jBtnSave);
65188		
65189		var jCustomPopup = $("#request-appt-setting .sa-text-editor");
65190		SA.TextEditor.init(jCustomPopup, 'Custom Popup');
65191		/*
65192		jCustomPopup.focusout(function() {
65193	        var element = $(this);
65194	        
65195	        if (!element.text().trim().length) {
65196	            element.empty();
65197	        }
65198	    });
65199	    */
65200	    _initRequestApptUrl();
65201	}
65202	function _initRequestApptUrl() {
65203		var highlight = UTIL.cleanString(GLO.Uri.url('highlight'));
65204		
65205		if (!UTIL.isEmpty(highlight)) {
65206			var jhigh = $('#' + highlight);
65207    		
65208    		if (jhigh.length) {
65209    			UI.highlight(jhigh, 100, 9500, true);
65210    			return true;
65211    		}
65212		}
65213	}
65214	
65215	_cRequestApptSetting.save = function() {
65216		var url = GLO.Link.Page.Provider.WebTemplate + 'RequestApptSetting';
65217		var j = $('#request-appt-setting');
65218		var jsave = $('#wizBody').find('.btnSave > a');
65219		
65220		var requireDT = j.find('#Require_DateTime_fl').prop('checked');
65221		var requireNote = j.find('#Require_Note_fl').prop('checked');
65222		var requireService = j.find('#Require_Service_fl').prop('checked');
65223		var allowOffDay = j.find('#Allow_OffDay_fl').prop('checked');
65224		var isAllowImageUpload = j.find('#Allow_Image_Upload_fl').prop('checked');
65225		
65226		var isDisplayPrice = j.find('#Display_Price_fl').prop('checked');
65227		var isRequireCardOnFile = j.find('#Require_CardOnFile_fl').prop('checked');
65228		var requireCardOnFileMin = j.find('#Require_CardOnFile_mn').val();
65229		
65230		var noteLabel = UTIL.htmlEncode2(j.find('#Note_Label_vc').val());
65231		var popupHtm = j.find('#request-appt-popup-note .sa-text-editor')[0].innerHTML;
65232		var popupWhen = j.find('#Request_Appt_Popup_cd').val();
65233		var jbookEvery = j.find('#Book_Every_cd');
65234		var currentBookEvery = jbookEvery.attr('current_book_every_cd'), newBookEvery = jbookEvery.val();
65235		
65236		if (!UTIL.isEmpty(popupHtm)) {
65237			popupHtm = UTIL.htmlEncode(DOMPurify.sanitize(popupHtm));
65238		}
65239		
65240		var jd = { "require_datetime_fl": requireDT, "require_note_fl": requireNote, "require_service_fl": requireService, "allow_offday_fl": allowOffDay
65241					, "require_cof_fl": isRequireCardOnFile, "display_price_fl": isDisplayPrice, "allow_image_upload_fl": isAllowImageUpload
65242					, "note_label_vc": noteLabel, "popup_vcm": popupHtm, "popup_when_cd": popupWhen
65243					, "current_book_every_cd": currentBookEvery, "new_book_every_cd": newBookEvery };
65244		
65245		if (isRequireCardOnFile) {
65246			jd.require_cof_mn = UTIL.coalesceMoney(requireCardOnFileMin, 0);
65247		}
65248		
65249		GLO.UI.Form.beginProcessing(jsave);
65250		
65251        var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, data: jd })
65252            .success(function(data, textStatus, jqXHR) {
65253                GLO.UI.Form.resetProcessing();
65254                
65255                jsave.removeClass('unsaved');
65256                jbookEvery.attr('current_book_every_cd', newBookEvery);
65257                
65258                new GLO.Popup.Success(SA.Resource.ChangesSaved);
65259            })
65260            .error(function(jqXHR, textStatus, errorThrown) {
65261                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65262            });
65263	}
65264	
65265	return _cRequestApptSetting;
65266})();
65267
65268SA.TimecardManager = (function() {
65269	function _cTimecardManager() { }
65270	var _lastRowId = 0;
65271	
65272	_cTimecardManager.init = function() {
65273		var jmanager = $('#timecard-manager');
65274		var jstart = jmanager.find('.Begin_dt'), jend = jmanager.find('.End_dt');
65275		
65276		_loadStaffList(jmanager);
65277		
65278		jstart.datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
65279						, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker });			//, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1
65280		jend.datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
65281						, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker });			//, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1
65282		
65283		_initFromUrl(jmanager);
65284		_initBreaktimeSetting(jmanager);
65285		jmanager.find('.btnSearch > a').click();
65286	}
65287	function _initBreaktimeSetting(jmanager) {
65288		var jClockHr = jmanager.find('#Timecard_Require_Break_After_Hour_sr');
65289		var jBreakMin = jmanager.find('#Timecard_Require_Break_Minute_sr');
65290		
65291		_initSetting(jClockHr);
65292		_initSetting(jBreakMin);
65293	}
65294	function _initSetting(jfield) {
65295		var uriSave = GLO.Link.WebsiteDomain + 'provider/manage/AdvancedFields';
65296		var fnAfterSave = function() { GLO.Provider.Advanced.afterSaveFieldText(jfield); };
65297		new UI.AutoSave(jfield, uriSave, fnAfterSave, 2800);
65298	}
65299	function _initFromUrl(jmanager) {
65300		var staff = GLO.Uri.url('staff'), service = GLO.Uri.url('service'), start = GLO.Uri.url('start'), end = GLO.Uri.url('end');
65301		var jstaff = jmanager.find('#Timecard_Staff_id');
65302		var jstart = jmanager.find('.Begin_dt');
65303		var jend = jmanager.find('.End_dt');
65304		
65305		if (!UTIL.isEmpty(staff)) {
65306			jstaff.val(staff).change();
65307		} else {
65308			jstaff.find('option:first').prop('selected', true).change();
65309		}
65310		
65311		if (!UTIL.isEmpty(service)) {
65312			jmanager.find('#Timecard_Service_id').val(service);
65313		}
65314		
65315		if (UTIL.isEmpty(start)) {
65316			if (!UTIL.isEmpty(jstaff.val())) {
65317				start = new Date( (new Date().getMonth() + 1) + '/1/' + new Date().getFullYear()).toGloDate();
65318			} else {
65319				start = new Date().addDays(-7).toGloDate();
65320			}
65321		}
65322		
65323		if (UTIL.isEmpty(end)) {
65324			end = new Date().toGloDate();
65325		}
65326		
65327		jstart.val(start);
65328		jend.val(end);
65329	}
65330	function _loadStaffList(jmanager, staffId) {
65331		var sids = UserPortal.getStaffWhoDoInternalService();
65332        var optionList = '';
65333        
65334    	if (sids.length > 0) {
65335	        for (var i=0; i < sids.length; i++) {
65336	        	optionList += '<option value="' + sids[i] + '">' + UserPortal.getStaffName(sids[i]) + '</option>';
65337	       	}
65338	       	
65339	       	jmanager.find('#Timecard_Staff_id').replaceWith('<select id="Timecard_Staff_id" class="timecard-staff-dd" onchange="SA.TimecardManager.changeStaff(this)">' + optionList + '</select>');
65340	       	
65341	       	jmanager.find('#Timecard_Staff_id').html(jmanager.find('#Timecard_Staff_id').find('option').sort(function (a, b) {
65342			    return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
65343			}));
65344			
65345			jmanager.find('#Timecard_Staff_id').prepend('<option value="">Select Person</option>');
65346	    } else {
65347	    	var aReportCommission = '<a onclick="GLO.Uri.gotoUriWithSpinner(\'provider/manage/CommissionByStaffService\', this, event, true)">Payroll Setup</a>';
65348	    	var msg1 = '<p>No Staff assigned to an <b class="narrow-text">Employee Service</b> to <b class="narrow-text">Clock-In/Out</b></p>';
65349	    	var msg2 = '<p>To create timecards please go to the ' + aReportCommission + ' to assign each staff a wage and to which service(s) each staff can clock-in</p>';
65350	    	
65351	    	jmanager.find('#timecard-manager-search').after('<div id="timecard-manager-no-staff">' + msg1 + msg2 + '</div>');
65352	    	jmanager.find('#Timecard_Staff_id').remove();
65353	    }
65354	}
65355	
65356	_cTimecardManager.checkAll = function(element) {
65357		GLO.Message.Bulk.checkAll2(element, '#timecard-list > tbody');
65358	}
65359	
65360	_cTimecardManager.changeDay = function(element) {
65361		var jin = $(element).closest('tr').find('.clockin-time');
65362		
65363		if (UTIL.isEmpty(jin.val())) {
65364			jin.focus();
65365		}
65366	}
65367	_cTimecardManager.changeTime = function(element, isClockIn) {
65368		var tr = $(element).closest('tr');
65369		var tmIn = tr.find('.clockin-time').val();
65370		var tmOut = tr.find('.clockout-time').val();
65371		
65372		if (UTIL.isValidTime(tmIn) && UTIL.isValidTime(tmOut)) {
65373			var srIn = UTIL.timeToInt(tmIn), srOut = UTIL.timeToInt(tmOut);
65374			var diffMin = srOut - srIn;
65375			
65376			if (diffMin > 0) {
65377				var breakTimeMin = UTIL.coalesceInt($('#Timecard_Require_Break_Minute_sr').val(), 0);
65378				var hrForBreak = UTIL.coalesceInt($('#Timecard_Require_Break_After_Hour_sr').val(), 0);
65379				
65380				if (breakTimeMin > 0 && hrForBreak > 0 && diffMin >= hrForBreak * 60) {
65381					tr.find('.tc-column-break-time').text(breakTimeMin + ' minutes');
65382				} else {
65383					breakTimeMin = 0;
65384					tr.find('.tc-column-break-time').text('');
65385				}
65386				
65387				diffMin -= breakTimeMin;
65388				var diffMinNice = UTIL.pluralLabel(UTIL.coalesceMoney(diffMin/60), 'hr');
65389				var diffMinTitle = UTIL.pluralLabel(parseInt(diffMin/60), 'hour') + ' ' + UTIL.pluralLabel(diffMin % 60, 'minute');
65390				tr.find('.tc-column-time-length').text(diffMinNice).attr('title', diffMinTitle);
65391			}
65392		}
65393	}
65394	_cTimecardManager.clickStaffName = function(element) {
65395		$(element).closest('tr').find('.timecard-copy-checkbox').click();
65396	}
65397	_cTimecardManager.changeStaff = function(ddStaff) {
65398		var jstaff = $(ddStaff);
65399		var staffId = jstaff.val();
65400		var jServiceListContainer = jstaff.closest('.timecard-filter').find('.timecard-manager-service-list');
65401		
65402		jServiceListContainer.find('.timecard-service-dd').remove();
65403		
65404		if (staffId > 0) {
65405			if (jstaff.attr('id') == 'Timecard_Staff_id') {
65406				var dropDownId = 'Timecard_Service_id';
65407			} else {
65408				var dropDownId = 'New_Timecard_Service_id';
65409			}
65410			
65411			var htmServiceList = _getEmployeeServiceDropDown(staffId, dropDownId);
65412			jServiceListContainer.append(htmServiceList);
65413		}
65414	}
65415	function _getEmployeeServiceDropDown(staffId, dropDownId) {
65416		var sgs = $('#ServiceGroupOptionsClone').find('option[default_service_group_id="1009"]');
65417    	var foundCount = 0, newOptionList = '';
65418    	
65419    	for (var a=0; a < sgs.length; a++) {
65420    		var sgid = sgs.eq(a).attr('value');
65421    		var optionList = UserPortal.getOriginalServiceDropDown(sgid);
65422    		var joptions = $('<select>' + optionList + '</select>').find('option');
65423    		var xmlOptions = '';
65424    		
65425    		for (var i=0; i < joptions.length; i++) {
65426	    		var sids = joptions.eq(i).attr('staff_ids');
65427	    		
65428	    		if (sids.split(',').has(staffId)) {
65429	        		++foundCount;
65430	        		xmlOptions += '<option value="' + joptions.eq(i).attr('value') + '">' + joptions.eq(i).text() + '</option>';
65431	    		}
65432	    	}
65433	    	
65434	    	if (sgs.length > 1) {
65435	    		xmlOptions = '<optgroup id="sgid"' + sgid + '>' + xmlOptions + '</optgroup>';
65436	    	}
65437	    	
65438	    	newOptionList += xmlOptions;
65439    	}
65440    	
65441    	if (foundCount > 0) {
65442    		return '<select id="' + dropDownId + '" class="timecard-service-dd">' + newOptionList + '</select>';
65443    	} else {
65444    		return '';
65445    	}
65446	}
65447	function _getStaffDropDown(staffId) {
65448		var jstaff = $('<select id="Timecard_Staff_id' + _lastRowId + '" class="timecard-staff">' + $('#timecard-manager #Timecard_Staff_id').html() + '</select>');
65449		
65450		if (staffId > 0) {
65451			jstaff.find('option[value="' + staffId + '"]').attr('selected', 'selected');
65452		}
65453		
65454		return jstaff.outerHTML();
65455	}
65456	function _getTimecardRowHtm(staffId, serviceId, staffName, serviceName, scheduleMultiId, scheduleId, dtDay) {
65457		++_lastRowId;
65458		var datepickerAttribute = '', trAttributes = '', rowCSS = 'timecard-is-new';
65459		
65460		if (GLO.Info.isMobile()) {
65461			datepickerAttribute = ' readonly="mobile"';
65462		}
65463		
65464		var removeRow = '<span class="ticket-row-remove" onclick="SA.TimecardManager.removeTimecard(this)"> <span class="ui-icon ui-icon-circle-close"></span> </span>';
65465		//var ddStaff = _getStaffDropDown(staffId);
65466		var datepicker = '<input type="text" id="dayTimecard' + _lastRowId + '" class="timecard-day" placeholder="Day" style="z-index: 10;" pattern="[0-9]*"' 
65467				+ datepickerAttribute + ' onchange="SA.TimecardManager.changeDay(this)"/>';
65468		
65469		var clockInTime  = '<input type="text" id="tmClockin' + _lastRowId + '" class="clock-time clockin-time" placeholder="In" pattern="[0-9]*" onchange="SA.TimecardManager.changeTime(this, true)">';
65470		var clockOutTime = '<input type="text" id="tmClockout' + _lastRowId + '" class="clock-time clockout-time" placeholder="Out" pattern="[0-9]*" onchange="SA.TimecardManager.changeTime(this)">';
65471		
65472		if (!UTIL.isEmpty(scheduleId)) {
65473			var displayDay = dtDay.getWeekDayString(true) + ', ' + dtDay.getMonthString(true) + ' ' + dtDay.getDate();
65474			
65475			rowCSS = 'timecard-is-edit timecard-is-loading';
65476			trAttributes = ' schedule_multi_id="' + scheduleMultiId + '" schedule_id="' + scheduleId + '" day_d="' + dtDay.toGloDate() + '"';
65477			datepicker = '<a onclick="UserPortal.Edit.get(' + scheduleMultiId + ')">' + displayDay + '</a>';
65478		}
65479		
65480		return '<tr class="' + rowCSS + '" service_id="' + $.trim(serviceId) + '" staff_id="' + $.trim(staffId) + '"' + trAttributes + '>'
65481			    	+ '<td class="tc-column-checkbox">' + removeRow + '</td>'						//<input class="timecard-copy-checkbox" type="checkbox"/>
65482			    	+ '<td class="tc-column-staff-name">' + staffName + '</td>'
65483			    	+ '<td class="tc-column-service-name">' + serviceName + '</td>'
65484				    + '<td class="tc-column-day" order_by="0">' + datepicker + '</td>'
65485					
65486				    + '<td class="tc-column-clockin">' + clockInTime + '</td>'
65487				    + '<td class="tc-column-clockout">' + clockOutTime + '</td>'
65488					
65489				    + '<td class="tc-column-time-length"></td>'
65490				    + '<td class="tc-column-break-time"></td>'
65491				    + '<td class="tc-column-edit"></td>'
65492				+ '</tr>';
65493	}
65494	
65495	function _getStaffAndServiceFilterHtm() {
65496		var jsearch = $('#timecard-manager-search');
65497		var jstaff = jsearch.find('#Timecard_Staff_id');
65498		var jservice = jsearch.find('#Timecard_Service_id');
65499		
65500		var staffId = jstaff.val(), serviceId = jservice.val();
65501		var ddStaff = '<span class="timecard-manager-staff-list">' + jstaff.clone().attr('id', 'New_Timecard_Staff_id').outerHTML() + '</span>';
65502		var ddService = '<span class="timecard-manager-service-list"></span>';			//' + $.trim(jservice.clone().attr('id', 'New_Timecard_Service_id').outerHTML()) + '
65503		
65504		return '<div id="pop-new-timecard-staff-service">' + ddStaff + ddService + '</div>';
65505	}
65506	function _initStaffAndServiceFilterPopup(jpop) {
65507		var jsearch = $('#timecard-manager-search');
65508		var staffId = jsearch.find('#Timecard_Staff_id').val();
65509		var serviceId = jsearch.find('#Timecard_Service_id').val();
65510		
65511		if (staffId > 0) {
65512			jpop.find('#New_Timecard_Staff_id').val(staffId).change();
65513			
65514			if (serviceId > 0) {
65515				jpop.find('#New_Timecard_Service_id').val(serviceId);
65516			}
65517		}
65518	}
65519	_cTimecardManager.removeTimecard = function(element) {
65520		$(element).closest('tr').remove();
65521	}
65522	_cTimecardManager.openNew = function() {
65523		var filter1 = _getStaffAndServiceFilterHtm();
65524		var datepickerAttribute = '';
65525		
65526		if (GLO.Info.isMobile()) {
65527			datepickerAttribute = ' readonly="mobile"';
65528		}
65529		
65530		var label1 = '<label for="Timecard_Count_nr">Add</label>';
65531		var label2 = '<label for="Timecard_Count_nr">Timecards to Edit</label>';
65532		var inputCount = '<input id="Timecard_Count_nr" type="text" maxlength="3" pattern="[0-9]*" value="1" onkeypress="UI.numberOnly()" style="width: 40px;"/>';
65533		var msg = '<p>' + label1 + inputCount + label2 + '</p>';
65534		
65535		var labelDates = '<p><label for="New_Start_Timecard_dt">Or create timecards over this date range</label></p>';
65536		var inputStart = '<input type="text" id="New_Start_Timecard_dt" class="Begin_dt timecard-date-filter" placeholder="Begin Day" style="z-index: 10;"' + datepickerAttribute + '/>';
65537		var inputEnd = '<input type="text" id="New_End_Timecard_dt" class="End_dt timecard-date-filter" placeholder="End Day" style="z-index: 10;"' + datepickerAttribute + '/>';
65538		var filter2 = '<div id="pop-new-timecard-dates">' + labelDates + inputStart + '<b> - </b>' + inputEnd + '</div>';
65539		
65540		var styleDatepicker = '<style> .ui-datepicker { z-index: 9999 !important; } </style>';
65541		var htmFilter = '<div class="timecard-filter">' + filter1 + '<fieldset>' + msg + filter2 + '</fieldset></div>';
65542		var htm = '<div id="pop-new-timecard-rows">' + styleDatepicker + htmFilter + '</div>';
65543		
65544		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Add Timecard Rows for Staff', SA.TimecardManager.addNewRows, null, true);
65545		var jpop = ojpop.getPopup();
65546		
65547		jpop.find('.btnSave').css({ "margin": "0", "width": "200px" }).find('> a').text('Create Timecard Rows');
65548		
65549		jpop.find('#New_Start_Timecard_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
65550							, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker });			//, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1
65551		jpop.find('#New_End_Timecard_dt').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
65552							, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadDatepicker });			//, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1
65553		
65554		_initStaffAndServiceFilterPopup(jpop);
65555		ojpop.saveOnEnter();
65556	}
65557	_cTimecardManager.addNewRows = function() {
65558		var jpop = $('#pop-new-timecard-rows').closest('.glopop');
65559		var staffId = jpop.find('#New_Timecard_Staff_id').val();
65560		
65561		if (!_isValidNewTimecardFilter(staffId)) { return; }
65562		
65563		GLO.UI.Form.beginProcessing(jpop.find('.btnSave'));
65564		
65565		setTimeout(function() {
65566			SA.TimecardManager.addNewRows2(jpop, staffId);
65567		}, 100);
65568	}
65569	_cTimecardManager.addNewRows2 = function(jpop, staffId) {
65570		var serviceId = jpop.find('#New_Timecard_Service_id').val();
65571		var staffName = jpop.find('#New_Timecard_Staff_id option:selected').text();
65572		var serviceName = jpop.find('#New_Timecard_Service_id option:selected').text();
65573		
65574		var dtStart = null, start = jpop.find('#New_Start_Timecard_dt').val();
65575		var end = jpop.find('#New_End_Timecard_dt').val();
65576		var count = UTIL.coalesceInt(jpop.find('#Timecard_Count_nr').val(), 1);
65577		var trnew1, tbody = $('#timecard-list > tbody');
65578		
65579		if (UTIL.isDate(start)) {
65580			dtStart = new Date(start);
65581			
65582			if (UTIL.isDate(end)) {
65583				count = UTIL.dayDiff(dtStart, new Date(end)) + 1;
65584			}
65585		}
65586		
65587		for (var i=0; i < count; i++) {
65588			var trhtm = _getTimecardRowHtm(staffId, serviceId, staffName, serviceName);
65589			var trnew = _loadNewRow(tbody, trhtm, dtStart);
65590			
65591			if (i == 0) { trnew1 = trnew; }
65592		}
65593		
65594		GLO.Popup.close(jpop);
65595		trnew1.find('.timecard-day').focus();
65596	}
65597	function _loadNewRow(tbody, trhtm, dtStart) {
65598		var trLastNew = _getLastEditRow(tbody);
65599		
65600		if (trLastNew.length) {
65601			trLastNew.after(trhtm);
65602		} else {
65603			tbody.prepend(trhtm);
65604		}
65605		
65606		var tr = _getLastEditRow(tbody);
65607		return _setRowDateAndTime(tr, dtStart);
65608	}
65609	function _getLastEditRow(tbody) {
65610		var tr = tbody.find('tr.timecard-is-new:last, tr.timecard-is-edit:last');
65611		
65612		if (tr.length > 1) {
65613			return tr.eq(tr.length - 1);
65614		} else {
65615			return tr;
65616		}
65617	}
65618	function _setRowDateAndTime(tr, dtStart) {
65619		var inId = tr.find('.clockin-time').attr('id');
65620		var outId = tr.find('.clockout-time').attr('id');
65621		
65622		var jday = tr.find('.timecard-day').datepicker({ showButtonPanel: true, closeText: SA.Resource.Close.toLowerCase(), showWeek: true, calculateWeek: UTIL.datePickerCalculateWeek
65623						, numberOfMonths: UI.getDatepickerMonths(), beforeShow: UI.loadD
65623atepicker });			//, changeYear: true, yearRange: yearRange, showCurrentAtPos: 1
65624		
65625		UI.timeMask('#' + inId);
65626		UI.timeMask('#' + outId, '11:59 am');
65627		UI.highlight(tr, null, null, true);
65628		
65629		if (UTIL.isDate(dtStart)) {
65630			jday.val(dtStart.toGloDate());
65631			dtStart.addDays(1);
65632		}
65633		
65634		return tr;
65635	}
65636	function _isValidNewTimecardFilter(staffId) {
65637		if (UTIL.isEmpty(staffId)) {
65638			var msgWarn = '<div id="pop-warn-new-timecard">Please choose person you want to create timecards for</div>';
65639			var fnWarn = function() {
65640				$('#pop-new-timecard-rows').closest('.glopop').find('#New_Timecard_Staff_id').focus();
65641			};
65642			
65643			GLO.Popup.Warning.open(msgWarn, 'Please Select Person', fnWarn);
65644			return false;
65645		}
65646		
65647		return true;
65648	}
65649	
65650	_cTimecardManager.openCopy = function() {
65651		if ($('#timecard-list').hasClass('timecard-list-copy')) {
65652			var msg1 = '<p>Please Save Copied Timecards on Screen</p>';
65653			var msg2 = '<p>Or Press Search to Clear these copied timecards and load existing timecards</p>';
65654			var htm = '<div id="pop-warn-copy-timecard-in-progress">' + msg1 + msg2 + '</div>';
65655			
65656			GLO.Popup.Warning.open(htm, 'Copy Already in Progress');
65657			return;
65658		}
65659		
65660		var htmFilter = _getStaffAndServiceFilterHtm();
65661		var jboxes = _getBoxesToCopy();
65662		
65663		if (jboxes.length) {
65664			var msg1 = '<p style="letter-spacing: 0;">This will copy ' + UTIL.pluralLabel(jboxes.length, 'timecard') + ' and display the copied timecards for you to edit</p>';
65665			var msg2 = '<p style="text-align: center;">Select the staff for the new timecards</p>';
65666			
65667			htmFilter = '<div class="timecard-filter" style="margin-bottom: 24px;">' + htmFilter + '</div>';
65668			var htm = '<div id="pop-copy-timecard-rows">' + msg1 + msg2 + htmFilter + '</div>';
65669			var ojpop = GLO.Popup.Custom.openSimple(htm, 'Copy Staff Timecards', SA.TimecardManager.copyTimecards, null, true);
65670			var jpop = ojpop.getPopup();
65671			
65672			jpop.find('.btnSave').css({ "margin": "0", "width": "160px" }).find('> a').text('Copy Timecards');
65673			
65674			_initStaffAndServiceFilterPopup(jpop);
65675			ojpop.saveOnEnter();
65676		}
65677	}
65678	_cTimecardManager.copyTimecards = function() {
65679		var jpop = $('#pop-copy-timecard-rows').closest('.glopop');
65680		var jstaff = jpop.find('#New_Timecard_Staff_id');
65681		var jservice = jpop.find('#New_Timecard_Service_id');
65682		
65683		var staffId = jstaff.val(), staffName = jstaff.find('option:selected').text();
65684		var serviceId = jservice.val(), serviceName = jservice.find('option:selected').text();
65685		
65686		var trnew1, copyCount = 0;
65687		var jtbl = $('#timecard-list');
65688		var tbody = jtbl.find('tbody');
65689		var trs = jtbl.find('tbody tr');			//_getBoxesToCopy();
65690		
65691		for (var i=0; i < trs.length; i++) {
65692			var tr = trs.eq(i);
65693			
65694			if (tr.find('.timecard-copy-checkbox').prop('checked')) {
65695				++copyCount;
65696				
65697				var day = new Date(tr.attr('day_d'));
65698				var trhtm = _getTimecardRowHtm(staffId, serviceId, staffName, serviceName);
65699				var trnew = _loadNewRow(tbody, trhtm, day);
65700				
65701				var clockIn  = tr.find('.tc-column-clockin').text();
65702				var clockOut = tr.find('.tc-column-clockout').text();
65703				
65704				//trnew.find('.timecard-day').val(day).change();
65705				trnew.find('.clockin-time').val(clockIn).change();
65706				trnew.find('.clockout-time').val(clockOut).change();
65707				
65708				if (i == 0) { trnew1 = trnew; }
65709				
65710				//tr.removeAttr('schedule_id').removeAttr('schedule_multi_id').removeAttr('special_request_vcl');
65711				//tr.attr('staff_id', staffId).attr('service_id', serviceId);
65712				//tr.find('.tc-column-staff-name').text(staffName);
65713				//tr.find('.tc-column-service-name').text(serviceName);
65714				//tr.find('.timecard-copy-checkbox').remove();
65715			}
65716			
65717			tr.remove();
65718		}
65719		
65720		jtbl.find('thead').find('#timecard-all-checkboxes').remove();
65721		jtbl.addClass('timecard-list-copy');
65722		
65723		GLO.Popup.close();
65724		_displayCopyTimecardMessage(copyCount);
65725		
65726		var jday = trnew1.find('.timecard-day:first');
65727		
65728		if (UTIL.isEmpty(jday.val)) {
65729			jday.focus();
65730		}
65731	}
65732	function _displayCopyTimecardMessage(copyCount) {
65733		var btnSave = '<span id="btnTimecardManagerSavePopup" class="btnSave"> <a onclick="SA.TimecardManager.openSave()">Save</a> </span>';
65734		var header = UTIL.pluralLabel(copyCount, 'Timecard') + ' Copied';
65735		var msg1 = '<p>' + header + ' + Only the New Copied Timecards are displayed</p>';
65736		var msg2 = '<p>Change the timecards as needed then press ' + btnSave + ' to create these new timecards</p>';
65737		
65738		var htm = '<div id="pop-copy-timecard-success">' + msg1 + msg2 + '</div>';
65739		var ojpop = GLO.Popup.Custom.openSimple(htm, 'Copy Staff Timecards', SA.TimecardManager.copyTimecards, null, true);
65740		var jpop = ojpop.getPopup();
65741		
65742		GLO.Popup.Custom.singleButton(jpop, 'Close');
65743		ojpop.saveOnEnter();
65744	}
65745	function _getBoxesToCopy() {
65746		var boxes = $('#timecard-list tbody .timecard-copy-checkbox:checked');
65747		
65748		if (boxes.length === 0) {
65749			var msg = '<p>Check the box next to the timecard(s) you would like to copy</p>';
65750			var fn = function() {
65751				UI.highlight($('#timecard-list .tc-column-checkbox'));
65752			}
65753			
65754			GLO.Popup.Warning.open('<div id="pop-warn-timecard-copy">' + msg + '</div>', 'No Timecards Selected to Copy', fn);
65755		}
65756		
65757		return boxes;
65758	}
65759	
65760	_cTimecardManager.switchRowToEdit = function(btn) {
65761		var trCurrent = $(btn).closest('tr');
65762		
65763		var staffId = trCurrent.attr('staff_id');
65764		var serviceId = trCurrent.attr('service_id');
65765		var staffName = trCurrent.find('.tc-column-staff-name').text();
65766		var serviceName = trCurrent.find('.tc-column-service-name').text()
65767		
65768		var scheduleMultiId = trCurrent.attr('schedule_multi_id');
65769		var scheduleId = trCurrent.attr('schedule_id');
65770		
65771		var day = new Date(trCurrent.attr('day_d'));
65772		var tmIn = trCurrent.find('.tc-column-clockin').text();
65773		var tmOut = trCurrent.find('.tc-column-clockout').text();
65774		
65775		var trHtm = _getTimecardRowHtm(staffId, serviceId, staffName, serviceName, scheduleMultiId, scheduleId, day);
65776		trCurrent.replaceWith(trHtm);
65777		var trNew = $('#timecard-list').find('.timecard-is-loading').removeClass('timecard-is-loading');
65778		
65779		_setRowDateAndTime(trNew, day);
65780		
65781		trNew.find('.clockin-time').val(tmIn);
65782		trNew.find('.clockout-time').val(tmOut).change();
65783	}
65784	
65785	_cTimecardManager.openSave = function() {
65786		GLO.Popup.close($('#pop-copy-timecard-success').closest('.glopop'));
65787		
65788		var newTimecardCount = $('#timecard-list').find('tr.timecard-is-new, tr.timecard-is-edit').length;
65789		var msg = '<p>Do you want to save ' + UTIL.pluralLabel(newTimecardCount, 'timecard') + '</p>';
65790		var htm = '<div id="pop-confirm-timecard-save">' + msg + '</div>';
65791		
65792		var fn = function() {
65793			SA.TimecardManager.openSaveConfirmed(newTimecardCount);
65794		}
65795		
65796		GLO.Popup.Confirm.open(htm, 'Confirm Save Timecards', fn);
65797	}
65798	_cTimecardManager.openSaveConfirmed = function(newTimecardCount) {
65799		var xml = _getTimecardXml();
65800		
65801		if (UTIL.coalesceInt(xml.length, 0) < 20) {			//= do NOT invalid save invalid timecard.
65802			return;
65803		}
65804		
65805		var url = GLO.Link.WebsiteDomain + 'schedule/TimecardSave';
65806		var jdata = { "timecards": UTIL.htmlEncode(xml) };
65807		
65808		GLO.UI.Form.beginProcessing($('#btnTimecardManagerSave'));
65809		
65810		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jdata })
65811            .success(function(data, textStatus, jqXHR) {
65812                var jfilter = $('#timecard-manager-search .timecard-filter');
65813                var staffName = jfilter.find('#Timecard_Staff_id option:selected').text();
65814                var dateFilter = jfilter.find('.Begin_dt ').val() + ' - ' + jfilter.find('.End_dt ').val();
65815                
65816                var msg1 = '<p>' + UTIL.pluralLabel(newTimecardCount, 'Timecard') + ' Saved</p>';
65817                var msg2 = '<p>Re-loading Timecards for ' + staffName + ' between ' + dateFilter + '...</p>';
65818                
65819                //GLO.UI.Form.resetProcessing();
65820                GLO.Popup.Success.open('<div id="pop-timecard-save">' + msg1 + msg2 + '</div>', 'Save Successful');
65821                
65822                _cTimecardManager.search();
65823            })
65824            .error(function(jqXHR, textStatus, errorThrown) {
65825                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65826                GLO.UI.Form.resetProcessing();
65827            });
65828	}
65829	function _getTimecardXml() {
65830		var xml = '';
65831		var trs = $('#timecard-list > tbody').find('tr.timecard-is-new, tr.timecard-is-edit');
65832		
65833		for (var i=0; i < trs.length; i++) {
65834			var tr = trs.eq(i);
65835			var staffId = tr.attr('staff_id');					//.find('.timecard-staff').val();
65836			var serviceId = tr.attr('service_id');
65837			
65838			var scheduleId = $.trim(tr.attr('schedule_id'));
65839			var breakTime = $.trim(tr.find('.tc-column-break-time').text().replace('minutes', '').replace('min', '').replace('hr', ''));
65840			
65841			var day = UTIL.coalesceDate(tr.find('.timecard-day').val(), tr.attr('day_d')).toGloDate();
65842			var tmIn = tr.find('.clockin-time').val();
65843			var tmOut = tr.find('.clockout-time').val();
65844			
65845			var dtIn = day + ' ' + $.trim(tmIn);
65846			var dtOut = day + ' ' + $.trim(tmOut);
65847			
65848			if (!UTIL.isValidTime(tmIn)) {
65849				return GLO.Popup.Warning.open('Please Enter Valid Clock-In Time', 'Invalid Clock-In Time');
65850			} else if (!UTIL.isValidTime(tmOut)) {
65851				return GLO.Popup.Warning.open('Please Enter Valid Clock-Out Time', 'Invalid Clock-Out Time');
65852			} else if (!UTIL.isDate(dtIn)) {
65853				return GLO.Popup.Warning.open('Please Enter Valid Day for the Timecard', 'Invalid Clock-In Time');
65854			}
65855			
65856			xml += '<timecard staff_id="' + staffId + '" service_id="' + serviceId + '" schedule_id="' + scheduleId + '" break_sr="' + breakTime + '" in_dt="' + dtIn + '" out_dt="' + dtOut + '"/>';
65857		}
65858		
65859		return '<manager>' + xml + '</manager>';
65860	}
65861	
65862	_cTimecardManager.openDelete = function() {
65863		var deleteCount = $('#timecard-list tbody .tc-column-checkbox input:checked').length;
65864		
65865		if (deleteCount == 0) {
65866			var msg1 = '<p>No Timecards Selected</p>';
65867			var msg2 = '<p>Check the box next to the timecard(s) you would like to delete</p>';
65868			var fn = function() {
65869				UI.highlight($('#timecard-list .tc-column-checkbox'));
65870			}
65871			
65872			GLO.Popup.Warning.open('<div id="pop-warn-timecard-delete">' + msg1 + msg2 + '</div>', 'No Timecards Selected to Delete', fn);
65873		} else {
65874			var msg = '<p>Do you want to delete ' + UTIL.pluralLabel(deleteCount, 'timecard') + '</p>';
65875			var htm = '<div id="pop-confirm-timecard-save">' + msg + '</div>';
65876			
65877			var fn = function() {
65878				SA.TimecardManager.openDeleteConfirmed(deleteCount);
65879			}
65880			
65881			GLO.Popup.Confirm.open(htm, 'Confirm Delete Timecards', fn);
65882		}
65883	}
65884	_cTimecardManager.openDeleteConfirmed = function(deleteTimecardCount) {
65885		var xml = '', trs = $('#timecard-list tbody .tc-column-checkbox input:checked').closest('tr');
65886		var deleteReason = '';	//toDo: add field in UI
65887		
65888		for (var i=0; i < trs.length; i++) {
65889			xml += '<dl schedule_multi_id="' + trs.eq(i).attr('schedule_multi_id') + '" schedule_id="' + trs.eq(i).attr('schedule_id') + '"/>';
65890		}
65891		
65892		var xml = UTIL.htmlEncode('<ul>' + xml + '</ul>');
65893		var jdata = { "timecards": xml, "reason": deleteReason };
65894		var url = GLO.Link.WebsiteDomain + 'schedule/TimecardDelete';
65895		
65896		GLO.UI.Form.beginProcessing($('#btnTimecardManagerDelete'));
65897		
65898		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false, "data": jdata })
65899            .success(function(data, textStatus, jqXHR) {
65900                var jfilter = $('#timecard-manager-search .timecard-filter');
65901                var staffName = jfilter.find('#Timecard_Staff_id option:selected').text();
65902                var dateFilter = jfilter.find('.Begin_dt ').val() + ' - ' + jfilter.find('.End_dt ').val();
65903                
65904                var msg1 = '<p>' + UTIL.pluralLabel(deleteTimecardCount, 'Timecard') + ' Deleted</p>';
65905                var msg2 = '<p>Re-loading Timecards for ' + staffName + ' between ' + dateFilter + '...</p>';
65906                
65907                //GLO.UI.Form.resetProcessing();
65908                GLO.Popup.Success.open('<div id="pop-timecard-delete-success">' + msg1 + msg2 + '</div>', 'Delete Successful');
65909                
65910                _cTimecardManager.search();
65911            })
65912            .error(function(jqXHR, textStatus, errorThrown) {
65913                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65914                GLO.UI.Form.resetProcessing();
65915            });
65916	}
65917	
65918	_cTimecardManager.openPrint = function() {
65919		window.print();
65920	}
65921	
65922	function _setPrintHeader() {
65923		var header2 = '<b>' + GLO.Data.provider.name + '</b> <span>' + UTIL.formatPhone(GLO.Data.provider.phone) + '</span>';
65924		var jfilter = $('#timecard-manager-search');
65925		var jheader = $('#timecard-manager-print-header');
65926		
65927		var staffId = jfilter.find('#Timecard_Staff_id').val();
65928		var staffName = jfilter.find('#Timecard_Staff_id option:selected').text();
65929		var start = jfilter.find('.Begin_dt').val();
65930		var end = jfilter.find('.End_dt').val();
65931		
65932		jheader.find('#timecard-manager-print-header-dates').html(start + ' - ' + end);
65933		jheader.find('h4').html(header2);
65934	}
65935	
65936	_cTimecardManager.search = function() {
65937		var jfilter = $('#timecard-manager-search');
65938		var staffId = jfilter.find('#Timecard_Staff_id').val();
65939		var serviceId = $.trim(jfilter.find('#Timecard_Service_id').val());
65940		var start = jfilter.find('.Begin_dt').val();
65941		var end = jfilter.find('.End_dt').val();
65942		
65943		var queryString = 'staff=' + staffId + '&service=' + serviceId + '&start=' + start + '&end=' + end;
65944		var url = GLO.Link.WebsiteDomain + 'schedule/TimecardManagerSearch?' + queryString;
65945		
65946		GLO.UI.Form.beginProcessing(jfilter.find('#btnTimecardSearch'));
65947		$('#timecard-manager-data .noResults').text('Looking up Timecards...');
65948		
65949		var jqxhr = $.ajax({ type: "GET", url: url, "cache": false })
65950            .success(function(data, textStatus, jqXHR) {
65951                GLO.UI.Form.resetProcessing();
65952                var jrpt = $('#timecard-manager-data.report-container');
65953                
65954                jrpt.html(data);
65955                var jtbl = $('#timecard-manager-data #timecard-list.tablesorter');
65956                
65957                UI.initTableSorter(jtbl, null, true);
65958                GLO.Report.enableFullPageCheck();
65959                GLO.Report.CellSummary.initReport(jtbl, true, true);
65960                
65961                _setPrintHeader();
65962                
65963                try {
65964		            url = GLO.Link.WebsiteDomain + 'schedule/TimecardManage?' + queryString;
65965		            window.history.pushState("", "Timecard Manager", url);
65966		        } catch (e) { }
65967            })
65968            .error(function(jqXHR, textStatus, errorThrown) {
65969                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
65970                GLO.UI.Form.resetProcessing();
65971            });
65972	}
65973	
65974	return _cTimecardManager;
65975})();
65976
65977GLO.RunningTotal = (function() {
65978	function _conRunTotal() { }
65979	_conRunTotal.unRequestedHours;
65980	var isInitialized = false, _sortByPrice = (GLO.runningTotalOrder == 1), _sortByTurns = (GLO.runningTotalOrder == 3);
65981	var _sortByTime = (!_sortByPrice && !_sortByTurns);
65982	
65983	function _init() {
65984		var sid, arr = [];
65985		var ths = $('.fc-view-resourceDay .fc-agenda-days').find('thead').find('th');
65986		
65987		for (var i=1; i < ths.length-1; i++) {
65988			sid = ths.eq(i).attr('id');
65989			
65990			arr.push({ "id": sid, "hrs": "", "price": "", "turns": "" });
65991		}
65992		
65993		_conRunTotal.unRequestedHours = arr;
65994		isInitialized = true;
65995	}
65996	
65997	_conRunTotal.displayRunningTotal = function() {
65998    	if (GLO.displayRunningTotal) {
65999    		if (!isInitialized) { _init(); }
66000    		
66001    		if (GLO.Calendar.isToday()) {
66002    			var arr = _calculate();
66003    			_setup(arr);
66004    			_conRunTotal.TurnTracker.setStaffOrderHeader();
66005    		} else {
66006    			_tearDown();
66007    		}
66008    	}
66009	}
66010	
66011	function _isClientService(calEvent) {
66012		if (!calEvent.className.has("cal-monthDayPersonal") && !calEvent.className.has("cal-InternalService") && !calEvent.className.has("cal-time-off") && !calEvent.className.has("cal-time-off-end")) {
66013			if (!UTIL.parseBool(calEvent.is_finish_out_fl)) {
66014				return true;
66015			}
66016		}
66017		
66018		return false;
66019	}
66020	
66021	function _calculate() {
66022		var sid, hrs, svc, price, oj;
66023		var evs = GLO.Calendar.cal.fullCalendar('clientEvents');
66024		
66025		for (var a=0; a < _conRunTotal.unRequestedHours.length; a++) {
66026			_conRunTotal.unRequestedHours[a].hrs = 0;
66027			_conRunTotal.unRequestedHours[a].price = 0;
66028			_conRunTotal.unRequestedHours[a].turns = 0;
66029		}
66030		
66031		for (var i=0; i < evs.length; i++) {       //~ loop in case there is a finish out.
66032            if (!UTIL.parseBool(evs[i].client_request_fl) && _isClientService(evs[i])) {
66033	            sid = evs[i].staff_id;
66034	            svc = UserPortal.Calendar.lookupService(evs[i].service_id);
66035	            
66036	            if (!UTIL.isEmpty(svc)) {			// = cannot lookup service in diff location.
66037		            hrs = UTIL.coalesceFloat(svc.total_minutes_nr, evs[i].minutes_nr, 0) / 60;
66038		            
66039		            price = UTIL.cleanString(svc.price).replace('+', '');
66040		            price = UTIL.coalesceMoney(price, evs[i].price_mn, 0);
66041		            
66042		            turns = UTIL.coalesceFloat(evs[i].turns_dr, 0);
66043		            
66044		            oj = UTIL.findObjectInArray(_conRunTotal.unRequestedHours, sid);
66045		            oj.hrs = UTIL.roundMoney(UTIL.coalesceFloat(oj.hrs, 0) + hrs);
66046		            oj.price = UTIL.roundMoney(UTIL.coalesceMoney(oj.price, 0) + price);
66047		            oj.turns = UTIL.coalesceFloat(UTIL.coalesceFloat(oj.turns, 0) + turns);
66048	            }
66049            }
66050        }
66051	}
66052	
66053	function _significantDiff(amt, compare) {		//= difference must be >= $10 or 10 minutes + > 5%
66054		if (amt < compare) {
66055			return true;
66056			
66057			/* if (amt + 10 < compare) {
66058				if (amt * .95 < compare) {
66059					return true;
66060				}
66061			} */
66062		}
66063	}
66064	
66065	_conRunTotal.getResourceStaffColor = function(staffId) {
66066        var i = 0;
66067        var len = GLO.resourceHours.length;
66068        
66069        for (; i < len; i++) {
66070            if (staffId == GLO.resourceHours[i].id) {
66071                return GLO.resourceHours[i].color;
66072            }
66073        }
66074    }
66075    
66076    function _setup(arr) {
66077		var htm, sid, ojHrs, amt, next = null, ondeck = null;
66078		var thead = $('.fc-view-resourceDay .fc-agenda-days').find('thead');
66079		var ths = thead.find('th');
66080		
66081		if (ths.eq(2).find('.turn-tracker-staff').length > 0) {
66082			var hasSpan = true, spanTitle = '';
66083		} else {
66084			var hasSpan = false, spanTitle = SA.Resource.UnrequestedClientHours;
66085		}
66086		
66087		for (var i=1; i < ths.length-1; i++) {
66088			var thClass = '', th = ths.eq(i);
66089			sid = th.attr('id');
66090			ojHrs = UTIL.findObjectInArray(_conRunTotal.unRequestedHours, sid);
66091			
66092			if (_sortByPrice) {
66093				amt = ojHrs.price;
66094			} else if (_sortByTurns) {
66095				amt = ojHrs["turns"];
66096			} else {
66097				amt = ojHrs["hrs"];
66098			}
66099			
66100			if (!UTIL.isDate(GLO.staffResources[i-1].signin)) {
66101				if (amt === 0) { amt = SA.Resource.Signin.toLowerCase(); }
66102				
66103				thClass = 'run-total-sign-in';
66104				spanTitle = SA.Resource.SigninHelp;
66105			} else {
66106				spanTitle = SA.Resource.ServiceTotalToday;
66107				
66108				if (next === null || _significantDiff(amt, next)) {
66109					ondeck = next;
66110					next = amt;
66111					_setNext(thead, th, hasSpan);
66112					
66113					if (amt == 0) { amt = SA.Resource.Next.toLowerCase(); }
66114				} else if (ondeck === null || _significantDiff(amt, ondeck)) {
66115					ondeck = amt;
66116					_setOnDeck(thead, th, hasSpan);
66117					
66118					if (amt == 0) { amt = ''; }
66119				}
66120			}
66121			
66122			if (GLO.Info.roleType < 220 || amt == 0) {
66123				amt = '';
66124			} else if (UTIL.isNumber(amt)) {
66125				if (_sortByPrice) {
66126					amt = '$' + parseInt(amt);
66127				} else if (_sortByTurns) {
66128					if (amt > 0) {							//= bonus are counted as decimals: replace the decimals with '+'
66129						var bonusCount = parseInt((amt - parseInt(amt)) * 10);
66130						
66131						for (var i=0; i < bonusCount; i++) {
66132							amt = UTIL.coalesceString(amt) + '+';
66133						}
66134					} else {
66135						amt = '';
66136					}
66137				} else {
66138					if (amt == 1) {
66139						amt = amt + ' hr';					// + SA.Resource.Hour.toLowerCase();
66140					} else {
66141						amt = amt + ' hr';					// + SA.Resource.Hours.toLowerCase();
66142					}
66143					
66144					if (amt.substring(0,2) === '0.') { amt = amt.substring(1); }
66145				}
66146			}
66147			
66148			if (th.hasClass('fc-col-first-available') || (i == 1 && $('#calendar .fc-col-first-available').length > 0) ) {		//= first check handles page load, second handles sign-in.
66149			} else {
66150				if (hasSpan) {
66151					th.find('.run-total').text(amt);
66152				} else {
66153					htm = '<span class="turn-tracker-staff" onclick="GLO.RunningTotal.clickHeader(event, this)" title="' + spanTitle + '"><span class="run-total">
66153' + amt + '</span></span>';
66154					var cssStyle = '', color = th.css('color');
66155					
66156					if (th.hasClass('hasCustomColor')) {
66157						//cssStyle = ' style="background-color: ' + color + ';"';
66158						th.css({ "background-color": " + color + " });
66159					}
66160					
66161					th.html(htm + '<span class="run-total-staff-name"' + cssStyle + '>' + ths.eq(i).text() + '</span>');
66162					
66163					th.off('click', GLO.Calendar.resourceHeaderClick);
66164					th.find('.run-total-staff-name').click(GLO.Calendar.resourceHeaderClick);
66165				}
66166				
66167				th.addClass(thClass);
66168			}
66169		}
66170	}
66171	
66172	function _setNext(thead, th, hasSpan) {
66173		var className = 'run-total-next', cssOnDeck = 'run-total-on-deck';
66174		
66175		thead.find('.' + cssOnDeck).removeClass(cssOnDeck)
66176		var prev = thead.find('.' + className).removeClass(className).addClass(cssOnDeck);
66177		
66178		if (prev.text() === '') { prev.text('next'); }
66179		
66180		th.addClass(className);
66181		return className;
66182	}
66183	
66184	function _setOnDeck(thead, th, hasSpan) {
66185		var className = 'run-total-on-deck';
66186		var prev = thead.find('.' + className).removeClass(className);
66187		
66188		//if (prev.text() === 'next') { prev.text(''); }
66189		//if (hasSpan) { th.addClass(className); }
66190		
66191		th.addClass(className);
66192		return className;
66193	}
66194	
66195	function _tearDown() {
66196		if (_conRunTotal.unRequestedHours && _conRunTotal.unRequestedHours.length) {
66197			for (var i=0; i < _conRunTotal.unRequestedHours.length; i++) {
66198				_conRunTotal.unRequestedHours[i].hrs = "";
66199				_conRunTotal.unRequestedHours[i].price = 0;
66200				_conRunTotal.unRequestedHours[i].turns = 0;
66201			}
66202		}
66203		
66204		var thead = $('.fc-view-resourceDay .fc-agenda-days').find('thead');
66205		thead.find('th .turn-tracker-staff').css({ "background-color": "" }).text('');
66206		
66207		thead.find('th').removeClass('has-staff-order');
66208		thead.find('th').off('click', GLO.Calendar.resourceHeaderClick);				//= avoids duplicate calls to: resourceHeaderClick
66209		thead.find('th').on('click', GLO.Calendar.resourceHeaderClick);
66210	}
66211	
66212	_conRunTotal.clickHeader = function(event, element) {
66213		var el = $(element);
66214		var th = el.closest('th');
66215		
66216		if (th.hasClass('run-total-sign-in')) {
66217			_conRunTotal.signin(th);
66218		} else {
66219			var firstName = th.find('.run-total-staff-name').text();
66220			_conRunTotal.OrderCalendar.openPopup(th, firstName);
66221		}
66222		
66223		//return UTIL.cancelEvent(event);
66224	}
66225	
66226	_conRunTotal.signinByStaffId = function(staffid) {
66227    	var ths = $('.fc-view-resourceDay').find('thead th');
66228    	
66229    	for (var i=0; i < ths.length; i++) {
66230    		if (ths.eq(i).attr('id') == staffid) {
66231    			_conRunTotal.signin(ths.eq(i));
66232    			break;
66233    		}
66234    	}
66235    }
66236    
66237    _conRunTotal.signin = function(th) {
66238		var sid = th.attr('id');
66239		var sname = th.find('.run-total-staff-name').text();
66240		var url = GLO.Link.WebsiteDomain + 'schedule/signin?staffid=' + sid;
66241    	
66242    	var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.SignIn2 + ' ' + sname + '</h1><div class="friendly-msg2">' + SA.Resource.Signing_in + ' ' + sname + '...</div></div>';
66243    	var ojProcessing = new GLO.Popup.Processing(msg);		//UI.displayProcessingLayer();
66244    	
66245    	var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
66246            .success(function(data, textStatus, jqXHR) {
66247                ojProcessing.close();				//GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
66248                var now = $(data).attr('now_dt');
66249                
66250                if (UTIL.isDate(now)) {
66251                	_signinSuccess(sid, sname, now);
66252                	th.find('.run-total-sign-in').removeClass('run-total-sign-in').removeAttr('title');
66253                }
66254            })
66255            .error(function(jqXHR, textStatus, errorThrown) {
66256                ojProcessing.close();				//GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
66257                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
66258            });
66259	}
66260	
66261	_conRunTotal.signout = function(staffid, staffFirstName) {
66262		if (UTIL.isEmpty(staffFirstName)) { staffFirstName = UserPortal.lookupStaffName(staffid); }
66263		
66264		var url = GLO.Link.WebsiteDomain + 'schedule/signout?staffid=' + staffid;
66265		var jpop = $('#pop-calendar-order').closest('.glopop');
66266		var jbtn = jpop.find('#btnSignout');
66267		
66268		GLO.UI.Form.beginProcessing(jbtn);
66269		
66270		var jqxhr = $.ajax({ type: "POST", url: url, "cache": false })
66271            .success(function(data, textStatus, jqXHR) {
66272                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
66273                GLO.Popup.close(jpop);
66274                
66275                _signoutSuccess(staffid, staffFirstName);
66276            })
66277            .error(function(jqXHR, textStatus, errorThrown) {
66278                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
66279                GLO.Log.processesSecurityException(null, null, textStatus, jqXHR);
66280            });
66281	}
66282	
66283	function _reorderCalendar(showMessage) {
66284		if (GLO.Calendar === undefined) { return; }
66285		
66286		if (showMessage) {
66287			var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.ReOrderCalendar + '</h1><div class="friendly-msg2">' + SA.Resource.UpdatingStaffOrderCalendar + '...</div></div>';
66288			var ojProcessing = new GLO.Popup.Processing(msg);
66289		}
66290		
66291		GLO.Schedule.Calendar.reloadCalendar(null, ojProcessing);
66292	}
66293	
66294	function _signoutSuccess(sid, staffFirstName) {
66295		var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.SignOut + ' ' + staffFirstName + '</h1><div class="friendly-msg2">' + SA.Resource.UpdatingOrderFor + ' ' + staffFirstName + '...</div></div>';
66296		var ojProcessing = new GLO.Popup.Processing(msg);
66297		
66298		var fn = function() { _moveToLast(sid); };
66299		
66300		GLO.Schedule.Calendar.reloadCalendar(fn, ojProcessing);
66301	}
66302	
66303	function _signinSuccess(sid, sname, now) {
66304		var msg = '<div><h1 class="friendly-msg2">' + SA.Resource.SignIn2 + ' ' + sname + '</h1><div class="friendly-msg2">' + SA.Resource.UpdatingOrderFor + ' ' + sname + '...</div></div>';
66305		var ojProcessing = new GLO.Popup.Processing(msg);
66306		var fn = function() { _reorderStaff(sid, now); }
66307		
66308		GLO.Schedule.Calendar.reloadCalendar(fn, ojProcessing);
66309	}
66310	
66311	function _moveToLast(sid) {
66312		var arrStaff;
66313		
66314		for (var s=0; s < GLO.staffResources.length; s++) {
66315			if (sid == GLO.staffResources[s].id) {
66316				arrStaff = GLO.staffResources[s];
66317				arrStaff.signin = "";
66318				GLO.staffResources.splice(s, 1);
66319				break;
66320			}
66321		}
66322		
66323		if (arrStaff) { GLO.staffResources.push(arrStaff); }
66324	}
66325	
66326	function _reorderStaff(sid, now) {
66327		var moveTo = null, arrStaff;
66328		//var hasFA = $('#calendar .fc-col-first-available').length;
66329		
66330		for (var s=0; s < GLO.staffResources.length; s++) {
66331			if (moveTo === null && UTIL.isEmpty(GLO.staffResources[s].signin) && !UTIL.parseBool(GLO.staffResources[s].is_first_available_fl)) {
66332				moveTo = s;
66333			}
66334			
66335			if (sid == GLO.staffResources[s].id) {
66336				arrStaff = GLO.staffResources[s];
66337				arrStaff.signin = now;
66338				GLO.staffResources.splice(s, 1);
66339				
66340				sid = null;
66341				if (moveTo !== null) { break; }
66342			}
66343		}
66344		
66345		if (moveTo !== null && arrStaff) {
66346			//if (hasFA) { ++moveTo; }
66347			GLO.staffResources.splice(moveTo, 0, arrStaff);
66348		}
66349	}
66350	
66351	_conRunTotal.getSigninStatus = function(staffid) {			//returns: 'in' (currently signed-in), 'out' (currently signed-out), or null (if staff not in GLO.staffResources).
66352		var oj = UserPortal.Calendar.findStaffResource(staffid);
66353		
66354		if (UTIL.isEmptyObject(oj)) {
66355			return null;
66356		} else if (UTIL.isDate(oj.signin)) {
66357			return 'in'
66358		} else  {
66359			return 'out'
66360		}
66361	}
66362	
66363	
66364	_conRunTotal.TurnTracker = (function() {				//= GLO.RunningTotal.TurnTracker
66365        function _cTurnTracker() { }
66366        
66367        _cTurnTracker.displayApptHeader = function(jappt) {
66368        	if (UserPortal.isLoading) { return; }
66369        	if (UserPortal.Edit.isLoadFromCreate) { return; }
66370        	if (!UserPortal.apptIsNow(jappt, 2000)) { return; }
66371        	
66372        	if (jappt.hasClass('simplemodal-container')) {
66373    			var jmodal = jappt;
66374    			jappt = jappt.find('.shadow');
66375    		} else {
66376    			var jmodal = jappt.closest('#simplemodal-container');
66377        	}
66378        	
66379        	//jmodal.find('.hello-bar-appt').remove();
66380        	var arrStaffForSvc = _getNextStaffForServiceArray(jappt);
66381        	var isCreateAppt = (jappt.attr('id') === 'ba-CreateAppointment');
66382        	
66383        	if (arrStaffForSvc.length) {
66384        		var htm = _getNextStaffApptHeaderHtm(arrStaffForSvc);
66385        		var cssClass = 'hello-bar-turn-tracker-next-staff';
66386        		
66387        		if (arrStaffForSvc.length > 7 || (isCreateAppt && arrStaffForSvc.length === 1)) {
66388        			cssClass += ' hello-bar-narrow-text'; 					//jmodal.find('.hello-bar-turn-tracker-next-staff').addClass('hello-bar-narrow-text');
66389        		}
66390        		
66391        		if (isCreateAppt) {
66392        			UserPortal.Calendar.addHelloBarCreateAppt(jappt, htm, cssClass);
66393        		} else {
66394        			UserPortal.Calendar.addHelloBarEditAppt(jappt, htm, cssClass);
66395        		}
66396        	}
66397        }
66398        function _getNextStaffApptHeaderHtm(arrStaffForSvc) {
66399        	var htm = '', labelText = 'Turn Tracking Next Staff';
66400        	
66401        	if (arrStaffForSvc.length > 14) {
66402        		labelText = '';
66403        	} else if (arrStaffForSvc.length > 9) {
66404        		labelText = 'Next Staff';
66405        	}
66406        	
66407        	for (var i=0; i < arrStaffForSvc.length; i++) {
66408        		if (i > 0) {
66409        			htm += '<i>&bull;</i>';
66410        		}
66411        		
66412        		var sid = arrStaffForSvc[i].staff_id;
66413        		var serviceId = arrStaffForSvc[i].service_id;
66414        		
66415        		var sname = UserPortal.getStaffName(sid);
66416        		var rowIndex = arrStaffForSvc[i].row_index_sr;
66417        		var title = (rowIndex + 1) + ': ' + sname;
66418        		
66419        		if (!UTIL.isEmpty(serviceId)) {
66420        			var svcName = UserPortal.getServiceName(serviceId);
66421        			title += ' for ' + svcName;
66422        		}
66423        		
66424        		var fnOnClick = 'GLO.RunningTotal.TurnTracker.setStaff(' + rowIndex + ', ' + sid + ')';
66425        		htm += '<b class="turn-tracker-staff" row_index_sr="' + rowIndex + '" staff_id="' + sid + '" onclick="' + fnOnClick + '">' + UTIL.maxString(sname, 12, true) + '</b>';
66426        	}
66427        	
66428        	var btn = '<span id="btnSetTurnTrackerStaff" class="btnAdd"><a onclick="GLO.RunningTotal.TurnTracker.setStaffAll()">Set</a></span>';
66429        	return '<div id="turn-tracker-appt-hello-bar"> <label>' + labelText + '</label>' + htm + btn + '</div>';
66430        }
66431        function _getNextStaffForServiceArray(jappt) {
66432        	var faid = UserPortal.getFirstAvailableStaffId();
66433        	var jsvc = jappt.find('.serviceDD:visible');
66434        	var jstaff = jappt.find('.staffDD:visible');
66435        	var arr = [], ignoreStaffIds = '';
66436        	
66437        	for (var i=0; i < jstaff.length; i++) {
66438        		if (jstaff.eq(i).val() == faid || UTIL.isEmpty(jstaff.eq(i).val())) {
66439        			var svcid = jsvc.eq(i).val();											//= this looks off but is ok: above loop is looping thru staff (i.e. service rows), there will be the same number of staff and service drop downs.
66440        			var sid = _cTurnTracker.getNextStaff(svcid, ignoreStaffIds);
66441        			
66442        			if (UTIL.isNumber(sid)) {
66443        				if (ignoreStaffIds !== '') {
66444        					ignoreStaffIds += ',';
66445        				}
66446        				
66447        				ignoreStaffIds += sid;
66448        				arr.push({ "row_index_sr": i, "staff_id": sid, "service_id": svcid });
66449        			}
66450        		}
66451        	}
66452        	
66453        	return arr;
66454        }
66455        _cTurnTracker.getNextStaff = function(serviceId, ignoreStaffIds) {
66456        	var arr = _cTurnTracker.getStaffOrderArray(serviceId, ignoreStaffIds);
66457        	
66458        	if (arr.length === 0) {
66459				return null;
66460			} else {
66461				return arr[0].id;
66462			}
66463        }
66464        _cTurnTracker.getStaffOrderArray = function(serviceId, ignoreStaffIds) {
66465			var jstaff = $('#calendar table.fc-agenda-days').find('th:not(.run-total-sign-in) .turn-tracker-staff');
66466			var arr = [];
66467			
66468			for (var i=0; i < jstaff.length; i++) {
66469				var js = jstaff.eq(i);
66470				var sid = js.parent().attr('id');
66471				var turn = $.trim(js.find('.run-total').text().replace('$', '').replace('hr', '').replace('hrs', '').replace('next', ''));
66472				
66473				if (UTIL.isNumber(turn) && _sortByTime) {
66474					turn = UTIL.coalesceFloat(turn) * 60;
66475				}
66476				
66477				turn = UTIL.coalesceInt(turn, 0);			//filter out bonus
66478				
66479				//incorporate signin date to turn value
66480				if (js.hasClass('run-total-on-deck')) {
66481					turn += .0001;
66482				} else if (!js.hasClass('run-total-next')) {
66483					turn = UTIL.roundNumber(turn + .0001 + (i + 1) * .0001, 4);
66484				}
66485				
66486				arr.push({ "id": sid, "turn": turn });
66487			}
66488			
66489			if (arr.length > 0) {
66490				var arr2 = [];
66491				var staffIdsWhoDoService = _getSignedInStaffArray(serviceId, ignoreStaffIds, arr);
66492					
66493				for (var i=0; i < arr.length; i++) {
66494					if (staffIdsWhoDoService.has(arr[i].id)) {
66495						arr2.push(arr[i]);
66496					}
66497				}
66498				
66499				arr = arr2;
66500			}
66501			
66502			return UTIL.sortArray(arr, "turn");
66503		}
66504		function _getSignedInStaffArray(serviceId, ignoreStaffIds, arr) {
66505			if (UTIL.isNumber(serviceId)) {
66506				var staffIds = $('#allServiceOptions').find('option[value="' + serviceId + '"]').attr('staff_ids').split(',');
66507			} else {
66508				var staffIds = [];
66509				
66510				for (var i = 0; i < arr.length; i++) {
66511					staffIds.push(arr[i].id);
66512				}
66513			}
66514			
66515			if (!UTIL.isEmpty(ignoreStaffIds)) {
66516				var ignoreIds = ignoreStaffIds.split(',');
66517				
66518				for (var a = staffIds.length -1; a >= 0; a--) {
66519					var sid = staffIds[a];
66520					
66521					for (var i = ignoreIds.length - 1; i >= 0; i--) {
66522						if (sid == ignoreIds[i]) {
66523							staffIds.splice(a, 1);
66524							ignoreIds.splice(i, 1);
66525							break;
66526						}
66527					}
66528				}
66529			}
66530			
66531			return staffIds;
66532		}
66533		
66534		_cTurnTracker.setStaffOrderHeader = function() {
66535        	var arr = _cTurnTracker.getStaffOrderArray();
66536        	var thead = $('.fc-view-resourceDay .fc-agenda-days').find('thead');
66537        	
66538        	for (var i=0; i < arr.length; i++) {
66539				var th = thead.find('th[id="' + arr[i].id + '"]').addClass('has-staff-order');
66540				var title = _getStaffHeaderTitle(arr[i], th, i + 1);
66541				
66542				if ($('body').hasClass('cal-very-narrow')) {
66543					var label = (i + 1);
66544				} else {
66545					var label = '#' + (i + 1);
66546				}
66547				
66548				var htm = '<b class="run-total-order">' + label + '</b>';
66549				
66550				th.find('.run-total-order').remove();
66551				th.find('.turn-tracker-staff').attr('title', title);
66552				th.find('.turn-tracker-staff').prepend(htm);
66553			}
66554        }
66555        function _getStaffHeaderTitle(jsonStaff, th, orderNumber) {
66556        	title = 'Turn Order #' + orderNumber;
66557        	
66558        	if (_sortByPrice || _sortByTime) {
66559        		var val = th.find('.run-total').text();
66560        		
66561        		if (!UTIL.isEmpty(val)) {
66562        			title += '\n' + SA.Resource.ServiceTotalToday + ' (not including client appointment requests): ' + val;
66563        		}
66564        	}
66565        	
66566        	return title;
66567        }
66568		
66569		_cTurnTracker.setStaffAll = function() {
66570			var jappt = UserPortal.getAppt();
66571			var jturns = $('#turn-tracker-appt-hello-bar .turn-tracker-staff');
66572			var jstaff = jappt.find('.staffDD');
66573			var jddLastStaff = null;
66574			
66575			for (var i=0; i < jturns.length; i++) {
66576        		var rowIndex = jturns.eq(i).attr('row_index_sr'), sid = jturns.eq(i).attr('staff_id');
66577        		jddLastStaff = jstaff.eq(rowIndex).val(sid);
66578        	}
66579        	
66580        	if (jddLastStaff) {
66581        		jddLastStaff.change();
66582        	}
66583		}
66584		_cTurnTracker.setStaff = function(rowIndex, staffId) {
66585			var jappt = UserPortal.getAppt();
66586			//var isCreate = (jappt.attr('id') === 'ba-CreateAppointment');
66587			
66588			//var jsvc = jappt.find('.serviceDD').eq(rowIndex);
66589        	var jstaff = jappt.find('.staffDD').eq(rowIndex);
66590        	
66591        	jstaff.val(staffId).change();
66592		}
66593		
66594        return _cTurnTracker;
66595    })();
66596	
66597	
66598	_conRunTotal.OrderCalendar = (function() {
66599        function _conOrderCalendar() { }
66600        
66601        _conOrderCalendar.openPopup = function(th) {
66602        	if (GLO.Calendar === undefined && !GLO.Provider.Advanced.canSaveChanges()) { GLO.Provider.Advanced.initReadOnlyCheck(); return; }
66603        	
66604        	if (th) {
66605        		var sid = th.attr('id');
66606				var htmStaffHeader = _getStaffHtmlHeader(sid);
66607			} else {
66608				var htmStaffHeader = '';
66609			}
66610			
66611			var h1 = '<h1 class="friendly-msg2">' + SA.Resource.OrderCalendar + '</h1>';
66612			var btnClose = '<span class="btnCancel btn" style="float: none; margin-right: 8px; letter-spacing: 1px;"> <a onclick="GLO.RunningTotal.OrderCalendar.close()">' + SA.Resource.Close + '</a> </span>';
66613			
66614			var msg1 = GLO.Provider.Advanced.Help.Calendar.getStaffOrderList('Change order staff displayed on');
66615			var msg2 = '<p id="pop-calendar-order-list-help">' + SA.Resource.DragStaffNameUpOrDown + '</p>';
66616			
66617			var htm = htmStaffHeader + msg1 + msg2
66618					+ '<div id="pop-calendar-order-list" style="margin-top: 2px; margin-bottom: 20px;">' + _staffOrderList() + '</div>'
66619					+ '<div id="pop-calendar-order-buttons">' + btnClose + '</div>';
66620			
66621			var css = ' style="text-align: center; letter-spacing: 1px;"';
66622			var jhtm = $('<div id="pop-calendar-order" style="min-width: 310px;">' + h1 + '<div' + css + '>' + htm + '</div> </div>');
66623			
66624			var ojpop = new GLO.Popup.Custom(jhtm);
66625			var jpop = ojpop.getPopup().addClass('no-persist');
66626			jpop.find('.pop-buttons').remove();
66627			
66628			$('#pop-calendar-order-list ol').sortable({
66629				//cancel: ".disable-sort-item",
66630				update: function(event, ui) {
66631					ui.item.attr('updated_fl', 1);
66632					
66633					setTimeout(function() {
66634						_displaySaveButton(ui.item);
66635					}, 900);
66636				}
66637				
66638				, stop: function (event, ui) {
66639					if (!_isValidStaffSort(event, ui)) {
66640						ui.item.removeAttr('updated_fl');
66641						$(this).sortable('cancel');
66642					}
66643				}
66644				
66645				//, change: function(event, ui) { }
66646				//, sort: function(event, ui) { }
66647			});
66648			
66649			_setWhoIsNextColors(jpop);
66650        }
66651        
66652        function _isValidStaffSort(event, ui) {
66653        	if (ui.item.hasClass('is-first-available')) {
66654        		var htm = '<div class="friendly-msg3">Cannot Move <b><i>First Available</i></b></div>';
66655        		new GLO.Popup.Warning(htm);
66656        		return false;
66657        	} else if (ui.item.index() === 0 && ui.item.closest('ol').find('li.is-first-available').length > 0) {
66658        		var htm = '<div class="friendly-msg3">Cannot Move Before <b><i>First Available</i></b></div>';
66659        		new GLO.Popup.Warning(htm);
66660        		return false;
66661        	}
66662        	
66663        	return true;
66664        }
66665        
66666        function _setWhoIsNextColors(jpop) {
66667        	if (!GLO.isFrontDeskCalendar) { return; }
66668        	
66669        	var thead = $('.fc-view-resourceDay').find('thead');
66670        	var nextSID = thead.find('.run-total-next').attr('id');
66671        	var ondeckSID = thead.find('.run-total-on-deck').attr('id');
66672        	
66673        	var lis = jpop.find('#pop-calendar-order-list').find('ol > li');
66674        	
66675        	for (var i=0; i < lis.length; i++) {
66676        		var li = lis.eq(i);
66677        		var sid = li.attr('staff_id');
66678        		
66679	        	if (nextSID == sid) {
66680	        		var bgc = thead.find('.run-total-next').css('background-color');
66681	        		li.find('a').css({ "background-color": bgc });
66682	        	}
66683	        	
66684	        	if (ondeckSID == sid) {
66685	        		var bgc = thead.find('.run-total-on-deck').css('background-color');
66686	        		li.find('a').css({ "background-color": bgc });
66687	        	}
66688	        }
66689        }
66690        
66691        function _getStaffHtmlHeader(sid) {
66692        	if (UTIL.isEmpty(sid)) { return ''; }
66693        	
66694        	var nm = UserPortal.lookupStaffName(sid);
66695			var cleanName = nm.replace(/"/g, '').replace(/'/g, '');
66696			var signin = UserPortal.Calendar.findStaffResource(sid).signin;
66697			
66698			var htmStaffHeader = '<div id="pop-calendar-order-top" style="line-height: 300%; margin-bottom: 20px;">'
66699									+ '<div> <a onclick="GLO.RunningTotal.OrderCalendar.gotoCalendar(event, ' + sid + ', \'' + cleanName + '\')">' + SA.Resource.GoTo + ' ' + nm + '\'s + ' + SA.Resource.Calendar + '</a> </div>';
66700			
66701			if (UTIL.isDate(signin)) {
66702				var title = 'Signed-in ' + new Date(signin).toGloTime();			//signin.toSADate(true)
66703				
66704				htmStaffHeader += '<div> <span id="btnSignout" class="btn btnAdd">'
66705								+ '<a onclick="GLO.RunningTotal.signout(' + sid + ', \'' + cleanName + '\')" title="' + title + '" style="background-color: rgba(255, 120, 0, .9);">Sign Out ' + nm + '</a>'
66706							+ '</span> </div>'
66707			}
66708			
66709			return htmStaffHeader + '</div>';
66710        }
66711        
66712        function _displaySaveButton(jitem) {
66713        	if (!UTIL.parseBool(jitem.attr('updated_fl'))) {
66714        		return;
66715        	}
66716        	
66717        	var jpop = $('#pop-calendar-order').closest('.glopop');
66718        	var jbtns = jpop.find('#pop-calendar-order-buttons');
66719        	
66720        	if (jbtns.find('.btnSave:visible').length > 0) {
66721        		return;
66722        	}
66723        	
66724        	var aSave = '<a onclick="GLO.RunningTotal.OrderCalendar.save()">' + SA.Resource.Save + '</a>';
66725        	var btnSave = '<span class="btn btnSave" style="position: absolute; right: 0; letter-spacing: 1px;">' + aSave + '</span>';
66726        	var divSave = '<div style="margin-top: 16px; margin-bottom: 24px;"><span class="btn btnSave">' + aSave + '</span></div>';
66727        	
66728        	jbtns.css({ "position": "relative", "min-height": "24px", "padding-top": "12px" }).find('.btnCancel').css({ "position": "absolute", "left": "8px" });
66729        	jbtns.append(btnSave);
66730        	
66731        	jpop.find('#staff-order-sort-help').replaceWith(divSave);
66732        }
66733        
66734        function _staffOrderList() {
66735			var cnt = 0, htm = '<ol>', signinOnly = false;
66736			
66737			if (UTIL.isDate(GLO.staffResources[0].signin)) { signinOnly = true; }
66738			
66739			for (var s=0; s < GLO.staffResources.length; s++) {
66740				if (!signinOnly || UTIL.isDate(GLO.staffResources[s].signin)) {
66741					if (UTIL.parseBool(GLO.staffResources[s].is_first_available_fl)) {
66742						cssClass = ' class="is-first-available"';
66743					} else {
66744						cssClass = '';
66745					}
66746					
66747					var sid = GLO.staffResources[s].id, signin = GLO.staffResources[s].signin, name = GLO.staffResources[s].name;
66748					var title = UTIL.coalesceString(GLO.staffResources[s].title);
66749					
66750					htm += '<li' + cssClass + ' staff_id="' + sid + '" signin_dt="' + signin + '" title="' + title + '"> <a>' + name + '</a> </li>';
66751					++cnt;
66752				}
66753			}
66754			
66755			if (cnt > 1) {
66756				return htm + '</ol>';
66757			} else {
66758				return '';
66759			}
66760		}
66761		
66762		function _dateToString(dt) {
66763			if (UTIL.isEmpty(dt)) { dt = new Date(); }
66764			return dt.toGloDate() + ' ' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds();
66765		}
66766		
66767		function _reOrderList() {
66768			var order = 100, hasSignin = false, arr = [], dt = new Date();
66769			var lis = $('#pop-calendar-order-list ol').find('li');
66770			
66771			dt = new Date(dt.setSeconds(dt.getSeconds() - 100));
66772			
66773			if (UTIL.isDate(GLO.staffResources[0].signin)) { hasSignin = true; }
66774			var htm = '<ol is_signin_fl="' + hasSignin + '">';
66775			
66776			for (var i=0; i < lis.length; i++) {
66777				var sid = lis.eq(i).attr('staff_id');
66778				var oj = UserPortal.Calendar.findStaffResource(sid);
66779				
66780				dt = new Date(dt.setSeconds(dt.getSeconds() + 1));
66781				htm += '<li staff_id="' + sid + '" signin_dt="' + _dateToString(dt) + '" order_sr="' + (++order) + '"/>';
66782				
66783				arr.push(oj);
66784			}
66785			
66786			if (hasSignin) {
66787				for (var s=0; s < GLO.staffResources.length; s++) {
66788					if (!UTIL.isDate(GLO.staffResources[s].signin)) {
66789						arr.push(GLO.staffResources[s]);
66790					}
66791				}
66792			}
66793			
66794			GLO.staffResources = arr;
66795			return htm + '</ol>';
66796		}
66797		
66798		_conOrderCalendar.gotoCalendar = function(ev, staffid, staffName) {
66799			url = GLO.Link.WebsiteDomain + 'provider/calendar?sfilter=' + staffid;
66800			
66801			var dt = GLO.Uri.url('dt');
66802	        if (!UTIL.isEmpty(dt)) { url += '&dt=' + dt; }
66803	        
66804	        _conOrderCalendar.close();
66805	        
66806	        if (ev && ev.ctrlKey) {
66807	            window.open(url);
66808	        } else {
66809	            UI.displayProcessingLayer();
66810	            setTimeout(function() { document.location = url; }, 200);
66811	        }
66812		}
66813		
66814		_conOrderCalendar.close = function() {
66815			var jpop = $('#pop-calendar-order').closest('.glopop');
66816			GLO.Popup.close(jpop);
66817		}
66818		
66819		_conOrderCalendar.save = function() {
66820			var ol = UTIL.htmlEncode(_reOrderList());
66821			_reorderCalendar();
66822			
66823			var uri = GLO.Link.WebsiteDomain + 'schedule/OrderCalendar';
66824			var jpop = $('#pop-calendar-order').closest('.glopop');
66825			var jbtn = jpop.find('.btnSave');
66826			
66827			GLO.UI.Form.beginProcessing(jbtn);
66828			
66829	        var jqxhr = $.ajax({ type: "POST", url: uri, "cache": false, data: { "ol": ol } })
66830	            .success(function(data, textStatus, jqXHR) {
66831	                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
66832                	GLO.Popup.close(jpop);
66833                	
66834                	if (GLO.isPOS) {
66835                		GLO.Popup.Success.open('New Staff Order Saved<br/><br/>Loading Changes....', 'Staff Sort Order');
66836                		
66837                		setTimeout(function() {
66838                			location.reload();
66839                		}, 100);
66840                	}
66841	            })
66842	            .error(function(jqXHR, textStatus, errorThrown) {
66843	                GLO.UI.Form.resetProcessing(); 		//UI.removeProcessingLayer();
66844	                //new GLO.Popup.Error('Unable to order the calendars staff');
66845	            });
66846		}
66847        
66848        return _conOrderCalendar;
66849    })();
66850	
66851	return _conRunTotal;
66852})();
66853
66854
66855
66856$(function() {
66857    var url = document.location.pathname;
66858
66859    if (url.indexOf('/provider/profile') !== -1) {
66860        $('#hd-profile-menu-text').addClass('selectedLink');
66861    } else if (url.indexOf('/provider/inventory') !== -1) {
66862        $('#hd-product-menu-text').addClass('selectedLink');
66863    } else if (url.indexOf('/provider/calendar') !== -1 || url.indexOf('/provider/reminders') !== -1 || url.indexOf('/provider/apptportal') !== -1) {
66864        $('#hd-schedule-menu-text').addClass('selectedLink');
66865    } else if (url.indexOf('/reports/') !== -1) {
66866        $('#hd-reports-menu-text').addClass('selectedLink');
66867    }
66868
66869    SA.Menu.init();
66870    Search.init('#easySearch_text', GLO.Link.Object.Provider.UserSearch + '?include-inventory=1');
66871    $('#runSearch').click(Search.run);
66872    
66873    $('#top-searchBox').bind('keydown', function(e) {
66874        if (e.which === 13) { // ENTER
66875            if (!Search.inProgress) {
66876                Search.run(); e.preventDefault();
66877            }
66878        }
66879    });
66880
66881    var jPageHeader = $('#search-bar');
66882    jPageHeader.find('#staff-filter, #easySearch_text').focus(function() {
66883	    var simpleModal = $('#simplemodal-container');
66884	    var glopop = $('.glopop:visible');
66885	    var element;
66886	    
66887        if (glopop.size() > 0) {							//set focus on first element in simple modal.
66888		    element = glopop.eq(0).find('input, select, textarea, button');
66889            if (element.size() > 0) { element.eq(0).focus(); }
66890	    } else if (simpleModal.css('display') !== undefined) {			//set focus on first element in simple modal.
66891		    element = simpleModal.find('input, select, textarea, button');
66892            if (element.size() > 0) { element.eq(0).focus(); }
66893	    }
66894    });
66895	
66896    GLO.Staff.Filter.initOnPageLoad();
66897    SA.Kiosk.init();
66898});

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.