diff --git a/LiveChat/App_LocalResources/AdminPanel.resx b/LiveChat/App_LocalResources/AdminPanel.resx new file mode 100644 index 0000000..a2b9a9e --- /dev/null +++ b/LiveChat/App_LocalResources/AdminPanel.resx @@ -0,0 +1,564 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 90 Degree + + + -90 Degree + + + Active Visitors + + + Add Agent + + + Agent has been created successfully. + + + Add Department + + + Department has been created successfully. + + + Add New Agent + + + Add New Department + + + Admin Panel + + + Agents + + + View permission of the current live chats for agents + + + All Agents In Department + + + Allow visitors to send you messages when you are offline. To receive email notification. + + + Allow visitors to rate their chats with your agents. + + + Anonymous + + + Appearance + + + Are you sure? + + + You can customize and limited live chat module! + + + Basic Settings + + + Basic Settings is not enabled! + + + Bottom + + + Bottom Left + + + Bottom Right + + + Byline + + + Cancel + + + Center + + + Chat Window + + + Clear Session Storage + + + Concierge + + + Css Style + + + After deleted agent, history is not deleted + + + Agent has been removed successfully. + + + If the department have agents you can not delete department + + + Department has been removed successfully. + + + Department Name + + + Departments + + + Description + + + Display agents' and visitors' avatars in chat messages. + + + Name + + + Display Title + + + Done! + + + Edit + + + Email + + + Email Templates + + + Enabled + + + Enable Rating + + + Error + + + Field value is required + + + Value must be a numeric + + + Exit + + + Export To Excel + + + Find a Agent... + + + Find a Department + + + Find a Visitor + + + Form Items + + + Forms + + + Functionality Settings + + + History + + + Home + + + Horizontal Position + + + hour + + + Html Template + + + Incoming Chats + + + Large + + + Left + + + Live Chat + + + Live Chat Enabled + + + Live Chat is not enabled! for chatting with visitors it must enabled! + + + Manage + + + Medium + + + Message + + + Message Style + + + min + + + Min Button + + + Minimized Chat Button + + + MyDnn Support + + + Name + + + Name,Email + + + No + + + No agents... + + + No departments... + + + Normal + + + Offline BG Color + + + Offline Button + + + Offline Color + + + Offline Email Template + + + Offline Form + + + Offline Message + + + Online + + + Online BG Color + + + Online Color + + + Online Form + + + Only Current Agents + + + Only Current Agents And Admin + + + Play a sound for the visitor when a new message is received + + + Priority + + + Referrer + + + Require visitors to complete a form before starting a chat. + + + Right + + + Rotate + + + Save + + + Select User + + + Automatically send the chat transcript to agent(s) email after the chat ends. + + + Send email notification to agent(s) when visitors send an offline message + + + Send Message + + + Settings + + + Show Avatars + + + Show desktop notifications for incoming chats + + + Show desktop notifications for new messages in open chats + + + Simple Live + + + Small + + + sort by + + + Sort by Browser + + + Sort by Country + + + Sort by Date Newest First + + + Sort by Date Oldest First + + + Speech Bubbles + + + Start Chat + + + Theme Color + + + Ticketing + + + Ticketing Enabled + + + Title Color + + + Toggle Fullscreen + + + Top + + + Top Title + + + Transcript Email Template + + + Update + + + Update Agent + + + Agent has been updated successfully. + + + Update Department + + + Department has been updated successfully. + + + Use Html + + + Vertical Position + + + Viewing + + + Visitor + + + Is Chatting... + + + Visitor List + + + Visitors Online is not enabled! for tracking the visitors it must enabled! + + + Visitors Online Enabled + + + Widget Position + + + Customize live chat widget and minimize button + + + Widget Settings + + + Widget Settings is not enabled! + + + Window Size + + + Yes + + + You can use html and css. + + + Visitor is typing... + + \ No newline at end of file diff --git a/LiveChat/App_LocalResources/Home.resx b/LiveChat/App_LocalResources/Home.resx new file mode 100644 index 0000000..874cf9d --- /dev/null +++ b/LiveChat/App_LocalResources/Home.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Admin Panel + + \ No newline at end of file diff --git a/LiveChat/App_LocalResources/SharedResources.resx b/LiveChat/App_LocalResources/SharedResources.resx new file mode 100644 index 0000000..6722f30 --- /dev/null +++ b/LiveChat/App_LocalResources/SharedResources.resx @@ -0,0 +1,483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Actions + + + Add Agent + + + Agent has been created successfully. + + + Add Department + + + Department has been created successfully. + + + Add New Agent + + + Add New Department + + + Advanced Search + + + Thanks for the message! We'll get back to you as soon as we can. + + + the agent has gone offline. + + + Agent(s) + + + All + + + Anonymous + + + Are you sure? + + + Ask us anything + + + Bad + + + Ban Visitor + + + Browser + + + Cancel + + + Chat + + + Chat rated Bad + + + Chat rated Good + + + Chat rating removed + + + Chat started + + + Chat Transcript + + + Current Chat + + + Date + + + Delete + + + After deleted agent, history is not deleted + + + Agent has been removed successfully. + + + If the department have agents you can not delete department + + + You can not removed department! + + + Department has been removed successfully. + + + Department + + + Department(s) + + + Detected language + + + Disconnect + + + Dismiss + + + Done! + + + {0} is exists. + + + Edit + + + Email + + + Email sent to + + + Email Transcript + + + To minimize this chat instead, click the minimize button or outside the chat window + + + End Chat? + + + End Chat + + + Error + + + Export Transcript + + + Filter by agents... + + + Filter by departments... + + + Filter by visitor email... + + + From date... + + + Good + + + History + + + Hour + + + hour + + + hr + + + Hour(s) + + + Introduce Yourself + + + IpAddress + + + Live Chat Request... + + + Live Support + + + Location + + + Message: + + + Placeholder + + + Messages + + + Min + + + Offline + + + Online + + + Minute + + + Minutes + + + Name + + + No + + + No Messages... + + + Not Now + + + of + + + offline + + + We are offline, but if you leave your message and contact details, we will try to get back to you =) + + + Offline Message from + + + online + + + Options + + + Past Chats + + + Past Visits + + + Platform + + + You're listening to this chat. Click here to join the chat... + + + Please wait until the agent connect to you... + + + Leave a question or comment and our agents will try to attend to you shortly =) + + + Are you sure? + + + Purge History + + + Rating + + + Reconnecting... + + + Referrer + + + Resend + + + Select action + + + What we can help with? + + + Send Email + + + Send Message + + + Serve requests + + + Showing + + + Start Chat + + + Support + + + Time On Site + + + to + + + To date... + + + Transcript + + + Translate + + + TranslateChat + + + Type your message here + + + Unread + + + Update Agent + + + Agent has been updated successfully. + + + Update Department + + + Department has been updated successfully. + + + UserAgent + + + User Info + + + Viewing: + + + Are you sure you want to end this chat? + + + Visitor Path + + + Write a message... + + + Yes + + \ No newline at end of file diff --git a/LiveChat/App_Start/DnnFeatureController.cs b/LiveChat/App_Start/DnnFeatureController.cs new file mode 100644 index 0000000..4d90e13 --- /dev/null +++ b/LiveChat/App_Start/DnnFeatureController.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Upgrade; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Content.Taxonomy; +using System.Linq; + +namespace MyDnn.Modules.Support.LiveChat.App_Start +{ + public class DnnFeatureController : IUpgradeable + { + public string UpgradeModule(string version) + { + SetUrlFriendly(); + + return "Update mydnn support livechat!."; + } + + private static void SetUrlFriendly() + { + HostController.Instance.Update("AUM_DoNotRewriteRegEx", "/signalr", true); + } + } +} \ No newline at end of file diff --git a/LiveChat/App_Start/PreApplicationStartCode.cs b/LiveChat/App_Start/PreApplicationStartCode.cs new file mode 100644 index 0000000..7847328 --- /dev/null +++ b/LiveChat/App_Start/PreApplicationStartCode.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using Microsoft.Web.Infrastructure.DynamicModuleHelper; +using MyDnn.Modules.Support.LiveChat.App_Start; + +[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")] +namespace MyDnn.Modules.Support.LiveChat.App_Start +{ + public class PreApplicationStartCode + { + public static void Start() + { + // Register our module + DynamicModuleUtility.RegisterModule(typeof(MyDnnVisitorsOnlineHttpModule)); + } + } + + public class MyDnnVisitorsOnlineHttpModule : IHttpModule + { + #region IHttpModule Members + + public void Dispose() + { + } + + public void Init(HttpApplication context) + { + context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute); + } + + #endregion + + protected void context_PreRequestHandlerExecute(object sender, EventArgs e) + { + try + { + HttpContext currentContext = HttpContext.Current; + Page page = currentContext.CurrentHandler as Page; + + if (page != null) + { + page.LoadComplete += new EventHandler(page_LoadComplete); + } + } + catch (Exception) + { + } + } + + protected void page_LoadComplete(object sender, EventArgs e) + { + try + { + Page page = sender as Page; + + if (page.IsCallback == false && page.IsPostBack == false) + { + if (!page.ClientScript.IsClientScriptIncludeRegistered("MyDnnSupportLiveChatWidget")) + { + page.ClientScript.RegisterClientScriptInclude("MyDnnSupportLiveChatWidget", DotNetNuke.Common.Globals.ResolveUrl("~/DesktopModules/MVC/MyDnnSupport/LiveChat/Scripts/init-widget.js")); + } + } + } + catch (Exception) + { + } + } + } +} \ No newline at end of file diff --git a/LiveChat/App_Start/RouteMapper.cs b/LiveChat/App_Start/RouteMapper.cs new file mode 100644 index 0000000..5bfe98c --- /dev/null +++ b/LiveChat/App_Start/RouteMapper.cs @@ -0,0 +1,14 @@ +using System.Web.Routing; +using DotNetNuke.Web.Api; +using System; + +namespace MyDnn.Modules.Support.LiveChat.App_Start +{ + public class RouteMapper : IServiceRouteMapper + { + public void RegisterRoutes(IMapRoute mapRouteManager) + { + mapRouteManager.MapHttpRoute("MyDnnSupport.LiveChat", "default", "{controller}/{action}", new[] { "MyDnn.Modules.Support.LiveChat.Services" }); + } + } +} \ No newline at end of file diff --git a/LiveChat/ClientApp/Controllers/agent-controller.js b/LiveChat/ClientApp/Controllers/agent-controller.js new file mode 100644 index 0000000..403b47e --- /dev/null +++ b/LiveChat/ClientApp/Controllers/agent-controller.js @@ -0,0 +1,184 @@ +app.controller("agentController", function ($scope, $http, $timeout, $filter, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'manage', Child: 'agents' }); + + var timeOut = false; + var $self = { + Headers: { + ModuleId: mydnnSupportLiveChat.ModuleID, + TabId: mydnnSupportLiveChat.TabID, + } + }; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + $scope.agent = {}; + $scope.checkValidate = false; + $scope.winTitle = ""; + $scope.isSearchReady = false; + $scope.isAgentEdit = false; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetAgents", { headers: $self.Headers }).success(function (data) { + $scope.agents = data; + $timeout(function () { $scope.isSearchReady = true; }, 1000); + }).error(function (data, status, headers, config) { + angular.element('#tblagents > tbody').html(''.replace("{0}", data)); + }); + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetNamesOfDepartments", { headers: $self.Headers }).success(function (data) { + $scope.departments = data; + }); + + //page events + $scope.onEditAgentClick = function (agent) { + if (!agent) { + $scope.agent = { + Enabled: true + }; + $scope.winTitle = $scope.localizeString["AddNewAgent.Text"]; + $scope.isAgentEdit = false; + } + else { + $scope.agent = angular.copy(agent); + $scope.winTitle = $scope.localizeString["Edit.Text"] + " " + $scope.agent.DisplayName; + $scope.isAgentEdit = true; + } + + $scope.checkValidate = false; + $('#wnEditAgent').modal('show'); + + setTimeout(function () { + $scope.$broadcast('newItemAdded'); + }, 500); + }; + + $scope.onDeleteAgentClick = function (agentID, index) { + swal({ + title: $scope.localizeString["AreYouSure.Text"], + text: $scope.localizeString["DeleteAgentConfirm.Text"], + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: $scope.localizeString["Yes.Text"], + cancelButtonText: $scope.localizeString["No.Text"], + closeOnConfirm: false, + animation: false + }, function () { + var data = { + ID: agentID + }; + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/DeleteAgent", data, { headers: $self.Headers }).success(function (data) { + $scope.agents.splice(index, 1); + $scope.agent = {}; + swal({ + title: $scope.localizeString["Done.Text"], + text: $scope.localizeString["DeleteAgentMsg.Text"], + type: "success", + timer: 3000 + }); + }).error(function (data, status, headers, config) { + swal({ + title: $scope.localizeString["Error.Text"], + text: data, + type: "error", + }); + swal($scope.localizeString["Error.Text"], data, "error"); + }); + }); + }; + + $scope.onUpdateAgentClick = function () { + $scope.checkValidate = true; + if ($scope.agentForm.$valid && $scope.agent.UserID) { + if ($scope.agent.AgentID) + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/UpdateAgent", $scope.agent, { headers: $self.Headers }).success(function (data) { + swal({ + title: $scope.localizeString["Done.Text"], + text: $scope.localizeString["UpdateAgentMsg.Text"], + type: "success", + timer: 3000 + }); + + $('#wnEditAgent').modal('hide'); + + var agent = $filter('filter')($scope.agents, function (d) { return d.AgentID === $scope.agent.AgentID; })[0]; + var index = $scope.agents.indexOf(agent); + $scope.agents[index] = $scope.agent; + + $scope.agent = {}; + }).error(function (data, status, headers, config) { + swal({ + title: $scope.localizeString["Error.Text"], + text: data, + type: "error", + }); + }); + else + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/AddAgent", $scope.agent, { headers: $self.Headers }).success(function (data) { + swal({ + title: $scope.localizeString["Done.Text"], + text: $scope.localizeString["AddAgentMsg.Text"], + type: "success", + timer: 3000 + }); + + $('#wnEditAgent').modal('hide'); + + $scope.agent = data.Agent; + $scope.agents.push($scope.agent); + + $scope.agent = {}; + }).error(function (data, status, headers, config) { + swal({ + title: $scope.localizeString["Error.Text"], + text: data, + type: "error", + }); + }); + + $scope.departmentsFilter = undefined; + } + }; + + // autocomplete for displayname + $scope.getUserByDisplayName = function (val) { + return $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetUserByDisplayName", { + headers: $self.Headers, + params: { + name: val + } + }).then(function (response) { + return response.data; + }); + + $scope.agent.UserID = 0; + }; + + $scope.setUserID = function (agent) { + $scope.agent.UserID = agent.UserID; + } + + //Search functions + $scope.filterModel = ''; + $scope.$watch('filterModel', function () { + if (timeOut) $timeout.cancel(timeOut) + + timeOut = $timeout(function () { + if ($scope.isSearchReady) + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/SearchAgents", { params: { searchType: 1, filter: $scope.filterModel }, headers: $self.Headers }).success(function (data) { + $scope.agents = data; + }); + }, 500) + }); + + $scope.onClearFilterClick = function () { + $scope.filterModel = ""; + }; + + $scope.$watch('departmentsFilter', function () { + if ($scope.departmentsFilter) { + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/SearchAgents", { params: { searchType: 2, filter: $scope.departmentsFilter.join(",") }, headers: $self.Headers }).success(function (data) { + $scope.agents = data; + }); + } + }); +}); + diff --git a/LiveChat/ClientApp/Controllers/department-controller.js b/LiveChat/ClientApp/Controllers/department-controller.js new file mode 100644 index 0000000..5e86725 --- /dev/null +++ b/LiveChat/ClientApp/Controllers/department-controller.js @@ -0,0 +1,148 @@ +app.controller("departmentController", function ($scope, $location, $http, $timeout, $filter, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'manage', Child: 'departments' }); + + var $self = { + Headers: { + ModuleId: mydnnSupportLiveChat.ModuleID, + TabId: mydnnSupportLiveChat.TabID, + } + }; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + $scope.department = {}; + $scope.checkValidate = false; + $scope.winTitle = ""; + $scope.isSearchReady = false; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetDepartments", { headers: $self.Headers }).success(function (data) { + $scope.departments = data; + $timeout(function () { $scope.isSearchReady = true; }, 1000); + }).error(function (data, status, headers, config) { + angular.element('#tblDepartments > tbody').html(''.replace("{0}", data)); + }); + + //page events + $scope.onEditDepartmentClick = function (department) { + if (!department) { + $scope.department = {}; + $scope.winTitle = $scope.localizeString["AddNewDepartment.Text"]; + } + else { + $scope.department = angular.copy(department); + $scope.winTitle = $scope.localizeString["Edit.Text"] + " " + $scope.department.DisplayName; + } + + $scope.checkValidate = false; + $('#wnEditDepartment').modal('show'); + + setTimeout(function () { + $scope.$broadcast('newItemAdded'); + }, 500); + }; + + $scope.onDeleteDepartmentClick = function (departmentID, index) { + swal({ + title: $scope.localizeString["AreYouSure.Text"], + text: $scope.localizeString["DeleteDepartmentConfirm.Text"], + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: $scope.localizeString["Yes.Text"], + cancelButtonText: $scope.localizeString["No.Text"], + closeOnConfirm: false, + animation: false + }, function () { + var data = { + ID: departmentID + }; + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/DeleteDepartment", data, { headers: $self.Headers }).success(function (data) { + $scope.departments.splice(index, 1); + $scope.department = {}; + swal({ + title: $scope.localizeString["Done.Text"], + text: $scope.localizeString["DeleteDepartmentMsg.Text"], + type: "success", + timer: 3000 + }); + }).error(function (data, status, headers, config) { + swal({ + title: $scope.localizeString["Error.Text"], + text: data, + type: "error", + }); + }); + }); + }; + + $scope.onUpdateDepartmentClick = function () { + $scope.checkValidate = true; + if ($scope.departmentForm.$valid) { + if ($scope.department.DepartmentID) { + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/UpdateDepartment", $scope.department, { headers: $self.Headers }).success(function (data) { + swal({ + title: $scope.localizeString["Done.Text"], + text: $scope.localizeString["UpdateDepartmentMsg.Text"], + type: "success", + timer: 3000 + }); + + $('#wnEditDepartment').modal('hide'); + + var department = $filter('filter')($scope.departments, function (d) { return d.DepartmentID === $scope.department.DepartmentID; })[0]; + var index = $scope.departments.indexOf(department); + $scope.departments[index] = $scope.department; + + $scope.department = {}; + }).error(function (data, status, headers, config) { + swal({ + title: $scope.localizeString["Error.Text"], + text: data, + type: "error", + }); + }); + } + else { + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/AddDepartment", $scope.department, { headers: $self.Headers }).success(function (data) { + swal({ + title: $scope.localizeString["Done.Text"], + text: $scope.localizeString["AddDepartmentMsg.Text"], + type: "success", + timer: 3000 + }); + + $('#wnEditDepartment').modal('hide'); + + $scope.department.DepartmentID = data.DepartmentID; + $scope.departments.push($scope.department); + + $scope.department = {}; + }).error(function (data, status, headers, config) { + swal({ + title: $scope.localizeString["Error.Text"], + text: data, + type: "error", + }); + }); + } + } + }; + + //Search functions + var timer = false; + $scope.filterModel = ''; + $scope.$watch('filterModel', function () { + if (timer) { + $timeout.cancel(timer) + } + timer = $timeout(function () { + if ($scope.isSearchReady) + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/SearchDepartments", { headers: $self.Headers, params: { filter: $scope.filterModel } }).success(function (data) { + $scope.departments = data; + }); + }, 500) + }); + $scope.onClearFilterClick = function () { + $scope.filterModel = ""; + }; +}); + diff --git a/LiveChat/ClientApp/Controllers/history-controller.js b/LiveChat/ClientApp/Controllers/history-controller.js new file mode 100644 index 0000000..56fd70f --- /dev/null +++ b/LiveChat/ClientApp/Controllers/history-controller.js @@ -0,0 +1,278 @@ +app.controller("historyController", function ($scope, $http, $timeout, $filter, $location, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'history' }); + + var filterTimeOut; + var $self = { + Headers: { + ModuleId: mydnnSupportLiveChat.ModuleID, + TabId: mydnnSupportLiveChat.TabID, + } + }; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + $scope.history = { + LiveChats: [], + Paging: { + PageIndex: 0, + PageSize: 10, + TotalCount: 0 + }, + }; + $scope.filters = { + Type: 0, + Departments: '', + Agents: '', + VisitorEmail: '', + FromDate: '', + ToDate: '', + GoodRate: false, + BadRate: false + }; + $scope.selectedItems = []; + $scope.selectedLiveChat = {}; + $scope.transcriptTab = true; + $scope.filterByRating = false; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetDepartments", { headers: $self.Headers }).success(function (data) { + $scope.departments = data; + }); + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetAgents", { headers: $self.Headers }).success(function (data) { + $scope.agents = data; + }); + + //page events + $scope.onTypeTabClick = function (type) { + $scope.filters.Type = type; + }; + + $scope.onSearchToggleClick = function () { + var $panel = angular.element(".advanced-search"); + if (!$panel.is(':visible')) { + $panel.show(); + $panel.removeClass("animated fadeOutUp"); + $panel.addClass("animated fadeInDown"); + angular.element(".history i.md-expand-more").addClass("hidden"); + angular.element(".history i.md-expand-less").removeClass("hidden"); + } + else { + $panel.removeClass("animated fadeInDown"); + $panel.addClass("animated fadeOutUp"); + angular.element(".history i.md-expand-less").addClass("hidden"); + angular.element(".history i.md-expand-more").removeClass("hidden"); + $timeout(function () { + $panel.hide(); + }, 500); + } + }; + + $scope.onSelectLiveChatChange = function (isAll) { + if (isAll == "true") { + if ($scope.history.AllSelected) + angular.forEach($scope.history.LiveChats, function (object) { + object.Selected = true; + }); + else + angular.forEach($scope.history.LiveChats, function (object) { + object.Selected = false; + }); + } + + $scope.selectedItems = $filter("filter")($scope.history.LiveChats, { Selected: true }); + }; + + $scope.onChangePageSizeClick = function (count) { + $scope.history.Paging.PageSize = count; + runQuery(); + }; + + $scope.onRowLiveChatClick = function (liveChatID) { + if ($scope.selectedLiveChat.LiveChatID != liveChatID) { + $scope.selectedLiveChat.LiveChatID = liveChatID; + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetMessages", { headers: $self.Headers, params: { livechatID: liveChatID } }).success(function (data) { + var result = $filter("filter")($scope.history.LiveChats, { LiveChatID: liveChatID }); + if (result.length) + $scope.selectedLiveChat = angular.copy(result[0]); + + $scope.selectedLiveChat.Messages = data.Messages; + parseLiveChatMessages($scope.selectedLiveChat, data.Messages); + }); + } + }; + + $scope.onActionChange = function () { + if ($scope.action == 'delete') { + swal({ + title: $scope.localizeString["PurgeHistory.Text"], + text: $scope.localizeString["PurgeHistory.Help"], + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: $scope.localizeString["Delete.Text"], + cancelButtonText: $scope.localizeString["Cancel.Text"], + closeOnConfirm: true, + }, function () { + var items = []; + angular.forEach($filter("filter")($scope.history.LiveChats, { Selected: true }), function (object) { + items.push(object.LiveChatID); + }); + + var data = { + Items: items + } + + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/PurgeHistory", data, { headers: $self.Headers }).success(function () { + angular.forEach(data.Items, function (livechatID) { + var result = $filter("filter")($scope.history.LiveChats, { LiveChatID: livechatID }); + if (result.length) { + var livechat = result[0]; + var indx = $scope.history.LiveChats.indexOf(livechat); + $scope.history.LiveChats.splice(indx, 1); + } + }); + swal($scope.localizeString["Done.Text"], $scope.localizeString["DeleteAgentMsg.Text"], "success"); + $scope.action = ""; + + $scope.history.AllSelected = false; + runQuery(); + }).error(function (data, status, headers, config) { + swal($scope.localizeString["Error.Text"], data, "error"); + }); + }); + } + }; + + $scope.onTranscriptTabClick = function (type) { + if (type == "0") + $scope.transcriptTab = true; + if (type == "1") + $scope.transcriptTab = false; + }; + + for (var key in $scope.filters) { + if ($scope.filters.hasOwnProperty(key)) { + $scope.$watch("filters." + key, function (val, oldVal) { + if (val != oldVal) + runQuery(); + }); + } + } + + $scope.onPageClick = function ($index, state) { + if ($scope.history.Paging.PageIndex > 0 && state == 'prev') + $scope.history.Paging.PageIndex--; + else if ($scope.history.Paging.PageIndex < $scope.history.Paging.PageCount && state == 'next') + $scope.history.Paging.PageIndex++; + else + $scope.history.Paging.PageIndex = $index; + + runQuery(); + }; + + $scope.onCloseTranscriptClick = function () { + $scope.selectedLiveChat = {}; + }; + + $scope.$watch("filterByRating", function (val, oldVal) { + if (!val) { + $scope.filters.GoodRate = false; + $scope.filters.BadRate = false; + } + }); + + function runQuery() { + if (filterTimeOut) $timeout.cancel(filterTimeOut); + + filterTimeOut = $timeout(function () { + var f = $scope.filters; + + var departments = ''; + if (f.Departments) + departments = createStringByArray(f.Departments, "DepartmentID"); + + var agents = ''; + if (f.Agents) + agents = createStringByArray(f.Agents, "UserID"); + + var rate = 0; + if ($scope.filterByRating && $scope.filters.GoodRate) + rate++; + if ($scope.filterByRating && $scope.filters.BadRate) + rate += 2; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetChatHistory", { + headers: $self.Headers, + params: { + type: f.Type, + departments: departments, + agents: agents, + visitorEmail: (f.VisitorEmail ? f.VisitorEmail : ''), + fromDate: (f.FromDate ? f.FromDate : ''), + toDate: (f.ToDate ? f.ToDate : ''), + rating: rate, + unread: false, + pageIndex: $scope.history.Paging.PageIndex, + pageSize: $scope.history.Paging.PageSize, + totalCount: $scope.history.Paging.TotalCount + } + }).success(function (data) { + $scope.selectedLiveChat = {}; + + $scope.history.LiveChats = data.LiveChats; + $scope.history.Paging = data.Paging; + + for (var i = 0; i < $scope.history.LiveChats.length; i++) { + parseVisitorItems($scope.history.LiveChats[i]); + } + }); + }, 250); // delay 250 ms + } + + function createStringByArray(array, key) { + var output = ''; + angular.forEach(array, function (object) { + output += object[key] + ','; + }); + return output; + } + + runQuery(); + + function parseLiveChatMessages(livechat, messages) { + for (var i = 0; i < messages.length; i++) { + parseLiveChatMessage(livechat, messages[i]); + } + } + + function parseLiveChatMessage(livechat, message) { + if (message.SentBy == 1) { //if visitor is sender message + message.SenderDisplayName = livechat.Visitor.DisplayName; + } + else if (message.SentBy == 2) { //if agent is sender message + var agent = $filter("filter")(livechat.Agents, { UserID: message.AgentUserID })[0]; + message.SenderDisplayName = agent.DisplayName; + } + message.Time = moment(message.CreateDate).format('h:mm a'); + } + + function parseVisitorItems(livechat) { + parseIpLocation(livechat.LiveChatID, livechat.Visitor.IP); + + var parser = new UAParser(); + parser.setUA(livechat.Visitor.UserAgent); + livechat.Visitor.UserAgentData = parser.getResult(); + } + + function parseIpLocation(id, ip) { + if (ip == "127.0.0.1") ip = ""; + $.getJSON("http://freegeoip.net/json/" + ip, function (data) { + var result = $filter("filter")($scope.history.LiveChats, { LiveChatID: id }); + if (result.length) { + var indx = $scope.history.LiveChats.indexOf(result[0]); + $scope.history.LiveChats[indx].Visitor.Location = data; + if ($scope.selectedLiveChat.Visitor) $scope.selectedLiveChat.Visitor.Location = data; + } + }); + } +}); + diff --git a/LiveChat/ClientApp/Controllers/home-controller.js b/LiveChat/ClientApp/Controllers/home-controller.js new file mode 100644 index 0000000..14eba59 --- /dev/null +++ b/LiveChat/ClientApp/Controllers/home-controller.js @@ -0,0 +1,3 @@ +app.controller("homeController", function ($scope, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'home' }); +}); \ No newline at end of file diff --git a/LiveChat/ClientApp/Controllers/livechat-agent-controller.js b/LiveChat/ClientApp/Controllers/livechat-agent-controller.js new file mode 100644 index 0000000..a409e81 --- /dev/null +++ b/LiveChat/ClientApp/Controllers/livechat-agent-controller.js @@ -0,0 +1,468 @@ +app.controller("livechatAgentController", function ($scope, $window, $location, $http, $interval, $timeout, $filter, localizationService, HubProxy) { + var siteRoot = mydnnSupportLiveChat.SiteRoot; + var portalID = mydnnSupportLiveChat.PortalID; + var currentCulture = mydnnSupportLiveChat.CurrentCulture; + var clearKeyPress = true; + var timerCalculator; + var me; + + $scope.currentLiveChat = 0; + $scope.livechats = []; + $scope.serveRequests = []; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + + if (localStorage["MyDnnVisitorsOnline_VisitorGUID"] == null) { + localStorage["MyDnnVisitorsOnline_VisitorGUID"] = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + var visitorGUID = localStorage["MyDnnVisitorsOnline_VisitorGUID"]; + + //events + $scope.onServeRequestsClick = function () { + for (var i = 0; i < $scope.serveRequests.length; i++) { + hub.invoke('InitialLiveChatForAgent', $scope.serveRequests[i].LiveChatID, false); + } + }; + + $scope.onLiveChatButtonClick = function ($event, id) { + if ($scope.currentLiveChat != id) + $scope.currentLiveChat = id; + else + $scope.currentLiveChat = 0; + + $event.stopPropagation(); + }; + + $scope.onMinimizeLiveChat = function () { + $scope.currentLiveChat = 0; + }; + + $scope.onCloseLiveChat = function (livechatID) { + var result = $filter("filter")($scope.livechats, { LiveChatID: livechatID }); + if (result.length) { + var indx = $scope.livechats.indexOf(result[0]); + if ($filter("filter")($scope.livechats, { Agents: { UserID: me.UserID } }).length) { + swal({ + title: $scope.localizeString["EndChat.Text"], + text: $scope.localizeString["EndChat.Help"], + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: $scope.localizeString["EndChat.Text"], + cancelButtonText: $scope.localizeString["Cancel.Text"], + closeOnConfirm: true, + }, function () { + hub.invoke('CloseLiveChatByAgent', portalID, livechatID); + $scope.livechats.splice(indx, 1); + }); + } + else + $scope.livechats.splice(indx, 1); + } + }; + + $scope.onStartChatClick = function (livechatID) { + hub.invoke('StartLiveChatByAgent', livechatID); + }; + + $scope.onMessageEditorKeypress = function ($event, livechatID) { + if ($event.which === 13 && clearKeyPress) { + var livechat = $filter("filter")($scope.livechats, { LiveChatID: livechatID })[0]; + + var message = { + MessageID: -1, + LiveChatID: livechat.LiveChatID, + CreateDate: new Date(), + SentBy: 2, + AgentUserID: me.UserID, + MessageType: 0, + Message: livechat.NewMessage + }; + + livechat.NewMessage = ''; + + parseLiveChatMessage(livechat, message); + livechat.Messages.push(message); + + $scope.$broadcast("onScrollBottom", { id: livechat.LiveChatID }); + + if (clearKeyPress) { + clearKeyPress = false; + + sendMessage(livechat, message); + + $timeout(function () { + clearKeyPress = true; + }, 100); + } + + $event.preventDefault(); + + return false; + } + }; + + $scope.onLiveChatWinClick = function ($event) { + $event.stopPropagation(); + }; + + $scope.onLiveChatWinMouseDown = function ($event) { + if ($event.which == 3) { + alert("!"); + $event.stopPropagation(); + } + }; + + angular.element($window).bind('click', function ($event) { + $scope.$apply(function ($event) { + $scope.currentLiveChat = 0; + angular.element(".mydnn-livechats").hide(); + }); + }); + + $scope.$watch('currentLiveChat', function () { + if ($scope.currentLiveChat) { + angular.element(".mydnn-livechats").show(); + + var result = $filter("filter")($scope.livechats, { LiveChatID: $scope.currentLiveChat }); + if (result.length) { + var livechat = result[0]; + + livechat.UnReadMessages = 0; + + seenMessages(livechat); + } + + $timeout(function () { + $scope.$broadcast('newItemAdded'); + }, 500); + } + else { + $(".livechat-window").one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function (e) { + if ($scope.currentLiveChat == 0) angular.element(".mydnn-livechats").hide(); + }); + } + }); + + //signalR + var hub = new HubProxy('MyDnnSupportLiveChatHub'); + hub.on('incomingLiveChat', function (livechatID, visitorGUID, message, mode) { + var result = ($filter("filter")($scope.serveRequests, { LiveChatID: livechatID })); + if (!result.length && mode == "add") { + $scope.$root.$broadcast("onIncomingLiveChat", { livechatID: livechatID, visitorGUID: visitorGUID, message: message }); + + var req = { + LiveChatID: livechatID, + VisitorGUID: visitorGUID + }; + $scope.serveRequests.push(req); + } + else if (result.length && mode == "remove") { + var indx = $scope.serveRequests.indexOf(result[0]); + $scope.serveRequests.splice(indx, 1); + } + }); + + hub.on('visitorIsInChatting', function (visitorGUID) { + $scope.$root.$broadcast("onVisitorIsChatting", { visitorGUID: visitorGUID }); + }); + + hub.on('initialLiveChatForAgent', function (livechat) { + if (livechat) { + parseVisitorItems(livechat); + parseLiveChatMessages(livechat, livechat.Messages); + $scope.livechats.push(livechat); + if ($scope.currentLiveChat == 0) + $scope.currentLiveChat = livechat.LiveChatID; + } + }); + + hub.on('reciveMessage', function (message) { + var livechatID = message.LiveChatID; + + var result = $filter("filter")($scope.livechats, { LiveChatID: livechatID }); + if (result.length) { + var livechat = result[0]; + reciveMessage(livechat, message); + } + else + hub.invoke('InitialLiveChatForAgent', livechatID); + }); + + hub.on('visitorIsTyping', function (livechatID) { + var result = $filter("filter")($scope.livechats, { LiveChatID: livechatID }); + if (result.length) { + var livechat = result[0]; + livechat.VisitorIsTyping = true; + $timeout(function () { + livechat.VisitorIsTyping = false; + }, 4000); + } + }); + + hub.on('removeLiveChat', function (livechatID) { + result = ($filter("filter")($scope.livechats, { LiveChatID: livechatID })); + if (result.length) { + var livechat = result[0]; + indx = $scope.livechats.indexOf(livechat); + $scope.livechats.splice(indx, 1); + } + }); + + hub.on('agentHasJoin', function (livechatID, agent) { + var result = $filter("filter")($scope.livechats, { LiveChatID: livechatID }); + if (result.length) { + var livechat = result[0]; + livechat.Agents.push(agent); + livechat.ChatStarted = true; + } + }); + + hub.on('closeLiveChatByAgent', function (livechatID) { + var result = $filter("filter")($scope.livechats, { LiveChatID: livechatID }); + if (result.length) { + var livechat = result[0]; + livechat.IsClosed = true; + } + }); + + hub.on('closeLiveChatByVisitor', function (livechatID) { + var result = $filter("filter")($scope.livechats, { LiveChatID: livechatID }); + if (result.length) { + var livechat = result[0]; + livechat.IsClosed = true; + } + + //remove from incoming chats... + result = $filter("filter")($scope.serveRequests, { LiveChatID: livechatID }); + if (result.length) { + request = result[0]; + var indx = $scope.serveRequests.indexOf(request); + $scope.serveRequests.splice(indx, 1); + } + }); + + hub.start().done(function () { + joinAgent(); + }); + + hub.connection.reconnected(function () { + joinAgent(); + }); + + hub.connection.disconnected(function () { + $timeout(function () { + joinAgent(); + }, 5000); + }); + + function joinAgent() { + hub.invoke('JoinAgent', portalID, true, true).then(function (data) { + if (data.Me) + me = data.Me; + + if (data.LiveChats) { + $scope.livechats = data.LiveChats; + for (var i = 0; i < $scope.livechats.length; i++) { + parseVisitorItems($scope.livechats[i]); + parseLiveChatMessages($scope.livechats[i], $scope.livechats[i].Messages); + } + } + if (data.IncomingLiveChats) + $scope.serveRequests = data.IncomingLiveChats; + }); + } + + function sendMessage(livechat, message) { + hub.invoke('SendMessage', portalID, message, livechat.IsClosed).then(function (messageID) { + if (messageID != -1) { + message.MessageID = messageID; + message.Resend = false; + } + else + message.Resend = true; // message not saved in database + }); + } + + function reciveMessage(livechat, message) { + livechat.VisitorIsTyping = false; + + parseLiveChatMessage(livechat, message); + livechat.Messages.push(message); + + if ($scope.currentLiveChat != livechat.LiveChatID) + livechat.UnReadMessages = (livechat.UnReadMessages == undefined ? 1 : livechat.UnReadMessages + 1); + + $scope.$broadcast("onScrollBottom", { id: livechat.LiveChatID }); + + if (checkPageFocus() && $scope.currentLiveChat == livechat.LiveChatID) { + seenMessage(message); + } + } + + function seenMessages(livechat) { + for (var i = 0; i < livechat.Messages.length; i++) { + var message = livechat.Messages[i]; + seenMessage(message); + } + } + + function seenMessage(message) { + if (message.SentBy != 2 && !message.Seen) { + message.Seen = true; + hub.invoke('SeenMessage', portalID, message); + } + } + + //private functions + function parseVisitorItems(livechat) { + livechat.Visitor.OnlineTime = getTimeDiff(livechat.Visitor.OnlineDate, moment()); + + parseIpLocation(livechat.LiveChatID, livechat.Visitor.IP); + + var parser = new UAParser(); + parser.setUA(livechat.Visitor.UserAgent); + livechat.Visitor.UserAgentData = parser.getResult(); + } + + function parseIpLocation(id, ip) { + if (ip == "127.0.0.1") ip = ""; + $.getJSON("http://freegeoip.net/json/" + ip, function (data) { + var result = $filter("filter")($scope.livechats, { LiveChatID: id }); + if (result.length) { + var indx = $scope.livechats.indexOf(result[0]); + $scope.livechats[indx].Visitor.Location = data; + } + }); + } + + function parseLiveChatMessages(livechat, messages) { + for (var i = 0; i < messages.length; i++) { + parseLiveChatMessage(livechat, messages[i]); + } + } + + function parseLiveChatMessage(livechat, message) { + if (message.SentBy == 1) { //if visitor is sender message + message.SenderDisplayName = livechat.Visitor.DisplayName; + message.SenderAvatar = livechat.Visitor.Avatar; + message.IsMyMessage = false; + } + else if (message.SentBy == 2) { //if agent is sender message + var agent; + if (message.AgentUserID == me.UserID) + agent = me; + else + agent = $filter("filter")(livechat.Agents, { UserID: message.AgentUserID })[0]; + + message.SenderDisplayName = agent.DisplayName; + message.SenderAvatar = agent.Avatar; + message.IsMyMessage = true; + } + } + + function offlineVisitor(visitorGUID) { + var result = $filter("filter")($scope.livechats, { Visitor: { VisitorGUID: visitorGUID } }); + + var livechatID = 0; + + if (result.length) { //check live chats... + var livechat = result[0]; + var indx = $scope.livechats.indexOf(livechat); + $scope.livechats[indx].Visitor.IsOffline = true; + + livechatID = livechat.LiveChatID; + } + else { // check incoming chats... + result = $filter("filter")($scope.serveRequests, { VisitorGUID: visitorGUID }); + if (result.length) { + request = result[0]; + var indx = $scope.serveRequests.indexOf(request); + $scope.serveRequests.splice(indx, 1); + + livechatID = request.LiveChatID; + } + } + + if (livechatID) + hub.invoke('VisitorHasLeftChat', livechatID); + } + + function calcVisitorsOnlineTime() { + timerCalculator = $interval(function () { + for (var i = 0; i < $scope.livechats.length; i++) { + var livechat = $scope.livechats[i]; + livechat.Visitor.OnlineTime = getTimeDiff(livechat.Visitor.OnlineDate, moment()); + } + }, 59000); + } + + function getTimeDiff(onlineT, nowT) { + var diff = nowT.diff(onlineT, 'minutes'); + var lbl = $scope.localizeString["Min.Text"] + if (diff >= 60) { + diff = nowT.diff(onlineT, 'hours'); + lbl = $scope.localizeString["HourMin.Text"] + } + return diff + ' ' + lbl; + } + + function checkPageFocus() { + if (typeof document.hasFocus === 'function') + return document.hasFocus(); + else + return false; + } + + /////////////////////////////////////////////////// + // signalR for visitors online hub + var vHub = new HubProxy('MyDnnVisitorsOnlineHub'); + vHub.on('populateVisitorsOnline', function (visitor) { + $scope.$root.$broadcast("onPopulateVisitorsOnline", { visitor: visitor }); + }); + vHub.on('updateVisitorInfo', function (visitor) { + $scope.$root.$broadcast("onUpdateVisitorInfo", { visitor: visitor }); + }); + vHub.on('populateVisitorsOffline', function (visitors) { + $scope.$root.$broadcast("onPopulateVisitorsOffline", { visitors: visitors }); + for (var i = 0; i < visitors.length; i++) { + offlineVisitor(visitors[i].VisitorGUID); + } + }); + vHub.start().done(function () { + vHub.invoke('JoinVisitor', portalID, visitorGUID, '', '', ''); + vHub.invoke('JoinGroup', 'MyDnnVisitorsOnline'); + }); + vHub.connection.reconnected(function () { + vHub.invoke('JoinVisitor', portalID, visitorGUID, '', '', ''); + }); + vHub.connection.disconnected(function () { + $timeout(function () { + vHub.invoke('JoinVisitor', portalID, visitorGUID, '', '', ''); + }, 5000); + }); + $interval(function () { + vHub.invoke('Ping', portalID, visitorGUID, '', '', ''); + }, 35000); + /////////////////////////////////////////////////// + + function onFocus() { + if ($scope.currentLiveChat) { + var result = $filter("filter")($scope.livechats, { LiveChatID: $scope.currentLiveChat }); + if (result.length) { + var livechat = result[0]; + seenMessages(livechat); + } + } + }; + + if (/*@cc_on!@*/false) { // check for Internet Explorer + document.onfocusin = onFocus; + } else { + window.onfocus = onFocus; + } +}); + diff --git a/LiveChat/ClientApp/Controllers/livechat-visitor-controller.js b/LiveChat/ClientApp/Controllers/livechat-visitor-controller.js new file mode 100644 index 0000000..9d4dfe1 --- /dev/null +++ b/LiveChat/ClientApp/Controllers/livechat-visitor-controller.js @@ -0,0 +1,452 @@ +angular.module('MyDnnSupportLiveChatApp', ['services.hub', 'ngMyDnnServices']) +.controller("livechatController", function ($scope, $location, $http, $interval, $timeout, $window, $compile, $filter, HubProxy) { + var rootUrl = mydnnLiveChatBaseData.RootUrl; + var visitorGUID = mydnnLiveChatBaseData.VisitorGUID; + var portalID; + var isTyping = false; + + $scope.livechat = {}; + $scope.livechatFormValidate = false; + $scope.waiting = false; + + $http.get(rootUrl + "DesktopModules/MyDnnSupport.LiveChat/API/VisitorService/InitialLiveChat", { params: { visitorGUID: visitorGUID } }).success(function (data) { + portalID = data.PortalID; + + $scope.WidgetHtml = data.Widget; + + $scope.localizeString = data.Resources; + $scope.widgetSettings = data.Settings; + $scope.isAgentOnline = data.IsAgentOnline; + $scope.departments = data.Departments; + + $scope.livechat.Step = "prechat"; + $scope.livechat.ConnectionState = 1; + $scope.livechat.LiveChatID = -1; + $scope.livechat.Visitor = { VisitorGUID: visitorGUID, UserID: data.UserID }; + $scope.livechat.Departments = []; + $scope.livechat.Agents = []; + $scope.livechat.WidgetMinimized = false; + + if (data.UserID != -1) { + $scope.livechat.Visitor.DisplayName = data.DisplayName; + $scope.livechat.Visitor.Email = data.Email; + } + else { + var name = getCookie("MyDnnSupportLiveChatName"); + var email = getCookie("MyDnnSupportLiveChatEmail"); + if (name) $scope.livechat.Visitor.DisplayName = name; + if (email) $scope.livechat.Visitor.Email = email; + } + + $('body').append(''); + $timeout(function () { + if (typeof jQuery.ui) $(".mydnn-livechat-widget").draggable({ handle: '.livechat-move' }); + }, 200); + }); + + $scope.reloadLiveChat = function () { + $scope.livechat.WidgetMinimized = false; + $http.get(rootUrl + "DesktopModules/MyDnnSupport.LiveChat/API/VisitorService/GetDepartmentsForLiveChat").success(function (data) { + $scope.departments = data.Departments; + $scope.isAgentOnline = data.IsAgentOnline; + $scope.department = null; + }); + }; + + //events + $scope.onLiveChatMinimizeClick = function () { + $scope.livechat.WidgetMinimized = true; + angular.element("#mydnnLiveChatMinButton").show(); + }; + + $scope.onDepartmentChanged = function () { + if ($scope.department) + $http.get(rootUrl + "DesktopModules/MyDnnSupport.LiveChat/API/VisitorService/IsAgentOnlineByDepartment", { params: { departmentID: $scope.department.DepartmentID } }).success(function (isAgentOnline) { + var result = $filter("filter")($scope.departments, { DepartmentID: $scope.department.DepartmentID }); + if (result.length) { + var indx = $scope.departments.indexOf(result[0]); + $scope.departments[indx].IsAgentOnline = isAgentOnline; + } + $scope.isAgentOnline = isAgentOnline; + }); + }; + + $scope.onStartChatClick = function () { + if (!$scope.isAgentOnline) // send offline message + { + sendOfflineMessageEmail(); + return; + } + + $scope.livechatFormValidate = true; + if ($scope.department && $scope.livechatForm.$valid) { + $scope.livechat.Departments = [$scope.department]; + hub.invoke('StartLiveChatByVisitor', $scope.livechat).then(function (livechatID) { + localStorage["MyDnnLiveChatCurrentChat"] = livechatID; + if (livechatID) + $scope.livechat.LiveChatID = livechatID; + else + window.location.reload(); + }); + setCookie("MyDnnSupportLiveChatName", $scope.livechat.Visitor.DisplayName, 1000); + setCookie("MyDnnSupportLiveChatEmail", $scope.livechat.Visitor.Email, 1000); + } + }; + + $scope.onResendMessage = function (message) { + sendMessage(message); + }; + + $scope.onBlurInput = function ($event) { + angular.element($event.target).addClass('control-focused'); + }; + + $scope.onMessageEditorKeypress = function ($event) { + if ($event.which === 13) { + if (!$scope.livechat.NewMessage) return; //empty message + + if (hub.connection.state != 1) { //check hub connected + $scope.livechat.ConnectionState = 2; + return false; + } + + var message = { + MessageID: -1, + LiveChatID: $scope.livechat.LiveChatID, + CreateDate: new Date(), + SentBy: 1, + MessageType: 0, + Message: $scope.livechat.NewMessage + }; + + $scope.livechat.NewMessage = ''; + + sendMessage(message); + + $event.preventDefault(); + } + else { //visitor is typing... + if (!isTyping) { + isTyping = true; + + visitorIsTyping(); + + $timeout(function () { + isTyping = false; + }, 4000); + } + } + }; + + $scope.onChatRateClick = function (rate) { + if (rate == $scope.livechat.Rate) + rate = 0; + + hub.invoke('RateChat', $scope.livechat.LiveChatID, rate).then(function (isSuccess) { + $scope.livechat.Rate = rate; + + var message = { + MessageID: -1, + LiveChatID: $scope.livechat.LiveChatID, + CreateDate: new Date(), + SentBy: 0, + MessageType: 0, + Message: rate == 0 ? $scope.localizeString["ChatRatingRemoved.Text"] : (rate == 1 ? $scope.localizeString["ChatRatedGood.Text"] : $scope.localizeString["ChatRatedBad.Text"]) + }; + + sendMessage(message); + }); + }; + + $scope.onOptionsClick = function ($event) { + angular.element(".livechat-email-transcript").hide(); + + if (!angular.element(".livechat-popupmenu").is(":visible")) + angular.element(".livechat-popupmenu").fadeIn(50); + else + angular.element(".livechat-popupmenu").fadeOut(50); + + $event.stopPropagation(); + }; + + $scope.onShowEmailClick = function ($event) { + angular.element(".livechat-popupmenu").hide(); + + angular.element(".livechat-email-transcript").fadeIn(50); + + $event.stopPropagation(); + }; + + $scope.onEmailInputClick = function ($event) { + $event.stopPropagation(); + }; + + $scope.onSendEmailClick = function ($event) { + sendTranscriptEmail(); + + $event.stopPropagation(); + }; + + $scope.onBtnEndChatClick = function ($event) { + if (confirm($scope.localizeString["VisitorEndChatConfirm.Text"])) { + hub.invoke('CloseLiveChatByVisitor', portalID, $scope.livechat.LiveChatID); + angular.element(".livechat-popupmenu").fadeOut(50); + } + + $event.stopPropagation(); + }; + + angular.element($window).bind('click', function ($event) { + $scope.$apply(function ($event) { + angular.element(".livechat-popupmenu").fadeOut(50); + angular.element(".livechat-email-transcript").fadeOut(50); + }); + }); + + //signalR + var hub = new HubProxy('MyDnnSupportLiveChatHub'); + hub.on('startLiveChat', function (livechat) { + $scope.livechat = livechat; + parseLiveChatMessages($scope.livechat.Messages); + $scope.livechat.Step = "chatstarted"; + }); + + hub.on('agentHasJoin', function (livechatID, agent) { + if (livechatID == $scope.livechat.LiveChatID) { + var result = $filter("filter")($scope.livechat.Agents, { UserID: agent.UserID }); + if (!result.length) { + $scope.livechat.Agents.push(agent); + } + } + }); + + hub.on('reciveMessage', function (message) { + reciveMessage(message); + }); + + hub.on('seenMessage', function (messageID) { + if ($scope.livechat.LiveChatID) { + var result = $filter("filter")($scope.livechat.Messages, { MessageID: messageID }); + if (result.length) { + result[0].Seen = true; + } + } + }); + + hub.on('closeLiveChatByAgent', function (livechatID) { + closeChat(livechatID); + }); + + hub.on('closeLiveChatByVisitor', function (livechatID) { + closeChat(livechatID); + }); + + hub.start().done(function () { + hub.invoke('JoinVisitor', portalID, visitorGUID).then(function (livechat) { + if (livechat) { + $scope.department = { DepartmentID: livechat.DepartmentID }; + + $scope.livechat = livechat; + $scope.livechat.Step = "chatstarted"; + $scope.livechat.WidgetMinimized = false; + + parseLiveChatMessages($scope.livechat.Messages); + + localStorage["MyDnnLiveChatCurrentChat"] = livechat.LiveChatID; + } + else + localStorage.removeItem("MyDnnLiveChatCurrentChat"); + }); + }); + + hub.connection.reconnecting(function () { + if ($scope.livechat.LiveChatID) { + $scope.livechat.ConnectionState = 2; + } + }); + + hub.connection.reconnected(function () { + if ($scope.livechat.LiveChatID) { + reconnectToLiveChat(); + } + }); + + hub.connection.disconnected(function () { + if ($scope.livechat.LiveChatID) { + $timeout(function () { + hub.start().done(function () { + hub.invoke('JoinVisitor', portalID, visitorGUID); + reconnectToLiveChat(); + }); + }, 5000); + } + }); + + function reconnectToLiveChat() { + $scope.livechat.ConnectionState = 1; + if ($scope.livechat.LiveChatID && !$scope.livechat.IsClosed) { + var lastMessage = $scope.livechat.Messages[$scope.livechat.Messages.length - 1]; + if (lastMessage) { + var lastMessageID = lastMessage.MessageID; + hub.invoke('VisitorReconnectedToLiveChat', portalID, $scope.livechat.LiveChatID, lastMessageID).then(function (data) { + if (data) { + if (data.Messages && data.Messages.length) { + parseLiveChatMessages(data.Messages); + $scope.livechat.Messages.push.apply($scope.livechat.Messages, data.Messages); + } + $scope.livechat.IsClosed = data.IsClosed; + } + }); + } + } + } + + function sendMessage(message) { + $scope.livechat.Messages.push(message); + parseLiveChatMessage(message); + + $scope.$broadcast("onScrollBottom", { id: $scope.livechat.LiveChatID }); + + hub.invoke('SendMessage', portalID, message, $scope.livechat.IsClosed).then(function (messageID) { + if (messageID != -1) { + message.MessageID = messageID; + message.Resend = false; + } + else + message.Resend = true; // message not saved in database + }); + } + + function reciveMessage(message) { + var livechatID = message.LiveChatID; + + if (livechatID == $scope.livechat.LiveChatID) { + $scope.livechat.Messages.push(message); + parseLiveChatMessage(message); + + $scope.$broadcast("onScrollBottom", { id: $scope.livechat.LiveChatID }); + } + } + + function visitorIsTyping() { + hub.invoke('VisitorIsTyping', portalID, $scope.livechat.LiveChatID).then(function (messageID) { + }); + } + + function closeChat(livechatID) { + if ($scope.livechat.LiveChatID == livechatID) { + $scope.livechat.IsClosed = true; + } + + localStorage.removeItem("MyDnnLiveChatCurrentChat"); + } + + function sendTranscriptEmail() { + $scope.waiting = true; + + var emailTemplate = $scope.widgetSettings["TranscriptEmailTemplate"]; + + var html = $compile(emailTemplate)($scope); + $('body').append($('')); + $('#mydnnLiveChatTemp').append(html); + + $timeout(function () { + var data = { + To: $scope.livechat.Visitor.Email, + Subject: $scope.localizeString["ChatTranscript.Text"], + Body: $('#mydnnLiveChatTemp').html() + } + + $http.post(rootUrl + "DesktopModules/MyDnnSupport.LiveChat/API/VisitorService/SendEmail", data).success(function () { + $scope.waiting = false; + alert($scope.localizeString["EmailSentMessage.Text"] + " " + $scope.livechat.Visitor.Email); + angular.element(".livechat-email-transcript").fadeOut(50); + }).error(function (data, status, headers, config) { + $scope.waiting = false; + alert(data); + angular.element(".livechat-email-transcript").fadeOut(50); + }); + + $('#mydnnLiveChatTemp').remove(); + }, 1000); + } + + function sendOfflineMessageEmail() { + alert($scope.localizeString["AfterSendOfflineMessage.Text"]); + + $scope.livechat.WidgetMinimized = true; + angular.element("#mydnnLiveChatMinButton").show(); + $scope.livechatFormValidate = false; + + var emailTemplate = $scope.widgetSettings["OfflineEmailTemplate"]; + + var html = $compile(emailTemplate)($scope); + $('body').append($('')); + $('#mydnnLiveChatTemp').append(html); + + $timeout(function () { + var data = { + DepartmentID: $scope.department.DepartmentID, + To: $scope.livechat.Visitor.Email, + Subject: $scope.localizeString["OfflineMessageFrom.Text"] + " " + $scope.livechat.Visitor.DisplayName, + Body: $('#mydnnLiveChatTemp').html() + } + + $http.post(rootUrl + "DesktopModules/MyDnnSupport.LiveChat/API/VisitorService/SendOfflineMessageEmail", data).success(function () { + }).error(function (data, status, headers, config) { + }); + + $scope.livechat.Message = ''; + + $('#mydnnLiveChatTemp').remove(); + }, 1000); + } + + + //private functions + function parseLiveChatMessages(messages) { + for (var i = 0; i < messages.length; i++) { + parseLiveChatMessage(messages[i]); + } + } + + function parseLiveChatMessage(message) { + if (message.SentBy == 1) { //if visitor is sender message + message.SenderDisplayName = $scope.livechat.Visitor.DisplayName; + message.SenderAvatar = $scope.livechat.Visitor.Avatar; + message.IsMyMessage = true; + } + else if (message.SentBy == 2) { //if agent is sender message + var agent; + agent = $filter("filter")($scope.livechat.Agents, { UserID: message.AgentUserID })[0]; + message.SenderDisplayName = agent.DisplayName; + message.SenderAvatar = agent.Avatar; + message.IsMyMessage = false; + } + message.MsgTime = moment(message.CreateDate).format("hh:mm") + + var indx = $scope.livechat.Messages.indexOf(message); + if (indx > 0) { + var prevMessage = $scope.livechat.Messages[indx - 1]; + if (prevMessage && prevMessage.SentBy == message.SentBy) + message.SenderPrevMessage = true; + } + } + + function setCookie(cname, cvalue, exdays) { + var d = new Date(); + d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); + var expires = "expires=" + d.toGMTString(); + document.cookie = cname + "=" + cvalue + "; " + expires; + } + + function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name) == 0) return c.substring(name.length, c.length); + } + return ""; + } +}); diff --git a/LiveChat/ClientApp/Controllers/setting-controller.js b/LiveChat/ClientApp/Controllers/setting-controller.js new file mode 100644 index 0000000..8465080 --- /dev/null +++ b/LiveChat/ClientApp/Controllers/setting-controller.js @@ -0,0 +1,45 @@ +app.controller("settingController", function ($scope, $http, $timeout, $filter, $location, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'settings', Child: 'basic' }); + + var siteRoot = mydnnSupportLiveChat.SiteRoot; + var $self = { + Headers: { + ModuleId: mydnnSupportLiveChat.ModuleID, + TabId: mydnnSupportLiveChat.TabID, + } + }; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + $scope.portalSettings = {}; + $scope.moduleSettings = {}; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetBasicSettings", { headers: $self.Headers }).success(function (data) { + $scope.portalSettings = data.PortalSettings; + $scope.moduleSettings = data.ModuleSettings; + + $scope.portalSettings.VisitorsOnlineEnabled = JSON.parse($scope.portalSettings.VisitorsOnlineEnabled.toLowerCase()); + $scope.portalSettings.LiveChatEnabled = JSON.parse($scope.portalSettings.LiveChatEnabled.toLowerCase()); + + $scope.moduleSettings.PlaySoundWhenNewMsg = $scope.moduleSettings.PlaySoundWhenNewMsg ? JSON.parse($scope.moduleSettings.PlaySoundWhenNewMsg.toLowerCase()) : false; + $scope.moduleSettings.ShowDekstopNotificationForIncoming = $scope.moduleSettings.ShowDekstopNotificationForIncoming ? JSON.parse($scope.moduleSettings.ShowDekstopNotificationForIncoming.toLowerCase()) : false; + $scope.moduleSettings.ShowDekstopNotificationForNewMsg = $scope.moduleSettings.ShowDekstopNotificationForNewMsg ? JSON.parse($scope.moduleSettings.ShowDekstopNotificationForNewMsg.toLowerCase()) : false; + $scope.moduleSettings.AgentsViewPermission = $scope.moduleSettings.AgentsViewPermission ? $scope.moduleSettings.AgentsViewPermission : 'OnlyCurrentAgents', + $scope.moduleSettings.SendEmailForOffline = $scope.moduleSettings.SendEmailForOffline ? JSON.parse($scope.moduleSettings.SendEmailForOffline.toLowerCase()) : false; + $scope.moduleSettings.SendEmailAfterChat = $scope.moduleSettings.SendEmailAfterChat ? JSON.parse($scope.moduleSettings.SendEmailAfterChat.toLowerCase()) : false; + $scope.moduleSettings.TranscriptEmailTemplate = $scope.moduleSettings.TranscriptEmailTemplate ? $scope.moduleSettings.TranscriptEmailTemplate : '

Chat Transcript with {{livechat.Visitor.DisplayName}}




{{localizeString["Name.Text"]}}{{livechat.Visitor.DisplayName}}
{{localizeString["Email.Text"]}}{{livechat.Visitor.Email}}
'; + $scope.moduleSettings.OfflineEmailTemplate = $scope.moduleSettings.OfflineEmailTemplate ? $scope.moduleSettings.OfflineEmailTemplate : '

{{localizeString["OfflineMessageFrom.Text"]}} {{livechat.Visitor.DisplayName}}



{{livechat.Message}}

{{localizeString["Name.Text"]}}{{livechat.Visitor.DisplayName}}
{{localizeString["Email.Text"]}}{{livechat.Visitor.Email}}
'; + }); + + $scope.onUpdateSettingsClick = function () { + var data = { + PortalSettings: $scope.portalSettings, + ModuleSettings: $scope.moduleSettings, + }; + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/UpdateBasicSettings", data, { headers: $self.Headers }).success(function (data) { + location.reload(); + }).error(function (data, status, headers, config) { + swal($scope.localizeString["Error.Text"], data, "error"); + }); + }; +}); + diff --git a/LiveChat/ClientApp/Controllers/visitorlist-controller.js b/LiveChat/ClientApp/Controllers/visitorlist-controller.js new file mode 100644 index 0000000..61a27df --- /dev/null +++ b/LiveChat/ClientApp/Controllers/visitorlist-controller.js @@ -0,0 +1,214 @@ +app.controller("visitorListController", function ($scope, $location, $http, $interval, $timeout, $filter, $q, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'visitorlist' }); + + var siteRoot = mydnnSupportLiveChat.SiteRoot; + var $self = { + Headers: { + ModuleId: mydnnSupportLiveChat.ModuleID, + TabId: mydnnSupportLiveChat.TabID, + } + }; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + $scope.visitor = {}; + $scope.visitors = []; + $scope.incomingLiveChats = []; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetVisitorList", { headers: $self.Headers }).success(function (visitors) { + $scope.visitors = visitors; + $scope.incomingLiveChats = []; + for (var i = 0; i < $scope.visitors.length; i++) { + var visitor = $scope.visitors[i]; + parseVisitorItems(visitor); + if (visitor.IncomingLiveChat) + $scope.incomingLiveChats.push(visitor); + } + calcVisitorsOnlineTime(); + }).error(function (data, status, headers, config) { }); + + //scope functions + $scope.$on('$destroy', function () { + $interval.cancel(timerCalculator); + timerCalculator = undefined; + }); + + //Search functions + $scope.sortModel = '1'; + $scope.$watch('sortModel', function () { + sortVisitors(); + }); + + //broadcasting from livechatAgentController + $scope.$on("onPopulateVisitorsOnline", function (event, args) { + var visitor = args.visitor; + result = $filter("filter")($scope.visitors, { VisitorGUID: visitor.VisitorGUID }); + if (result.length == 0) { + $scope.visitors.push(visitor); + parseVisitorItems(visitor); + sortVisitors(); + } + }); + + $scope.$on("onUpdateVisitorInfo", function (event, args) { + var visitor = args.visitor; + result = $filter("filter")($scope.visitors, { VisitorGUID: visitor.VisitorGUID }); + if (result.length) { + var indx = $scope.visitors.indexOf(result[0]); + if (visitor.UserName != '') { + $scope.visitors[indx].UserID = visitor.UserID; + $scope.visitors[indx].UserName = visitor.UserName; + $scope.visitors[indx].Avatar = getVisitorAvatar(visitor.UserID); + } + if (visitor.DisplayName != '') { + $scope.visitors[indx].DisplayName = visitor.DisplayName; + $scope.visitors[indx].Email = visitor.Email; + } + $scope.visitors[indx].LastURL = visitor.LastURL; + } + }); + + $scope.$on("onPopulateVisitorsOffline", function (event, args) { + var visitors = args.visitors; + for (var i = 0; i < visitors.length; i++) { + removeVisitor(visitors[i]); + removeIncomingChat(visitors[i]); + } + }); + + $scope.$on("onIncomingLiveChat", function (event, args) { + var livechatID = args.livechatID, visitorGUID = args.visitorGUID, message = args.message; + + result = $filter("filter")($scope.visitors, { VisitorGUID: visitorGUID }); + if (result.length) { + result[0].IncomingLiveChat = true; + if ($filter("filter")($scope.incomingLiveChats, { VisitorGUID: visitorGUID }).length == 0) { + result[0].Message = message; + $scope.incomingLiveChats.push(result[0]); + } + } + }); + + $scope.$on("onVisitorIsChatting", function (event, args) { + var visitorGUID = args.visitorGUID; + + removeIncomingChat(visitorGUID); + result = $filter("filter")($scope.visitors, { VisitorGUID: visitorGUID }); + if (result.length) { + result[0].IncomingLiveChat = false; + result[0].CurrentLiveChat = true; + } + }); + + //private functions + function parseVisitorItems(visitor) { + visitor.DisplayName = getDisplayName(visitor); + visitor.Avatar = getVisitorAvatar(visitor.UserID); + visitor.OnlineTime = getTimeDiff(visitor.OnlineDate, moment()); + + if (!visitor.Location) + parseIpLocation(visitor.VisitorGUID, visitor.IP); + + if (!visitor.UserAgentData) { + var parser = new UAParser(); + parser.setUA(visitor.UserAgent); + visitor.UserAgentData = parser.getResult(); + } + } + + function parseIpLocation(id, ip) { + if (ip == "127.0.0.1") + ip = ""; + $.getJSON("http://freegeoip.net/json/" + ip, function (data) { + var visitor = $filter("filter")($scope.visitors, { VisitorGUID: id }); + var indx = $scope.visitors.indexOf(visitor[0]); + $scope.visitors[indx].Location = data; + $timeout(function () { + }, 100); + }); + } + + function getDisplayName(visitor) { + if (visitor.DisplayName == '') + return $scope.localizeString["Anonymous.Text"] + " #" + visitor.VisitorGUID.substr(0, 4); + else + return visitor.DisplayName; + } + + function getVisitorAvatar(userID) { + if (userID <= 0) + return siteRoot + "images/no_avatar.gif"; + else + return siteRoot + "dnnimagehandler.ashx?mode=profilepic&userid=" + userID; + }; + + function getTimeDiff(onlineT, nowT) { + var diff = nowT.diff(onlineT, 'minutes'); + var lbl = $scope.localizeString["Min.Text"] + if (diff >= 60) { + diff = nowT.diff(onlineT, 'hours'); + lbl = $scope.localizeString["Hours.Text"] + } + return diff + ' ' + lbl; + } + + function parseDate(d) { + return new Date(d); + } + + function parseCountry(c) { + return c.country_code; + } + + function parseBrowser(b) { + return b.browser.name; + } + + function sortList(field, reverse, primer) { + var key = primer ? + function (x) { return primer(x[field]) } : + function (x) { return x[field] }; + + reverse = [-1, 1][+!!reverse]; + + return function (a, b) { + return a = key(a), b = key(b), reverse * ((a > b) - (b > a)); + } + } + + function sortVisitors() { + if ($scope.sortModel == '1') + $scope.visitors = $scope.visitors.sort(sortList('OnlineDate', true, parseDate)) + else if ($scope.sortModel == '2') + $scope.visitors = $scope.visitors.sort(sortList('OnlineDate', false, parseDate)) + else if ($scope.sortModel == '3') + $scope.visitors = $scope.visitors.sort(sortList('Location', false, parseCountry)) + else if ($scope.sortModel == '4') + $scope.visitors = $scope.visitors.sort(sortList('UserAgentData', true, parseBrowser)) + }; + + var timerCalculator; + function calcVisitorsOnlineTime() { + timerCalculator = $interval(function () { + for (var i = 0; i < $scope.visitors.length; i++) { + var visitor = $scope.visitors[i]; + visitor.OnlineTime = getTimeDiff(visitor.OnlineDate, moment()); + } + }, 59000); + } + + function removeVisitor(id) { + result = $filter("filter")($scope.visitors, { VisitorGUID: id }); + if (result.length) { + var indx = $scope.visitors.indexOf(result[0]); + $scope.visitors.splice(indx, 1); + } + } + + function removeIncomingChat(id) { + result = $filter("filter")($scope.incomingLiveChats, { VisitorGUID: id }); + if (result.length) { + var indx = $scope.incomingLiveChats.indexOf(result[0]); + $scope.incomingLiveChats.splice(indx, 1); + } + } +}); \ No newline at end of file diff --git a/LiveChat/ClientApp/Controllers/widgetsetting-controller.js b/LiveChat/ClientApp/Controllers/widgetsetting-controller.js new file mode 100644 index 0000000..e6b458e --- /dev/null +++ b/LiveChat/ClientApp/Controllers/widgetsetting-controller.js @@ -0,0 +1,190 @@ +app.controller("widgetSettingController", function ($scope, $http, $timeout, $filter, $location, cfpLoadingBar, activeMenu) { + activeMenu.setActiveMenu({ Parent: 'settings', Child: 'widget' }); + + var siteRoot = mydnnSupportLiveChat.SiteRoot; + var moduleSettings; + var timeOut; + var $self = { + Headers: { + ModuleId: mydnnSupportLiveChat.ModuleID, + TabId: mydnnSupportLiveChat.TabID, + } + }; + + $scope.localizeString = mydnnSupportLiveChat.SharedResources; + $scope.livechat = {}; + $scope.widgetSettings = {}; + $scope.minButtonSettings = {}; + $scope.isVisibleWidget = true; + $scope.isAgentOnline = true; + + $http.get(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/GetWidgetSettings", { headers: $self.Headers }).success(function (data) { + $scope.livechat.WidgetHtml = data.LiveChatWidget; + $scope.livechat.HtmlTemplate = data.LiveChatWidget; + + moduleSettings = data.Settings; + + setDefaultValue(); + + $('body').append(''); + $('body').append(''); + $('body').append(''); + $('[data-toggle="popover"]').popover(); + }); + + $scope.onStepTabClick = function (tabName) { + if (tabName == 'appearance') { + $scope.isVisibleWidget = true; + $scope.livechat.Step = 'chatstarted'; + } + else if (tabName == 'forms') { + $scope.isVisibleWidget = true; + $scope.livechat.Step = 'prechat'; + } + else if (tabName == 'minbutton') { + $scope.isVisibleWidget = false; + } + }; + + $scope.onFormElementFocus = function (visibility) { + if (visibility == 'online') + $scope.isAgentOnline = true; + else if (visibility == 'offline') + $scope.isAgentOnline = false; + }; + + function setDefaultValue() { + $scope.livechat.Step = 'chatstarted', + $scope.livechat.Visitor = + { + UserID: -1, + Avatar: moduleSettings.VisitorDefaultAvatar ? moduleSettings.VisitorDefaultAvatar : siteRoot + 'DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/Images/visitor-avatar.png' + }, + $scope.livechat.AgentDefaultAvatar = moduleSettings.AgentDefaultAvatar ? moduleSettings.AgentDefaultAvatar : siteRoot + 'DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/Images/agent-avatar.png' + $scope.livechat.Messages = [ + { + SentBy: 0, + Message: 'Chat started' + }, + { + SentBy: 1, + SenderDisplayName: 'Paola', + SenderAvatar: moduleSettings.VisitorDefaultAvatar, + MessageType: 0, + Message: 'Hi there, I`m looking for green and pink shirts.', + IsMyMessage: true, + MsgTime: moment().format("hh:mm"), + Seen: true + }, + { + SentBy: 0, + Message: 'Ian Borland joined the chat' + }, + { + SentBy: 2, + SenderDisplayName: 'Ian Borland ', + SenderAvatar: moduleSettings.VisitorDefaultAvatar, + MessageType: 0, + Message: 'Hi Paola, welcome to our store!', + IsMyMessage: false, + MsgTime: moment().format("hh:mm") + }, + { + SentBy: 1, + SenderDisplayName: 'Paola', + SenderAvatar: moduleSettings.VisitorDefaultAvatar, + MessageType: 0, + Message: 'I have one problem on my portal :(. I can`t login into website', + IsMyMessage: true, + MsgTime: moment().format("hh:mm"), + Seen: true + }, + { + SentBy: 2, + SenderDisplayName: 'Ian Borland ', + SenderAvatar: moduleSettings.VisitorDefaultAvatar, + MessageType: 0, + Message: 'Please send your user info to support email (info@email.com)!', + IsMyMessage: false, + MsgTime: moment().format("hh:mm") + }, + { + SentBy: 0, + Message: 'Ian Borland has left chat' + }, + { + SentBy: 1, + SenderDisplayName: 'Paola', + SenderAvatar: moduleSettings.VisitorDefaultAvatar, + MessageType: 0, + Message: 'eeee koja rafti baba jan man karet dashtama zood bargard lanati lanati lanati', + IsMyMessage: true, + MsgTime: moment().format("hh:mm"), + Seen: false + }], + $scope.widgetSettings = { + LiveChatThemeColor: moduleSettings.LiveChatThemeColor ? moduleSettings.LiveChatThemeColor : '#1D91E5', + LiveChatTitleColor: moduleSettings.LiveChatTitleColor ? moduleSettings.LiveChatTitleColor : '#fff', + LiveChatWindowSize: moduleSettings.LiveChatWindowSize ? moduleSettings.LiveChatWindowSize : 'Medium', + LiveChatWidgetPosition: moduleSettings.LiveChatWidgetPosition ? moduleSettings.LiveChatWidgetPosition : 'BottomRight', + LiveChatEnableRating: moduleSettings.LiveChatEnableRating ? JSON.parse(moduleSettings.LiveChatEnableRating.toLowerCase()) : true, + LiveChatShowAvatar: moduleSettings.LiveChatShowAvatar ? JSON.parse(moduleSettings.LiveChatShowAvatar.toLowerCase()) : true, + LiveChatMessageStyle: moduleSettings.LiveChatMessageStyle ? moduleSettings.LiveChatMessageStyle : 'SpeechBubbles', + }, + $scope.minButtonSettings = { + OnlineButton: moduleSettings.LiveChatMinBtnOnline ? moduleSettings.LiveChatMinBtnOnline : 'Live Chat: Online', + OnlineButtonBGColor: moduleSettings.LiveChatMinBtnOnlineBgColor ? moduleSettings.LiveChatMinBtnOnlineBgColor : '#4caf50', + OnlineButtonColor: moduleSettings.LiveChatMinBtnOnlineColor ? moduleSettings.LiveChatMinBtnOnlineColor : '#fff', + OfflineButton: moduleSettings.LiveChatMinBtnOffline ? moduleSettings.LiveChatMinBtnOffline : 'Send Message', + OfflineButtonBGColor: moduleSettings.LiveChatMinBtnOfflineBgColor ? moduleSettings.LiveChatMinBtnOfflineBgColor : '#c7cec7', + OfflineButtonColor: moduleSettings.LiveChatMinBtnOfflineColor ? moduleSettings.LiveChatMinBtnOfflineColor : '#333', + HorizontalPosition: moduleSettings.LiveChatMinBtnHPos ? moduleSettings.LiveChatMinBtnHPos : 'Right', + VerticalPosition: moduleSettings.LiveChatMinBtnVPos ? moduleSettings.LiveChatMinBtnVPos : 'Bottom', + Rotate: moduleSettings.LiveChatMinBtnRotate ? moduleSettings.LiveChatMinBtnRotate : '0', + CssStyle: moduleSettings.LiveChatMinBtnCssStyle ? moduleSettings.LiveChatMinBtnCssStyle : '.livechat-minbutton{\n} \n.livechat-minbutton .online-button {\npadding: 10px;} \n.livechat-minbutton .offline-button {\npadding: 10px;}', + } + } + + $scope.$watch("widgetSettings.LiveChatThemeColor", function (val, oldVal) { + if (timeOut) $timeout.cancel(timeOut); + + timeOut = $timeout(function () { + reWriteWidgetColorsStyles(); + }, 250); + }); + + $scope.$watch("widgetSettings.LiveChatTitleColor", function (val, oldVal) { + if (timeOut) $timeout.cancel(timeOut); + + timeOut = $timeout(function () { + reWriteWidgetColorsStyles(); + }, 250); + }); + + function reWriteWidgetColorsStyles() { + angular.element('#mydnnLiveChatWidgetStyles').html('.livechat-theme-bgcolor{background-color:' + $scope.widgetSettings.LiveChatThemeColor + ';}.livechat-theme-color{color:' + $scope.widgetSettings.LiveChatThemeColor + ';}.livechat-theme-titlecolor{color:' + $scope.widgetSettings.LiveChatTitleColor + ';}.livechat-focusable:focus{border-color:' + $scope.widgetSettings.LiveChatThemeColor + ' !important;}'); + } + + $scope.$watch("minButtonSettings.CssStyle", function (val, oldVal) { + if (timeOut) $timeout.cancel(timeOut); + + timeOut = $timeout(function () { + $('#mydnnLiveChatMinButtonStyles').html(val); + }, 250); + }); + + $scope.onUpdateSettingsClick = function () { + $scope.minButtonSettings.HtmlTemplate = angular.element("#livechat-minbutton-panel").html(); + var data = { + WidgetSettings: $scope.widgetSettings, + MinButtonSettings: $scope.minButtonSettings, + Locales: $scope.localizeString + }; + $http.post(mydnnGetServiceRoot("MyDnnSupport.LiveChat") + "AgentService/UpdateWidgetSettings", data, { headers: $self.Headers }).success(function (data) { + location.reload(); + }).error(function (data, status, headers, config) { + swal($scope.localizeString["Error.Text"], data, "error"); + }); + }; +}); + diff --git a/LiveChat/ClientApp/Services/ng-mydnn-services.js b/LiveChat/ClientApp/Services/ng-mydnn-services.js new file mode 100644 index 0000000..57025c2 --- /dev/null +++ b/LiveChat/ClientApp/Services/ng-mydnn-services.js @@ -0,0 +1,99 @@ +var ngMyDnnServices = angular.module('ngMyDnnServices', []) + .factory('localizationService', ['$http', function ($http) { + var sdo = { + getResources: function (moduleApi, controller, resource, culture) { + return $http.get(moduleApi + "/" + controller + "/GetResources", { params: { resource: resource, culture: culture } }); + } + } + return sdo; + }]) + .factory('activeMenu', function () { + var activeMenu = { + Parent: "home", + Child: undefined + }; + return { + getActiveMenu: function () { + return activeMenu; + }, + setActiveMenu: function (val) { + activeMenu = val; + } + }; + }).directive('focusOn', function () { + return function (scope, elem, attr) { + scope.$on(attr.focusOn, function (e) { + elem[0].focus(); + }); + }; + }).directive('dynamic', function ($compile) { + return { + restrict: 'A', + replace: true, + link: function (scope, ele, attrs) { + scope.$watch(attrs.dynamic, function (html) { + ele.html(html); + $compile(ele.contents())(scope); + }); + } + }; + }).directive('intNumber', function () { + return { + require: 'ngModel', + restrict: 'A', + link: function (scope, element, attr, ctrl) { + function inputValue(val) { + if (val) { + var digits = val.replace(/[^0-9]/g, ''); + + if (digits !== val) { + ctrl.$setViewValue(digits); + ctrl.$render(); + } + return parseInt(digits, 10); + } + return undefined; + } + ctrl.$parsers.push(inputValue); + } + }; + }).directive('realNumber', function () { + return { + require: 'ngModel', + restrict: 'A', + link: function (scope, element, attr, ctrl) { + function inputValue(val) { + if (val) { + var digits = val.replace(/[^0-9.]/g, ''); + + if (digits !== val) { + ctrl.$setViewValue(digits); + ctrl.$render(); + } + return parseFloat(digits); + } + return undefined; + } + ctrl.$parsers.push(inputValue); + } + }; + }).directive('numberMask', function () { + return { + restrict: 'A', + link: function (scope, element, attrs) { + $(element).numeric(); + } + } + }).directive('schrollBottom', function () { + return function (scope, elem, attr) { + scope.$on(attr.schrollBottom, function (event, args) { + var $element = angular.element('[data-livechat-messages=' + args.id + ']'); + $element.animate({ scrollTop: $element.prop("scrollHeight") }, 500); + }); + }; + }).filter('cmdate', ['$filter', function ($filter) { + return function (input, format) { + return moment(input).format(format); + }; + } + ]); diff --git a/LiveChat/ClientApp/Services/signalr.service.js b/LiveChat/ClientApp/Services/signalr.service.js new file mode 100644 index 0000000..052bfa9 --- /dev/null +++ b/LiveChat/ClientApp/Services/signalr.service.js @@ -0,0 +1,289 @@ +(function ($, angular, document) { + 'use strict'; + + HubFactory.$inject = ['$rootScope', '$q', 'HubConnectionEvents']; + function HubFactory($rootScope, $q, ConnectionEvents) { + + /** + * Class Hub + * This is a re-usable Class + * @example + * + * var myHub = new Hub('myHub'); + * + * myHub.send('sendMessage', 'Hello from Client'); + * + * myHub.on('receiveMessage', function(msg){ console.log('Server:', msg); }); + * + * @param {String} hubName + * @param [{Object}] options + */ + function Hub(hubName, options) { + + // Ensure a hub name was passed + if (!hubName) { + throw new Error('Hub name was not specified, be sure to pass it in when invoking the Hub class'); + } + + // Hub Settings + var settings = angular.extend({ + + // Enable hub logging events + loggingEnabled: false, + + }, options); + + // Create and set the connection property + this.connection = $.hubConnection(settings.connectionPath); + + // Set Logging + this.connection.logging = settings.loggingEnabled; + + // Create and set the Hub Proxy + this.proxy = this.connection.createHubProxy(hubName); + + // Bind to connection events , this is only done once. + bindConnectionEvents(this); + + + } + + /** + * Add the following methods to the Hub.prototype chain + */ + Hub.prototype = { + /** + * Starts the hub connection + * @return {Promise} + */ + start: function start() { + return this.connection.start({ transport: 'longPolling' }); + }, + + /** + * Hub.on + * @param {String} evt + * @param {Function} fn + */ + on: function on(evt, fn) { + + this.proxy.on(evt, function () { + + var args = arguments; + + // Have angular run a digest + $rootScope.$evalAsync(function () { + fn.apply(fn, args); + }); + + }); + + return this; // Return for chaining + }, + + /** + * Hub.off + * Stops listening to passed in event + * + * @example + * Hub.off('getDataFromHub', getDataFromHubCallback); + */ + off: function () { + this.proxy.off.apply(this.proxy, arguments); + }, + + /** + * Hub.invoke + * Method will ensure that a connection has been established before + * calling to the hub + * + * @example + * Hub.invoke('sendMessage', 'Message to Send'); + */ + invoke: function invoke() { + + // Store the passed in arguments + var args = arguments, + + // Send will always return a promise. + // Promises are resolved by the hub invoke method + deferred = $q.defer(), + + // Internal context + self = this + ; + + // Resolve the invoke call and it's promise + function resolve() { + // Our promise is either resolved or rejected by the hubs response. + self.proxy.invoke.apply(self.proxy, args).then(deferred.resolve, deferred.reject); + } + + // Resolve the method immediately if the connection is established + if (this.connection.state === $.signalR.connectionState.connected) { + resolve(); + } + + // In the event that we're disconnected + if (this.connection.state === $.signalR.connectionState.disconnected) { + + // Start the connection, then resolve once we're connected + this.start().done(function () { + resolve(); + }); + } + + // Return the promise + return deferred.promise; + }, + + /** + * Alias for invoke + */ + send: function () { + return this.invoke.apply(this, arguments); + }, + + /** + * Exposes the Hubs connection status + */ + connectionStatus: { + + // Disconnected flag + disconnected: false, + + // Reconnecting flag + reconnecting: false, + + /** + * Determine if the hub is connected + * @return boolean + */ + isConnected: function () { + return !this.disconnected && !this.reconnecting; + }, + + /** + * Is connection disconnected + */ + isDisconnected: function () { + return this.disconnected; + }, + + /** + * Is Reconnecting + */ + isReconnecting: function () { + return this.reconnecting; + }, + + /** + * Determine if the hub connection is down + * + * @return boolean + */ + isDown: function () { + return this.disconnected || this.reconnecting; + }, + + /** + * Update the connection status + * @param {Boolean} reconnectVal + * @param {Boolean} disconnectVal + */ + setConnection: function (reconnectVal, disconnectVal) { + + var self = this; + + // Ask angular to udpate the digest + $rootScope.$evalAsync(function () { + self.reconnecting = reconnectVal; + self.disconnected = disconnectVal; + }); + } + } + }; + + + /** + * Bind to the connection events. + * This is a private method, we use it to bind the hubs connection events when constructed. + * + * @param {Hub} hubInstance + */ + function bindConnectionEvents(hubInstance) { + + /** + * Uses rootScope to broadcast the desired connection event + */ + function broadcastConnectionEvent() { + $rootScope.$broadcast.apply($rootScope, arguments); + } + + /** + * Update the connection status on the hub, when the state changes + */ + function updateConnectionState(evt, state) { + + var reconnecting = state.newState === $.signalR.connectionState.reconnecting, + disconnected = state.newState === $.signalR.connectionState.disconnected + ; + + hubInstance.connectionStatus.setConnection(reconnecting, disconnected); + + } + + // Hook into the change event + $rootScope.$on(ConnectionEvents.change, updateConnectionState); + + // Bind to the connection reconnecting event + hubInstance.connection.reconnecting(function () { + broadcastConnectionEvent(ConnectionEvents.reconnecting); + }); + + // Bind to the connection reconnected event + hubInstance.connection.reconnected(function () { + broadcastConnectionEvent(ConnectionEvents.reconnected); + }); + + // Bind to the connection disconnected event + hubInstance.connection.disconnected(function () { + broadcastConnectionEvent(ConnectionEvents.disconnected); + }); + + // Bind to the connection error event + hubInstance.connection.error(function (error, data) { + broadcastConnectionEvent(ConnectionEvents.error, error, data); + }); + + // Bind to the connection change event + hubInstance.connection.stateChanged(function (state) { + broadcastConnectionEvent(ConnectionEvents.change, state); + }); + } + + + + // Return our Class + return Hub; + + } + + angular.module('services.hub', []) + // Hub Conncetion event object + // This can be used throughout the application to hook into the $scope or $rootScope for connection events + // + .value('HubConnectionEvents', { + change: 'hub:connection:change', + error: 'hub:connection:error', + disconnected: 'hub:connection:disconnected', + reconnected: 'hub:connection:reconnected', + reconnecting: 'hub:connection:reconnecting' + }) + + // Register the Hub Proxy Service + .factory('HubProxy', HubFactory); + + + +})(window.jQuery, window.angular, document); diff --git a/LiveChat/ClientApp/app.js b/LiveChat/ClientApp/app.js new file mode 100644 index 0000000..8d5ad82 --- /dev/null +++ b/LiveChat/ClientApp/app.js @@ -0,0 +1,38 @@ +var app = angular.module('MyDnnSupportApp', ['ngRoute', 'ngAnimate', 'ui.bootstrap', 'angular-loading-bar', 'localytics.directives', 'angular-bootstrap-select', 'farbtastic', 'ngResource', 'ngSanitize', 'ngMyDnnServices', 'services.hub']) +app.config(['$routeProvider', function ($routeProvider) { + $routeProvider + .when('/visitorlist', { + templateUrl: 'visitorlist.html', + controller: 'visitorListController', + }) + .when('/history', { + templateUrl: 'history.html', + controller: 'historyController', + }) + .when('/departments', { + templateUrl: 'departments.html', + controller: 'departmentController', + }) + .when('/agents', { + templateUrl: 'agents.html', + controller: 'agentController', + }) + .when('/settings', { + templateUrl: 'basicsettings.html', + controller: 'settingController', + }) + .when('/widgetsettings', { + templateUrl: 'widgetsettings.html', + controller: 'widgetSettingController', + }) + .otherwise({ + redirectTo: '/visitorlist' + }); +}]); + +app.controller("adminPanelController", function ($scope, $http, $timeout, cfpLoadingBar, activeMenu) { + $scope.activeMenu = activeMenu.getActiveMenu(); + $scope.$watch(function () { return activeMenu.getActiveMenu(); }, function (newValue, oldValue) { + if (newValue !== oldValue) $scope.activeMenu = newValue; + }); +}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/angular-farbtastic/angular-farbtastic.js b/LiveChat/ClientComponents/angular-farbtastic/angular-farbtastic.js new file mode 100644 index 0000000..6d52e4a --- /dev/null +++ b/LiveChat/ClientComponents/angular-farbtastic/angular-farbtastic.js @@ -0,0 +1,479 @@ +'use scrict'; + +/* + * Based on farbtastic 2.0.0-alpha.1 + * https://github.com/mattfarina/farbtastic + * + * Farbtastic was originally written by Steven Wittens and is licensed under the GPL. + */ +(function($) { + var Farbtastic = function($container, callback, options) { + var self = this; + + this.options = $.extend({ + width: 200, + wheelWidth: (options.width || 200) / 10, + color: '#808080' + }, options); + + this.$container = $container; + // Initialize. + this.initWidget(); + + // Set linked elements/callback + this.callback = callback; + + this.setColor(this.options.color); + + this.mousemove = function(event) { + Farbtastic.prototype.mousemove.call(self, event); + }; + + this.mouseup = function(event) { + Farbtastic.prototype.mouseup.call(self, event); + }; + + this.mousedown = function(event) { + Farbtastic.prototype.mousedown.call(self, event); + }; + + // Install mousedown handler (the others are set on the document on-demand) + $('canvas.farbtastic-overlay', $container).bind('mousedown', this.mousedown); + }; + + Farbtastic.prototype.updateValue = function() { + if (this.value && this.value !== this.color) { + this.setColor(this.value); + } + return this; + }; + + /** + * Change color with HTML syntax #123456 + */ + Farbtastic.prototype.setColor = function(color) { + var unpacked = unpack(color); + if (this.color !== color && unpacked) { + this.color = color; + this.rgb = unpacked; + this.hsl = RGBToHSL(this.rgb); + this.updateDisplay(); + } + return this; + }; + + /** + * Change color with HSL triplet [0..1, 0..1, 0..1] + */ + Farbtastic.prototype.setHSL = function(hsl) { + this.hsl = hsl; + this.rgb = HSLToRGB(hsl); + this.color = pack(this.rgb); + this.updateDisplay(); + return this; + }; + + ///////////////////////////////////////////////////// + + /** + * Initialize the color picker widget. + */ + Farbtastic.prototype.initWidget = function() { + + // Insert markup and size accordingly. + var dim = { + width: this.options.width, + height: this.options.width + }; + this.$container + .html( + '
' + + '
' + + '' + + '' + + '
' + ) + .find('*').attr(dim).css(dim).end() + .find('div>*').css('position', 'absolute'); + + // Determine layout + this.radius = (this.options.width - this.options.wheelWidth) / 2 - 1; + this.square = Math.floor((this.radius - this.options.wheelWidth / 2) * 0.7) - 1; + this.mid = Math.floor(this.options.width / 2); + this.markerSize = this.options.wheelWidth * 0.3; + this.solidFill = $('.farbtastic-solid', this.$container).css({ + width: this.square * 2 - 1, + height: this.square * 2 - 1, + left: this.mid - this.square, + top: this.mid - this.square + }); + + // Set up drawing context. + this.cnvMask = $('.farbtastic-mask', this.$container); + this.ctxMask = this.cnvMask[0].getContext('2d'); + this.cnvOverlay = $('.farbtastic-overlay', this.$container); + this.ctxOverlay = this.cnvOverlay[0].getContext('2d'); + this.ctxMask.translate(this.mid, this.mid); + this.ctxOverlay.translate(this.mid, this.mid); + + // Draw widget base layers. + this.drawCircle(); + this.drawMask(); + + return this; + }; + + /** + * Draw the color wheel. + */ + Farbtastic.prototype.drawCircle = function() { + var tm = +(new Date()); + // Draw a hue circle with a bunch of gradient-stroked beziers. + // Have to use beziers, as gradient-stroked arcs don't work. + var n = 24, + r = this.radius, + w = this.options.wheelWidth, + nudge = 8 / r / n * Math.PI, // Fudge factor for seams. + m = this.ctxMask, + angle1 = 0, color1, d1; + m.save(); + m.lineWidth = w / r; + m.scale(r, r); + // Each segment goes from angle1 to angle2. + for (var i = 0; i <= n; ++i) { + var d2 = i / n, + angle2 = d2 * Math.PI * 2, + // Endpoints + x1 = Math.sin(angle1), y1 = -Math.cos(angle1); + x2 = Math.sin(angle2), y2 = -Math.cos(angle2), + // Midpoint chosen so that the endpoints are tangent to the circle. + am = (angle1 + angle2) / 2, + tan = 1 / Math.cos((angle2 - angle1) / 2), + xm = Math.sin(am) * tan, ym = -Math.cos(am) * tan, + // New color + color2 = pack(HSLToRGB([d2, 1, 0.5])); + if (i > 0) { + var grad = m.createLinearGradient(x1, y1, x2, y2); + grad.addColorStop(0, color1); + grad.addColorStop(1, color2); + m.strokeStyle = grad; + // Draw quadratic curve segment. + m.beginPath(); + m.moveTo(x1, y1); + m.quadraticCurveTo(xm, ym, x2, y2); + m.stroke(); + } + // Prevent seams where curves join. + angle1 = angle2 - nudge; + color1 = color2; + d1 = d2; + } + m.restore(); + return this; + }; + + /** + * Draw the saturation/luminance mask. + */ + Farbtastic.prototype.drawMask = function() { + // Iterate over sat/lum space and calculate appropriate mask pixel values. + var size = this.square * 2, sq = this.square; + function calculateMask(sizex, sizey, outputPixel) { + var isx = 1 / sizex, isy = 1 / sizey; + for (var y = 0; y <= sizey; ++y) { + var l = 1 - y * isy; + for (var x = 0; x <= sizex; ++x) { + var s = 1 - x * isx; + // From sat/lum to alpha and color (grayscale) + var a = 1 - 2 * Math.min(l * s, (1 - l) * s); + var c = (a > 0) ? ((2 * l - 1 + a) * .5 / a) : 0; + outputPixel(x, y, c, a); + } + } + } + + // Method #1: direct pixel access (new Canvas). + if (this.ctxMask.getImageData) { + // Create half-resolution buffer. + var sz = Math.floor(size / 2); + var buffer = document.createElement('canvas'); + buffer.width = buffer.height = sz + 1; + var ctx = buffer.getContext('2d'); + var frame = ctx.getImageData(0, 0, sz + 1, sz + 1); + + var i = 0; + calculateMask(sz, sz, function(x, y, c, a) { + frame.data[i++] = frame.data[i++] = frame.data[i++] = c * 255; + frame.data[i++] = a * 255; + }); + + ctx.putImageData(frame, 0, 0); + this.ctxMask.drawImage(buffer, 0, 0, sz + 1, sz + 1, -sq, -sq, sq * 2, sq * 2); + } + // Method #2: vertical DXImageTransform gradient strips (IE). + else { + var cache_last, cache, w = 6; // Each strip is 6 pixels wide. + var sizex = Math.floor(size / w); + // 6 vertical pieces of gradient per strip. + calculateMask(sizex, 6, function(x, y, c, a) { + if (x === 0) { + cache_last = cache; + cache = []; + } + c = Math.round(c * 255); + a = Math.round(a * 255); + // We can only start outputting gradients once we have two rows of pixels. + if (y > 0) { + var c_last = cache_last[x][0], + a_last = cache_last[x][1], + color1 = packDx(c_last, a_last), + color2 = packDx(c, a), + y1 = Math.round(this.mid + ((y - 1) * .333 - 1) * sq), + y2 = Math.round(this.mid + (y * .333 - 1) * sq); + $('
').css({ + position: 'absolute', + filter: "progid:DXImageTransform.Microsoft.Gradient(StartColorStr=" + color1 + ", EndColorStr=" + color2 + ", GradientType=0)", + top: y1, + height: y2 - y1, + // Avoid right-edge sticking out. + left: this.mid + (x * w - sq - 1), + width: w - (x === sizex ? Math.round(w / 2) : 0) + }).appendTo(this.cnvMask); + } + cache.push([c, a]); + }); + } + return this; + }; + + /** + * Draw the selection markers. + */ + Farbtastic.prototype.drawMarkers = function() { + // Determine marker dimensions + var sz = this.options.width, lw = Math.ceil(this.markerSize / 4), r = this.markerSize - lw + 1; + var angle = this.hsl[0] * 6.28, + x1 = Math.sin(angle) * this.radius, + y1 = -Math.cos(angle) * this.radius, + x2 = 2 * this.square * (.5 - this.hsl[1]), + y2 = 2 * this.square * (.5 - this.hsl[2]), + c1 = this.invert ? '#fff' : '#000', + c2 = this.invert ? '#000' : '#fff'; + var circles = [ + {x: x1, y: y1, r: r, c: '#000', lw: lw + 1}, + {x: x1, y: y1, r: this.markerSize, c: '#fff', lw: lw}, + {x: x2, y: y2, r: r, c: c2, lw: lw + 1}, + {x: x2, y: y2, r: this.markerSize, c: c1, lw: lw}, + ]; + + // Update the overlay canvas. + this.ctxOverlay.clearRect(-this.mid, -this.mid, sz, sz); + for (var i = 0; i < circles.length; i++) { + var c = circles[i]; + this.ctxOverlay.lineWidth = c.lw; + this.ctxOverlay.strokeStyle = c.c; + this.ctxOverlay.beginPath(); + this.ctxOverlay.arc(c.x, c.y, c.r, 0, Math.PI * 2, true); + this.ctxOverlay.stroke(); + } + return this; + }; + + /** + * Update the markers and styles + */ + Farbtastic.prototype.updateDisplay = function() { + // Determine whether labels/markers should invert. + this.invert = (this.rgb[0] * 0.3 + this.rgb[1] * .59 + this.rgb[2] * .11) <= 0.6; + + // Update the solid background fill. + this.solidFill.css('backgroundColor', pack(HSLToRGB([this.hsl[0], 1, 0.5]))); + + // Draw markers + this.drawMarkers(); + + // Linked callback + this.callback.call(this, this.color); + + return this; + }; + + /** + * Helper for returning coordinates relative to the center. + */ + Farbtastic.prototype.widgetCoords = function(event) { + return { + x: event.pageX - this.offset.left - this.mid, + y: event.pageY - this.offset.top - this.mid + }; + }; + + /** + * Mousedown handler + */ + Farbtastic.prototype.mousedown = function(event) { + // Capture mouse + if (!this.dragging) { + $(document).bind('mousemove', this.mousemove) + .bind('mouseup', this.mouseup); + this.dragging = true; + } + + // Update the stored offset for the widget. + this.offset = this.$container.offset(); + + // Check which area is being dragged + var pos = this.widgetCoords(event); + this.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) > (this.square + 2); + + // Process + this.mousemove(event); + return false; + }; + + /** + * Mousemove handler + */ + Farbtastic.prototype.mousemove = function(event) { + // Get coordinates relative to color picker center + var pos = this.widgetCoords(event); + + // Set new HSL parameters + if (this.circleDrag) { + var hue = Math.atan2(pos.x, -pos.y) / 6.28; + this.setHSL([(hue + 1) % 1, this.hsl[1], this.hsl[2]]); + } + else { + var sat = Math.max(0, Math.min(1, -(pos.x / this.square / 2) + .5)); + var lum = Math.max(0, Math.min(1, -(pos.y / this.square / 2) + .5)); + this.setHSL([this.hsl[0], sat, lum]); + } + return false; + }; + + /** + * Mouseup handler + */ + Farbtastic.prototype.mouseup = function() { + // Uncapture mouse + $(document).unbind('mousemove', this.mousemove); + $(document).unbind('mouseup', this.mouseup); + this.dragging = false; + }; + + /* Various color utility functions */ + function dec2hex(x) { + return (x < 16 ? '0' : '') + x.toString(16); + } + + function packDx(c, a) { + return '#' + dec2hex(a) + dec2hex(c) + dec2hex(c) + dec2hex(c); + } + + function pack(rgb) { + var r = Math.round(rgb[0] * 255); + var g = Math.round(rgb[1] * 255); + var b = Math.round(rgb[2] * 255); + return '#' + dec2hex(r) + dec2hex(g) + dec2hex(b); + } + + function unpack(color) { + if (color.length === 7) { + function x(i) { + return parseInt(color.substring(i, i + 2), 16) / 255; + } + return [x(1), x(3), x(5)]; + } + else if (color.length === 4) { + function x(i) { + return parseInt(color.substring(i, i + 1), 16) / 15; + } + return [x(1), x(2), x(3)]; + } + } + + function HSLToRGB(hsl) { + var m1, m2; + var h = hsl[0], s = hsl[1], l = hsl[2]; + m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s; + m1 = l * 2 - m2; + return [ + hueToRGB(m1, m2, h + 0.33333), + hueToRGB(m1, m2, h), + hueToRGB(m1, m2, h - 0.33333) + ]; + } + + function hueToRGB(m1, m2, h) { + h = (h + 1) % 1; + if (h * 6 < 1) + return m1 + (m2 - m1) * h * 6; + if (h * 2 < 1) + return m2; + if (h * 3 < 2) + return m1 + (m2 - m1) * (0.66666 - h) * 6; + return m1; + } + + function RGBToHSL(rgb) { + var r = rgb[0], g = rgb[1], b = rgb[2], + min = Math.min(r, g, b), + max = Math.max(r, g, b), + delta = max - min, + h = 0, + s = 0, + l = (min + max) / 2; + if (l > 0 && l < 1) { + s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); + } + if (delta > 0) { + if (max === r && max !== g) + h += (g - b) / delta; + if (max === g && max !== b) + h += (2 + (b - r) / delta); + if (max === b && max !== r) + h += (4 + (r - g) / delta); + h /= 6; + } + return [h, s, l]; + } + + var safeApply = function($scope, fn) { + var phase = $scope.$root.$$phase; + if (phase === '$apply' || phase === '$digest') { + if (fn && (typeof (fn) === 'function')) { + fn(); + } + } else { + $scope.$root.$apply(fn); + } + }; + + angular.module('farbtastic', []) + .directive('ngFarbtastic', + function() { + return { + restrict: 'E', + require: '^ngModel', + link: function($scope, $element, $attrs, ngModel) { + var farbtastic; + + ngModel.$render = function(){ + if (!farbtastic) { + farbtastic = new Farbtastic($element, function(color) { + safeApply($scope, function() { + ngModel.$setViewValue(color); + }); + }, { + color: ngModel.$viewValue + }); + } + else{ + farbtastic.setColor(ngModel.$viewValue); + } + } + } + }; + }); + +})(jQuery); \ No newline at end of file diff --git a/LiveChat/ClientComponents/angular-farbtastic/farbtastic.css b/LiveChat/ClientComponents/angular-farbtastic/farbtastic.css new file mode 100644 index 0000000..48161fb --- /dev/null +++ b/LiveChat/ClientComponents/angular-farbtastic/farbtastic.css @@ -0,0 +1,51 @@ +/** + * Farbtastic Color Picker 1.2 + * © 2008 Steven Wittens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +.farbtastic { + position: relative; +} +.farbtastic * { + position: absolute; + cursor: crosshair; +} +.farbtastic, .farbtastic .wheel { + width: 195px; + height: 195px; +} +.farbtastic .color, .farbtastic .overlay { + top: 47px; + left: 47px; + width: 101px; + height: 101px; +} +.farbtastic .wheel { + background: url(wheel.png) no-repeat; + width: 195px; + height: 195px; +} +.farbtastic .overlay { + background: url(mask.png) no-repeat; +} +.farbtastic .marker { + width: 17px; + height: 17px; + margin: -8px 0 0 -8px; + overflow: hidden; + background: url(marker.png) no-repeat; +} + diff --git a/LiveChat/ClientComponents/angularjs/angular-animate.js b/LiveChat/ClientComponents/angularjs/angular-animate.js new file mode 100644 index 0000000..fc0e217 --- /dev/null +++ b/LiveChat/ClientComponents/angularjs/angular-animate.js @@ -0,0 +1,3721 @@ +/** + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/* jshint ignore:start */ +var noop = angular.noop; +var extend = angular.extend; +var jqLite = angular.element; +var forEach = angular.forEach; +var isArray = angular.isArray; +var isString = angular.isString; +var isObject = angular.isObject; +var isUndefined = angular.isUndefined; +var isDefined = angular.isDefined; +var isFunction = angular.isFunction; +var isElement = angular.isElement; + +var ELEMENT_NODE = 1; +var COMMENT_NODE = 8; + +var NG_ANIMATE_CLASSNAME = 'ng-animate'; +var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren'; + +var isPromiseLike = function(p) { + return p && p.then ? true : false; +} + +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function packageStyles(options) { + var styles = {}; + if (options && (options.to || options.from)) { + styles.to = options.to; + styles.from = options.from; + } + return styles; +} + +function pendClasses(classes, fix, isPrefix) { + var className = ''; + classes = isArray(classes) + ? classes + : classes && isString(classes) && classes.length + ? classes.split(/\s+/) + : []; + forEach(classes, function(klass, i) { + if (klass && klass.length > 0) { + className += (i > 0) ? ' ' : ''; + className += isPrefix ? fix + klass + : klass + fix; + } + }); + return className; +} + +function removeFromArray(arr, val) { + var index = arr.indexOf(val); + if (val >= 0) { + arr.splice(index, 1); + } +} + +function stripCommentsFromElement(element) { + if (element instanceof jqLite) { + switch (element.length) { + case 0: + return []; + break; + + case 1: + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element[0].nodeType === ELEMENT_NODE) { + return element; + } + break; + + default: + return jqLite(extractElementNode(element)); + break; + } + } + + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); + } +} + +function extractElementNode(element) { + if (!element[0]) return element; + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType == ELEMENT_NODE) { + return elm; + } + } +} + +function $$addClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.addClass(elm, className); + }); +} + +function $$removeClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.removeClass(elm, className); + }); +} + +function applyAnimationClassesFactory($$jqLite) { + return function(element, options) { + if (options.addClass) { + $$addClass($$jqLite, element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$removeClass($$jqLite, element, options.removeClass); + options.removeClass = null; + } + } +} + +function prepareAnimationOptions(options) { + options = options || {}; + if (!options.$$prepared) { + var domOperation = options.domOperation || noop; + options.domOperation = function() { + options.$$domOperationFired = true; + domOperation(); + domOperation = noop; + }; + options.$$prepared = true; + } + return options; +} + +function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); +} + +function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } +} + +function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } +} + +function mergeAnimationOptions(element, target, newOptions) { + var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || ''); + var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || ''); + var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove); + + extend(target, newOptions); + + if (classes.addClass) { + target.addClass = classes.addClass; + } else { + target.addClass = null; + } + + if (classes.removeClass) { + target.removeClass = classes.removeClass; + } else { + target.removeClass = null; + } + + return target; +} + +function resolveElementClasses(existing, toAdd, toRemove) { + var ADD_CLASS = 1; + var REMOVE_CLASS = -1; + + var flags = {}; + existing = splitClassesToLookup(existing); + + toAdd = splitClassesToLookup(toAdd); + forEach(toAdd, function(value, key) { + flags[key] = ADD_CLASS; + }); + + toRemove = splitClassesToLookup(toRemove); + forEach(toRemove, function(value, key) { + flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS; + }); + + var classes = { + addClass: '', + removeClass: '' + }; + + forEach(flags, function(val, klass) { + var prop, allow; + if (val === ADD_CLASS) { + prop = 'addClass'; + allow = !existing[klass]; + } else if (val === REMOVE_CLASS) { + prop = 'removeClass'; + allow = existing[klass]; + } + if (allow) { + if (classes[prop].length) { + classes[prop] += ' '; + } + classes[prop] += klass; + } + }); + + function splitClassesToLookup(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; + } + + return classes; +} + +function getDomNode(element) { + return (element instanceof angular.element) ? element[0] : element; +} + +var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) { + var tickQueue = []; + var cancelFn; + + function scheduler(tasks) { + // we make a copy since RAFScheduler mutates the state + // of the passed in array variable and this would be difficult + // to track down on the outside code + tickQueue.push([].concat(tasks)); + nextTick(); + } + + /* waitUntilQuiet does two things: + * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through + * 2. It will delay the next wave of tasks from running until the quiet `fn` has run. + * + * The motivation here is that animation code can request more time from the scheduler + * before the next wave runs. This allows for certain DOM properties such as classes to + * be resolved in time for the next animation to run. + */ + scheduler.waitUntilQuiet = function(fn) { + if (cancelFn) cancelFn(); + + cancelFn = $$rAF(function() { + cancelFn = null; + fn(); + nextTick(); + }); + }; + + return scheduler; + + function nextTick() { + if (!tickQueue.length) return; + + var updatedQueue = []; + for (var i = 0; i < tickQueue.length; i++) { + var innerQueue = tickQueue[i]; + runNextTask(innerQueue); + if (innerQueue.length) { + updatedQueue.push(innerQueue); + } + } + tickQueue = updatedQueue; + + if (!cancelFn) { + $$rAF(function() { + if (!cancelFn) nextTick(); + }); + } + } + + function runNextTask(tasks) { + var nextTask = tasks.shift(); + nextTask(); + } +}]; + +var $$AnimateChildrenDirective = [function() { + return function(scope, element, attrs) { + var val = attrs.ngAnimateChildren; + if (angular.isString(val) && val.length === 0) { //empty attribute + element.data(NG_ANIMATE_CHILDREN_DATA, true); + } else { + attrs.$observe('ngAnimateChildren', function(value) { + value = value === 'on' || value === 'true'; + element.data(NG_ANIMATE_CHILDREN_DATA, value); + }); + } + }; +}]; + +/** + * @ngdoc service + * @name $animateCss + * @kind object + * + * @description + * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes + * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT + * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or + * directives to create more complex animations that can be purely driven using CSS code. + * + * Note that only browsers that support CSS transitions and/or keyframe animations are capable of + * rendering animations triggered via `$animateCss` (bad news for IE9 and lower). + * + * ## Usage + * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that + * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however, + * any automatic control over cancelling animations and/or preventing animations from being run on + * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to + * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger + * the CSS animation. + * + * The example below shows how we can create a folding animation on an element using `ng-if`: + * + * ```html + * + *
+ * This element will go BOOM + *
+ * + * ``` + * + * Now we create the **JavaScript animation** that will trigger the CSS transition: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` + * + * ## More Advanced Uses + * + * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks + * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code. + * + * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation, + * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with + * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order + * to provide a working animation that will run in CSS. + * + * The example below showcases a more advanced version of the `.fold-animation` from the example above: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * addClass: 'red large-text pulse-twice', + * easing: 'ease-out', + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` + * + * Since we're adding/removing CSS classes then the CSS transition will also pick those up: + * + * ```css + * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code, + * the CSS classes below will be transitioned despite them being defined as regular CSS classes */ + * .red { background:red; } + * .large-text { font-size:20px; } + * + * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */ + * .pulse-twice { + * animation: 0.5s pulse linear 2; + * -webkit-animation: 0.5s pulse linear 2; + * } + * + * @keyframes pulse { + * from { transform: scale(0.5); } + * to { transform: scale(1.5); } + * } + * + * @-webkit-keyframes pulse { + * from { -webkit-transform: scale(0.5); } + * to { -webkit-transform: scale(1.5); } + * } + * ``` + * + * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen. + * + * ## How the Options are handled + * + * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation + * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline + * styles using the `from` and `to` properties. + * + * ```js + * var animator = $animateCss(element, { + * from: { background:'red' }, + * to: { background:'blue' } + * }); + * animator.start(); + * ``` + * + * ```css + * .rotating-animation { + * animation:0.5s rotate linear; + * -webkit-animation:0.5s rotate linear; + * } + * + * @keyframes rotate { + * from { transform: rotate(0deg); } + * to { transform: rotate(360deg); } + * } + * + * @-webkit-keyframes rotate { + * from { -webkit-transform: rotate(0deg); } + * to { -webkit-transform: rotate(360deg); } + * } + * ``` + * + * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is + * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition + * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition + * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied + * and spread across the transition and keyframe animation. + * + * ## What is returned + * + * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually + * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are + * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties: + * + * ```js + * var animator = $animateCss(element, { ... }); + * ``` + * + * Now what do the contents of our `animator` variable look like: + * + * ```js + * { + * // starts the animation + * start: Function, + * + * // ends (aborts) the animation + * end: Function + * } + * ``` + * + * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends. + * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been + * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties + * and that changing them will not reconfigure the parameters of the animation. + * + * ### runner.done() vs runner.then() + * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the + * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**. + * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()` + * unless you really need a digest to kick off afterwards. + * + * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss + * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code). + * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works. + * + * @param {DOMElement} element the element that will be animated + * @param {object} options the animation-related options that will be applied during the animation + * + * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied + * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.) + * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both). + * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`). + * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`). + * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation. + * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. + * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation. + * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation. + * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0` + * is provided then the animation will be skipped entirely. + * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is + * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value + * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same + * CSS delay value. + * * `stagger` - A numeric time value representing the delay between successively animated elements + * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) + * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a + * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.) + * + * @return {object} an object with start and end methods and details about the animation. + * + * * `start` - The method to start the animation. This will return a `Promise` when called. + * * `end` - This method will cancel the animation and remove all applied CSS classes and styles. + */ + +// Detect proper transitionend/animationend event names. +var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; + +// If unprefixed events are not supported but webkit-prefixed are, use the latter. +// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. +// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` +// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. +// Register both events in case `window.onanimationend` is not supported because of that, +// do the same for `transitionend` as Safari is likely to exhibit similar behavior. +// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit +// therefore there is no reason to test anymore for other vendor prefixes: +// http://caniuse.com/#search=transition +if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { + CSS_PREFIX = '-webkit-'; + TRANSITION_PROP = 'WebkitTransition'; + TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; +} else { + TRANSITION_PROP = 'transition'; + TRANSITIONEND_EVENT = 'transitionend'; +} + +if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { + CSS_PREFIX = '-webkit-'; + ANIMATION_PROP = 'WebkitAnimation'; + ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; +} else { + ANIMATION_PROP = 'animation'; + ANIMATIONEND_EVENT = 'animationend'; +} + +var DURATION_KEY = 'Duration'; +var PROPERTY_KEY = 'Property'; +var DELAY_KEY = 'Delay'; +var TIMING_KEY = 'TimingFunction'; +var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; +var ANIMATION_PLAYSTATE_KEY = 'PlayState'; +var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; +var CLOSING_TIME_BUFFER = 1.5; +var ONE_SECOND = 1000; +var BASE_TEN = 10; + +var SAFE_FAST_FORWARD_DURATION_VALUE = 9999; + +var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY; +var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY; + +var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY; +var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY; + +var DETECT_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + transitionProperty: TRANSITION_PROP + PROPERTY_KEY, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP, + animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY +}; + +var DETECT_STAGGER_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP +}; + +function computeCssStyles($window, element, properties) { + var styles = Object.create(null); + var detectedStyles = $window.getComputedStyle(element) || {}; + forEach(properties, function(formalStyleName, actualStyleName) { + var val = detectedStyles[formalStyleName]; + if (val) { + var c = val.charAt(0); + + // only numerical-based values have a negative sign or digit as the first value + if (c === '-' || c === '+' || c >= 0) { + val = parseMaxTime(val); + } + + // by setting this to null in the event that the delay is not set or is set directly as 0 + // then we can still allow for zegative values to be used later on and not mistake this + // value for being greater than any other negative value. + if (val === 0) { + val = null; + } + styles[actualStyleName] = val; + } + }); + + return styles; +} + +function parseMaxTime(str) { + var maxValue = 0; + var values = str.split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) == 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; +} + +function truthyTimingValue(val) { + return val === 0 || val != null; +} + +function getCssTransitionDurationStyle(duration, applyOnlyDuration) { + var style = TRANSITION_PROP; + var value = duration + 's'; + if (applyOnlyDuration) { + style += DURATION_KEY; + } else { + value += ' linear all'; + } + return [style, value]; +} + +function getCssKeyframeDurationStyle(duration) { + return [ANIMATION_DURATION_PROP, duration + 's']; +} + +function getCssDelayStyle(delay, isKeyframeAnimation) { + var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP; + return [prop, delay + 's']; +} + +function blockTransitions(node, duration) { + // we use a negative delay value since it performs blocking + // yet it doesn't kill any existing transitions running on the + // same element which makes this safe for class-based animations + var value = duration ? '-' + duration + 's' : ''; + applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]); + return [TRANSITION_DELAY_PROP, value]; +} + +function blockKeyframeAnimations(node, applyBlock) { + var value = applyBlock ? 'paused' : ''; + var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY; + applyInlineStyle(node, [key, value]); + return [key, value]; +} + +function applyInlineStyle(node, styleTuple) { + var prop = styleTuple[0]; + var value = styleTuple[1]; + node.style[prop] = value; +} + +function createLocalCacheLookup() { + var cache = Object.create(null); + return { + flush: function() { + cache = Object.create(null); + }, + + count: function(key) { + var entry = cache[key]; + return entry ? entry.total : 0; + }, + + get: function(key) { + var entry = cache[key]; + return entry && entry.value; + }, + + put: function(key, value) { + if (!cache[key]) { + cache[key] = { total: 1, value: value }; + } else { + cache[key].total++; + } + } + }; +} + +var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { + var gcsLookup = createLocalCacheLookup(); + var gcsStaggerLookup = createLocalCacheLookup(); + + this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', + '$document', '$sniffer', '$$rAFScheduler', + function($window, $$jqLite, $$AnimateRunner, $timeout, + $document, $sniffer, $$rAFScheduler) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var parentCounter = 0; + function gcsHashFn(node, extraClasses) { + var KEY = "$$ngAnimateParentKey"; + var parentNode = node.parentNode; + var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter); + return parentID + '-' + node.getAttribute('class') + '-' + extraClasses; + } + + function computeCachedCssStyles(node, className, cacheKey, properties) { + var timings = gcsLookup.get(cacheKey); + + if (!timings) { + timings = computeCssStyles($window, node, properties); + if (timings.animationIterationCount === 'infinite') { + timings.animationIterationCount = 1; + } + } + + // we keep putting this in multiple times even though the value and the cacheKey are the same + // because we're keeping an interal tally of how many duplicate animations are detected. + gcsLookup.put(cacheKey, timings); + return timings; + } + + function computeCachedCssStaggerStyles(node, className, cacheKey, properties) { + var stagger; + + // if we have one or more existing matches of matching elements + // containing the same parent + CSS styles (which is how cacheKey works) + // then staggering is possible + if (gcsLookup.count(cacheKey) > 0) { + stagger = gcsStaggerLookup.get(cacheKey); + + if (!stagger) { + var staggerClassName = pendClasses(className, '-stagger'); + + $$jqLite.addClass(node, staggerClassName); + + stagger = computeCssStyles($window, node, properties); + + // force the conversion of a null value to zero incase not set + stagger.animationDuration = Math.max(stagger.animationDuration, 0); + stagger.transitionDuration = Math.max(stagger.transitionDuration, 0); + + $$jqLite.removeClass(node, staggerClassName); + + gcsStaggerLookup.put(cacheKey, stagger); + } + } + + return stagger || {}; + } + + var bod = getDomNode($document).body; + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + rafWaitQueue.push(callback); + $$rAFScheduler.waitUntilQuiet(function() { + gcsLookup.flush(); + gcsStaggerLookup.flush(); + + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + var width = bod.offsetWidth + 1; + + // we use a for loop to ensure that if the queue is changed + // during this looping then it will consider new requests + for (var i = 0; i < rafWaitQueue.length; i++) { + rafWaitQueue[i](width); + } + rafWaitQueue.length = 0; + }); + } + + return init; + + function computeTimings(node, className, cacheKey) { + var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES); + var aD = timings.animationDelay; + var tD = timings.transitionDelay; + timings.maxDelay = aD && tD + ? Math.max(aD, tD) + : (aD || tD); + timings.maxDuration = Math.max( + timings.animationDuration * timings.animationIterationCount, + timings.transitionDuration); + + return timings; + } + + function init(element, options) { + var node = getDomNode(element); + if (!node || !node.parentNode) { + return closeAndReturnNoopAnimator(); + } + + options = prepareAnimationOptions(options); + + var temporaryStyles = []; + var classes = element.attr('class'); + var styles = packageStyles(options); + var animationClosed; + var animationPaused; + var animationCompleted; + var runner; + var runnerHost; + var maxDelay; + var maxDelayTime; + var maxDuration; + var maxDurationTime; + + if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) { + return closeAndReturnNoopAnimator(); + } + + var method = options.event && isArray(options.event) + ? options.event.join(' ') + : options.event; + + var isStructural = method && options.structural; + var structuralClassName = ''; + var addRemoveClassName = ''; + + if (isStructural) { + structuralClassName = pendClasses(method, 'ng-', true); + } else if (method) { + structuralClassName = method; + } + + if (options.addClass) { + addRemoveClassName += pendClasses(options.addClass, '-add'); + } + + if (options.removeClass) { + if (addRemoveClassName.length) { + addRemoveClassName += ' '; + } + addRemoveClassName += pendClasses(options.removeClass, '-remove'); + } + + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + if (options.applyClassesEarly && addRemoveClassName.length) { + applyAnimationClasses(element, options); + addRemoveClassName = ''; + } + + var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); + var fullClassName = classes + ' ' + setupClasses; + var activeClasses = pendClasses(setupClasses, '-active'); + var hasToStyles = styles.to && Object.keys(styles.to).length > 0; + var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0; + + // there is no way we can trigger an animation if no styles and + // no classes are being applied which would then trigger a transition, + // unless there a is raw keyframe value that is applied to the element. + if (!containsKeyframeAnimation + && !hasToStyles + && !setupClasses) { + return closeAndReturnNoopAnimator(); + } + + var cacheKey, stagger; + if (options.stagger > 0) { + var staggerVal = parseFloat(options.stagger); + stagger = { + transitionDelay: staggerVal, + animationDelay: staggerVal, + transitionDuration: 0, + animationDuration: 0 + }; + } else { + cacheKey = gcsHashFn(node, fullClassName); + stagger = computeCachedCssStaggerStyles(node, setupClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES); + } + + $$jqLite.addClass(element, setupClasses); + + var applyOnlyDuration; + + if (options.transitionStyle) { + var transitionStyle = [TRANSITION_PROP, options.transitionStyle]; + applyInlineStyle(node, transitionStyle); + temporaryStyles.push(transitionStyle); + } + + if (options.duration >= 0) { + applyOnlyDuration = node.style[TRANSITION_PROP].length > 0; + var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration); + + // we set the duration so that it will be picked up by getComputedStyle later + applyInlineStyle(node, durationStyle); + temporaryStyles.push(durationStyle); + } + + if (options.keyframeStyle) { + var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle]; + applyInlineStyle(node, keyframeStyle); + temporaryStyles.push(keyframeStyle); + } + + var itemIndex = stagger + ? options.staggerIndex >= 0 + ? options.staggerIndex + : gcsLookup.count(cacheKey) + : 0; + + var isFirst = itemIndex === 0; + + // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY + // without causing any combination of transitions to kick in. By adding a negative delay value + // it forces the setup class' transition to end immediately. We later then remove the negative + // transition delay to allow for the transition to naturally do it's thing. The beauty here is + // that if there is no transition defined then nothing will happen and this will also allow + // other transitions to be stacked on top of each other without any chopping them out. + if (isFirst) { + blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE); + } + + var timings = computeTimings(node, fullClassName, cacheKey); + var relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + var flags = {}; + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all'; + flags.applyTransitionDuration = hasToStyles && ( + (flags.hasTransitions && !flags.hasTransitionAll) + || (flags.hasAnimations && !flags.hasTransitions)); + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; + + if (flags.applyTransitionDuration || flags.applyAnimationDuration) { + maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; + + if (flags.applyTransitionDuration) { + flags.hasTransitions = true; + timings.transitionDuration = maxDuration; + applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0; + temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration)); + } + + if (flags.applyAnimationDuration) { + flags.hasAnimations = true; + timings.animationDuration = maxDuration; + temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration)); + } + } + + if (maxDuration === 0 && !flags.recalculateTimingStyles) { + return closeAndReturnNoopAnimator(); + } + + // we need to recalculate the delay value since we used a pre-emptive negative + // delay value and the delay value is required for the final event checking. This + // property will ensure that this will happen after the RAF phase has passed. + if (options.duration == null && timings.transitionDuration > 0) { + flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst; + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + if (!options.skipBlocking) { + flags.blockTransition = timings.transitionDuration > 0; + flags.blockKeyframeAnimation = timings.animationDuration > 0 && + stagger.animationDelay > 0 && + stagger.animationDuration === 0; + } + + applyAnimationFromStyles(element, options); + if (!flags.blockTransition) { + blockTransitions(node, false); + } + + applyBlocking(maxDuration); + + // TODO(matsko): for 1.5 change this code to have an animator object for better debugging + return { + $$willAnimate: true, + end: endFn, + start: function() { + if (animationClosed) return; + + runnerHost = { + end: endFn, + cancel: cancelFn, + resume: null, //this will be set during the start() phase + pause: null + }; + + runner = new $$AnimateRunner(runnerHost); + + waitUntilQuiet(start); + + // we don't have access to pause/resume the animation + // since it hasn't run yet. AnimateRunner will therefore + // set noop functions for resume and pause and they will + // later be overridden once the animation is triggered + return runner; + } + }; + + function endFn() { + close(); + } + + function cancelFn() { + close(true); + } + + function close(rejected) { // jshint ignore:line + // if the promise has been called already then we shouldn't close + // the animation again + if (animationClosed || (animationCompleted && animationPaused)) return; + animationClosed = true; + animationPaused = false; + + $$jqLite.removeClass(element, setupClasses); + $$jqLite.removeClass(element, activeClasses); + + blockKeyframeAnimations(node, false); + blockTransitions(node, false); + + forEach(temporaryStyles, function(entry) { + // There is only one way to remove inline style properties entirely from elements. + // By using `removeProperty` this works, but we need to convert camel-cased CSS + // styles down to hyphenated values. + node.style[entry[0]] = ''; + }); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + + // the reason why we have this option is to allow a synchronous closing callback + // that is fired as SOON as the animation ends (when the CSS is removed) or if + // the animation never takes off at all. A good example is a leave animation since + // the element must be removed just after the animation is over or else the element + // will appear on screen for one animation frame causing an overbearing flicker. + if (options.onDone) { + options.onDone(); + } + + // if the preparation function fails then the promise is not setup + if (runner) { + runner.complete(!rejected); + } + } + + function applyBlocking(duration) { + if (flags.blockTransition) { + blockTransitions(node, duration); + } + + if (flags.blockKeyframeAnimation) { + blockKeyframeAnimations(node, !!duration); + } + } + + function closeAndReturnNoopAnimator() { + runner = new $$AnimateRunner({ + end: endFn, + cancel: cancelFn + }); + + close(); + + return { + $$willAnimate: false, + start: function() { + return runner; + }, + end: endFn + }; + } + + function start() { + if (animationClosed) return; + if (!node.parentNode) { + close(); + return; + } + + var startTime, events = []; + + // even though we only pause keyframe animations here the pause flag + // will still happen when transitions are used. Only the transition will + // not be paused since that is not possible. If the animation ends when + // paused then it will not complete until unpaused or cancelled. + var playPause = function(playAnimation) { + if (!animationCompleted) { + animationPaused = !playAnimation; + if (timings.animationDuration) { + var value = blockKeyframeAnimations(node, animationPaused); + animationPaused + ? temporaryStyles.push(value) + : removeFromArray(temporaryStyles, value); + } + } else if (animationPaused && playAnimation) { + animationPaused = false; + close(); + } + }; + + // checking the stagger duration prevents an accidently cascade of the CSS delay style + // being inherited from the parent. If the transition duration is zero then we can safely + // rely that the delay value is an intential stagger delay style. + var maxStagger = itemIndex > 0 + && ((timings.transitionDuration && stagger.transitionDuration === 0) || + (timings.animationDuration && stagger.animationDuration === 0)) + && Math.max(stagger.animationDelay, stagger.transitionDelay); + if (maxStagger) { + $timeout(triggerAnimationStart, + Math.floor(maxStagger * itemIndex * ONE_SECOND), + false); + } else { + triggerAnimationStart(); + } + + // this will decorate the existing promise runner with pause/resume methods + runnerHost.resume = function() { + playPause(true); + }; + + runnerHost.pause = function() { + playPause(false); + }; + + function triggerAnimationStart() { + // just incase a stagger animation kicks in when the animation + // itself was cancelled entirely + if (animationClosed) return; + + applyBlocking(false); + + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[key] = value; + }); + + applyAnimationClasses(element, options); + $$jqLite.addClass(element, activeClasses); + + if (flags.recalculateTimingStyles) { + fullClassName = node.className + ' ' + setupClasses; + cacheKey = gcsHashFn(node, fullClassName); + + timings = computeTimings(node, fullClassName, cacheKey); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + if (maxDuration === 0) { + close(); + return; + } + + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + } + + if (flags.applyTransitionDelay || flags.applyAnimationDelay) { + relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay) + ? parseFloat(options.delay) + : relativeDelay; + + maxDelay = Math.max(relativeDelay, 0); + + var delayStyle; + if (flags.applyTransitionDelay) { + timings.transitionDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + + if (flags.applyAnimationDelay) { + timings.animationDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay, true); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + + if (options.easing) { + var easeProp, easeVal = options.easing; + if (flags.hasTransitions) { + easeProp = TRANSITION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + if (flags.hasAnimations) { + easeProp = ANIMATION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + } + + if (timings.transitionDuration) { + events.push(TRANSITIONEND_EVENT); + } + + if (timings.animationDuration) { + events.push(ANIMATIONEND_EVENT); + } + + startTime = Date.now(); + element.on(events.join(' '), onAnimationProgress); + $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime); + + applyAnimationToStyles(element, options); + } + + function onAnimationExpired() { + // although an expired animation is a failed animation, getting to + // this outcome is very easy if the CSS code screws up. Therefore we + // should still continue normally as if the animation completed correctly. + close(); + } + + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); + + /* Firefox (or possibly just Gecko) likes to not round values up + * when a ms measurement is used for the animation */ + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); + + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animations sometimes close off early */ + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + // we set this flag to ensure that if the transition is paused then, when resumed, + // the animation will automatically close itself since transitions cannot be paused. + animationCompleted = true; + close(); + } + } + } + } + }]; +}]; + +var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateCssDriver'); + + var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim'; + var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor'; + + var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out'; + var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in'; + + this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$document', '$sniffer', + function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $document, $sniffer) { + + // only browsers that support these properties can render animations + if (!$sniffer.animations && !$sniffer.transitions) return noop; + + var bodyNode = getDomNode($document).body; + var rootNode = getDomNode($rootElement); + + var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); + + return function initDriverFn(animationDetails) { + return animationDetails.from && animationDetails.to + ? prepareFromToAnchorAnimation(animationDetails.from, + animationDetails.to, + animationDetails.classes, + animationDetails.anchors) + : prepareRegularAnimation(animationDetails); + }; + + function filterCssClasses(classes) { + //remove all the `ng-` stuff + return classes.replace(/\bng-\S+\b/g, ''); + } + + function getUniqueValues(a, b) { + if (isString(a)) a = a.split(' '); + if (isString(b)) b = b.split(' '); + return a.filter(function(val) { + return b.indexOf(val) === -1; + }).join(' '); + } + + function prepareAnchoredAnimation(classes, outAnchor, inAnchor) { + var clone = jqLite(getDomNode(outAnchor).cloneNode(true)); + var startingClasses = filterCssClasses(getClassVal(clone)); + + outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + + clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME); + + rootBodyElement.append(clone); + + var animatorIn, animatorOut = prepareOutAnimation(); + + // the user may not end up using the `out` animation and + // only making use of the `in` animation or vice-versa. + // In either case we should allow this and not assume the + // animation is over unless both animations are not used. + if (!animatorOut) { + animatorIn = prepareInAnimation(); + if (!animatorIn) { + return end(); + } + } + + var startingAnimator = animatorOut || animatorIn; + + return { + start: function() { + var runner; + + var currentAnimation = startingAnimator.start(); + currentAnimation.done(function() { + currentAnimation = null; + if (!animatorIn) { + animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; + } + } + // in the event that there is no `in` animation + end(); + runner.complete(); + }); + + runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn + }); + + return runner; + + function endFn() { + if (currentAnimation) { + currentAnimation.end(); + } + } + } + }; + + function calculateAnchorStyles(anchor) { + var styles = {}; + + var coords = getDomNode(anchor).getBoundingClientRect(); + + // we iterate directly since safari messes up and doesn't return + // all the keys for the coods object when iterated + forEach(['width','height','top','left'], function(key) { + var value = coords[key]; + switch (key) { + case 'top': + value += bodyNode.scrollTop; + break; + case 'left': + value += bodyNode.scrollLeft; + break; + } + styles[key] = Math.floor(value) + 'px'; + }); + return styles; + } + + function prepareOutAnimation() { + var animator = $animateCss(clone, { + addClass: NG_OUT_ANCHOR_CLASS_NAME, + delay: true, + from: calculateAnchorStyles(outAnchor) + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function getClassVal(element) { + return element.attr('class') || ''; + } + + function prepareInAnimation() { + var endingClasses = filterCssClasses(getClassVal(inAnchor)); + var toAdd = getUniqueValues(endingClasses, startingClasses); + var toRemove = getUniqueValues(startingClasses, endingClasses); + + var animator = $animateCss(clone, { + to: calculateAnchorStyles(inAnchor), + addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd, + removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove, + delay: true + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function end() { + clone.remove(); + outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + } + } + + function prepareFromToAnchorAnimation(from, to, classes, anchors) { + var fromAnimation = prepareRegularAnimation(from); + var toAnimation = prepareRegularAnimation(to); + + var anchorAnimations = []; + forEach(anchors, function(anchor) { + var outElement = anchor['out']; + var inElement = anchor['in']; + var animator = prepareAnchoredAnimation(classes, outElement, inElement); + if (animator) { + anchorAnimations.push(animator); + } + }); + + // no point in doing anything when there are no elements to animate + if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + forEach(anchorAnimations, function(animation) { + animationRunners.push(animation.start()); + }); + + var runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn // CSS-driven animations cannot be cancelled, only ended + }); + + $$AnimateRunner.all(animationRunners, function(status) { + runner.complete(status); + }); + + return runner; + + function endFn() { + forEach(animationRunners, function(runner) { + runner.end(); + }); + } + } + }; + } + + function prepareRegularAnimation(animationDetails) { + var element = animationDetails.element; + var options = animationDetails.options || {}; + + if (animationDetails.structural) { + // structural animations ensure that the CSS classes are always applied + // before the detection starts. + options.structural = options.applyClassesEarly = true; + + // we special case the leave animation since we want to ensure that + // the element is removed as soon as the animation is over. Otherwise + // a flicker might appear or the element may not be removed at all + options.event = animationDetails.event; + if (options.event === 'leave') { + options.onDone = options.domOperation; + } + } else { + options.event = null; + } + + var animator = $animateCss(element, options); + + // the driver lookup code inside of $$animation attempts to spawn a + // driver one by one until a driver returns a.$$willAnimate animator object. + // $animateCss will always return an object, however, it will pass in + // a flag as a hint as to whether an animation was detected or not + return animator.$$willAnimate ? animator : null; + } + }]; +}]; + +// TODO(matsko): use caching here to speed things up for detection +// TODO(matsko): add documentation +// by the time... + +var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) { + this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite', + function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + // $animateJs(element, 'enter'); + return function(element, event, classes, options) { + // the `classes` argument is optional and if it is not used + // then the classes will be resolved from the element's className + // property as well as options.addClass/options.removeClass. + if (arguments.length === 3 && isObject(classes)) { + options = classes; + classes = null; + } + + options = prepareAnimationOptions(options); + if (!classes) { + classes = element.attr('class') || ''; + if (options.addClass) { + classes += ' ' + options.addClass; + } + if (options.removeClass) { + classes += ' ' + options.removeClass; + } + } + + var classesToAdd = options.addClass; + var classesToRemove = options.removeClass; + + // the lookupAnimations function returns a series of animation objects that are + // matched up with one or more of the CSS classes. These animation objects are + // defined via the module.animation factory function. If nothing is detected then + // we don't return anything which then makes $animation query the next driver. + var animations = lookupAnimations(classes); + var before, after; + if (animations.length) { + var afterFn, beforeFn; + if (event == 'leave') { + beforeFn = 'leave'; + afterFn = 'afterLeave'; // TODO(matsko): get rid of this + } else { + beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + afterFn = event; + } + + if (event !== 'enter' && event !== 'move') { + before = packageAnimations(element, event, options, animations, beforeFn); + } + after = packageAnimations(element, event, options, animations, afterFn); + } + + // no matching animations + if (!before && !after) return; + + function applyOptions() { + options.domOperation(); + applyAnimationClasses(element, options); + } + + return { + start: function() { + var closeActiveAnimations; + var chain = []; + + if (before) { + chain.push(function(fn) { + closeActiveAnimations = before(fn); + }); + } + + if (chain.length) { + chain.push(function(fn) { + applyOptions(); + fn(true); + }); + } else { + applyOptions(); + } + + if (after) { + chain.push(function(fn) { + closeActiveAnimations = after(fn); + }); + } + + var animationClosed = false; + var runner = new $$AnimateRunner({ + end: function() { + endAnimations(); + }, + cancel: function() { + endAnimations(true); + } + }); + + $$AnimateRunner.chain(chain, onComplete); + return runner; + + function onComplete(success) { + animationClosed = true; + applyOptions(); + applyAnimationStyles(element, options); + runner.complete(success); + } + + function endAnimations(cancelled) { + if (!animationClosed) { + (closeActiveAnimations || noop)(cancelled); + onComplete(cancelled); + } + } + } + }; + + function executeAnimationFn(fn, element, event, options, onDone) { + var args; + switch (event) { + case 'animate': + args = [element, options.from, options.to, onDone]; + break; + + case 'setClass': + args = [element, classesToAdd, classesToRemove, onDone]; + break; + + case 'addClass': + args = [element, classesToAdd, onDone]; + break; + + case 'removeClass': + args = [element, classesToRemove, onDone]; + break; + + default: + args = [element, onDone]; + break; + } + + args.push(options); + + var value = fn.apply(fn, args); + if (value) { + if (isFunction(value.start)) { + value = value.start(); + } + + if (value instanceof $$AnimateRunner) { + value.done(onDone); + } else if (isFunction(value)) { + // optional onEnd / onCancel callback + return value; + } + } + + return noop; + } + + function groupEventedAnimations(element, event, options, animations, fnName) { + var operations = []; + forEach(animations, function(ani) { + var animation = ani[fnName]; + if (!animation) return; + + // note that all of these animations will run in parallel + operations.push(function() { + var runner; + var endProgressCb; + + var resolved = false; + var onAnimationComplete = function(rejected) { + if (!resolved) { + resolved = true; + (endProgressCb || noop)(rejected); + runner.complete(!rejected); + } + }; + + runner = new $$AnimateRunner({ + end: function() { + onAnimationComplete(); + }, + cancel: function() { + onAnimationComplete(true); + } + }); + + endProgressCb = executeAnimationFn(animation, element, event, options, function(result) { + var cancelled = result === false; + onAnimationComplete(cancelled); + }); + + return runner; + }); + }); + + return operations; + } + + function packageAnimations(element, event, options, animations, fnName) { + var operations = groupEventedAnimations(element, event, options, animations, fnName); + if (operations.length === 0) { + var a,b; + if (fnName === 'beforeSetClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass'); + } else if (fnName === 'setClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass'); + } + + if (a) { + operations = operations.concat(a); + } + if (b) { + operations = operations.concat(b); + } + } + + if (operations.length === 0) return; + + // TODO(matsko): add documentation + return function startAnimation(callback) { + var runners = []; + if (operations.length) { + forEach(operations, function(animateFn) { + runners.push(animateFn()); + }); + } + + runners.length ? $$AnimateRunner.all(runners, callback) : callback(); + + return function endFn(reject) { + forEach(runners, function(runner) { + reject ? runner.cancel() : runner.end(); + }); + }; + }; + } + }; + + function lookupAnimations(classes) { + classes = isArray(classes) ? classes : classes.split(' '); + var matches = [], flagMap = {}; + for (var i=0; i < classes.length; i++) { + var klass = classes[i], + animationFactory = $animateProvider.$$registeredAnimations[klass]; + if (animationFactory && !flagMap[klass]) { + matches.push($injector.get(animationFactory)); + flagMap[klass] = true; + } + } + return matches; + } + }]; +}]; + +var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateJsDriver'); + this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) { + return function initDriverFn(animationDetails) { + if (animationDetails.from && animationDetails.to) { + var fromAnimation = prepareAnimation(animationDetails.from); + var toAnimation = prepareAnimation(animationDetails.to); + if (!fromAnimation && !toAnimation) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + $$AnimateRunner.all(animationRunners, done); + + var runner = new $$AnimateRunner({ + end: endFnFactory(), + cancel: endFnFactory() + }); + + return runner; + + function endFnFactory() { + return function() { + forEach(animationRunners, function(runner) { + // at this point we cannot cancel animations for groups just yet. 1.5+ + runner.end(); + }); + }; + } + + function done(status) { + runner.complete(status); + } + } + }; + } else { + return prepareAnimation(animationDetails); + } + }; + + function prepareAnimation(animationDetails) { + // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations + var element = animationDetails.element; + var event = animationDetails.event; + var options = animationDetails.options; + var classes = animationDetails.classes; + return $$animateJs(element, event, classes, options); + } + }]; +}]; + +var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var NG_ANIMATE_PIN_DATA = '$ngAnimatePin'; +var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { + var PRE_DIGEST_STATE = 1; + var RUNNING_STATE = 2; + + var rules = this.rules = { + skip: [], + cancel: [], + join: [] + }; + + function isAllowed(ruleType, element, currentAnimation, previousAnimation) { + return rules[ruleType].some(function(fn) { + return fn(element, currentAnimation, previousAnimation); + }); + } + + function hasAnimationClasses(options, and) { + options = options || {}; + var a = (options.addClass || '').length > 0; + var b = (options.removeClass || '').length > 0; + return and ? a && b : a || b; + } + + rules.join.push(function(element, newAnimation, currentAnimation) { + // if the new animation is class-based then we can just tack that on + return !newAnimation.structural && hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // there is no need to animate anything if no classes are being added and + // there is no structural animation that will be triggered + return !newAnimation.structural && !hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // why should we trigger a new structural animation if the element will + // be removed from the DOM anyway? + return currentAnimation.event == 'leave' && newAnimation.structural; + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // if there is a current animation then skip the class-based animation + return currentAnimation.structural && !newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // there can never be two structural animations running at the same time + return currentAnimation.structural && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // if the previous animation is already running, but the new animation will + // be triggered, but the new animation is structural + return currentAnimation.state === RUNNING_STATE && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + var nO = newAnimation.options; + var cO = currentAnimation.options; + + // if the exact same CSS class is added/removed then it's safe to cancel it + return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass); + }); + + this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap', + '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', + function($$rAF, $rootScope, $rootElement, $document, $$HashMap, + $$animation, $$AnimateRunner, $templateRequest, $$jqLite) { + + var activeAnimationsLookup = new $$HashMap(); + var disabledElementsLookup = new $$HashMap(); + + var animationsEnabled = null; + + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( + function() { return $templateRequest.totalPendingRequests === 0; }, + function(isEmpty) { + if (!isEmpty) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + // we check for null directly in the event that the application already called + // .enabled() with whatever arguments that it provided it with + if (animationsEnabled === null) { + animationsEnabled = true; + } + }); + }); + } + ); + + var bodyElement = jqLite($document[0].body); + + var callbackRegistry = {}; + + // remember that the classNameFilter is set during the provider/config + // stage therefore we can optimize here and setup a helper function + var classNameFilter = $animateProvider.classNameFilter(); + var isAnimatableClassName = !classNameFilter + ? function() { return true; } + : function(className) { + return classNameFilter.test(className); + }; + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function normalizeAnimationOptions(element, options) { + return mergeAnimationOptions(element, options, {}); + } + + function findCallbacks(element, event) { + var targetNode = getDomNode(element); + + var matches = []; + var entries = callbackRegistry[event]; + if (entries) { + forEach(entries, function(entry) { + if (entry.node.contains(targetNode)) { + matches.push(entry.callback); + } + }); + } + + return matches; + } + + function triggerCallback(event, element, phase, data) { + $$rAF(function() { + forEach(findCallbacks(element, event), function(callback) { + callback(element, phase, data); + }); + }); + } + + return { + on: function(event, container, callback) { + var node = extractElementNode(container); + callbackRegistry[event] = callbackRegistry[event] || []; + callbackRegistry[event].push({ + node: node, + callback: callback + }); + }, + + off: function(event, container, callback) { + var entries = callbackRegistry[event]; + if (!entries) return; + + callbackRegistry[event] = arguments.length === 1 + ? null + : filterFromRegistry(entries, container, callback); + + function filterFromRegistry(list, matchContainer, matchCallback) { + var containerNode = extractElementNode(matchContainer); + return list.filter(function(entry) { + var isMatch = entry.node === containerNode && + (!matchCallback || entry.callback === matchCallback); + return !isMatch; + }); + } + }, + + pin: function(element, parentElement) { + assertArg(isElement(element), 'element', 'not an element'); + assertArg(isElement(parentElement), 'parentElement', 'not an element'); + element.data(NG_ANIMATE_PIN_DATA, parentElement); + }, + + push: function(element, event, options, domOperation) { + options = options || {}; + options.domOperation = domOperation; + return queueAnimation(element, event, options); + }, + + // this method has four signatures: + // () - global getter + // (bool) - global setter + // (element) - element getter + // (element, bool) - element setter + enabled: function(element, bool) { + var argCount = arguments.length; + + if (argCount === 0) { + // () - Global getter + bool = !!animationsEnabled; + } else { + var hasElement = isElement(element); + + if (!hasElement) { + // (bool) - Global setter + bool = animationsEnabled = !!element; + } else { + var node = getDomNode(element); + var recordExists = disabledElementsLookup.get(node); + + if (argCount === 1) { + // (element) - Element getter + bool = !recordExists; + } else { + // (element, bool) - Element setter + bool = !!bool; + if (!bool) { + disabledElementsLookup.put(node, true); + } else if (recordExists) { + disabledElementsLookup.remove(node); + } + } + } + } + + return bool; + } + }; + + function queueAnimation(element, event, options) { + var node, parent; + element = stripCommentsFromElement(element); + if (element) { + node = getDomNode(element); + parent = element.parent(); + } + + options = prepareAnimationOptions(options); + + // we create a fake runner with a working promise. + // These methods will become available after the digest has passed + var runner = new $$AnimateRunner(); + + // there are situations where a directive issues an animation for + // a jqLite wrapper that contains only comment nodes... If this + // happens then there is no way we can perform an animation + if (!node) { + close(); + return runner; + } + + if (isArray(options.addClass)) { + options.addClass = options.addClass.join(' '); + } + + if (isArray(options.removeClass)) { + options.removeClass = options.removeClass.join(' '); + } + + if (options.from && !isObject(options.from)) { + options.from = null; + } + + if (options.to && !isObject(options.to)) { + options.to = null; + } + + var className = [node.className, options.addClass, options.removeClass].join(' '); + if (!isAnimatableClassName(className)) { + close(); + return runner; + } + + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // this is a hard disable of all animations for the application or on + // the element itself, therefore there is no need to continue further + // past this point if not enabled + var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node); + var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {}; + var hasExistingAnimation = !!existingAnimation.state; + + // there is no point in traversing the same collection of parent ancestors if a followup + // animation will be run on the same element that already did all that checking work + if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) { + skipAnimations = !areAnimationsAllowed(element, parent, event); + } + + if (skipAnimations) { + close(); + return runner; + } + + if (isStructural) { + closeChildAnimations(element); + } + + var newAnimation = { + structural: isStructural, + element: element, + event: event, + close: close, + options: options, + runner: runner + }; + + if (hasExistingAnimation) { + var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation); + if (skipAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + close(); + return runner; + } else { + mergeAnimationOptions(element, existingAnimation.options, options); + return existingAnimation.runner; + } + } + + var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation); + if (cancelAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + // this will end the animation right away and it is safe + // to do so since the animation is already running and the + // runner callback code will run in async + existingAnimation.runner.end(); + } else if (existingAnimation.structural) { + // this means that the animation is queued into a digest, but + // hasn't started yet. Therefore it is safe to run the close + // method which will call the runner methods in async. + existingAnimation.close(); + } else { + // this will merge the existing animation options into this new follow-up animation + mergeAnimationOptions(element, newAnimation.options, existingAnimation.options); + } + } else { + // a joined animation means that this animation will take over the existing one + // so an example would involve a leave animation taking over an enter. Then when + // the postDigest kicks in the enter will be ignored. + var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation); + if (joinAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + normalizeAnimationOptions(element, options); + } else { + event = newAnimation.event = existingAnimation.event; + options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options); + return runner; + } + } + } + } else { + // normalization in this case means that it removes redundant CSS classes that + // already exist (addClass) or do not exist (removeClass) on the element + normalizeAnimationOptions(element, options); + } + + // when the options are merged and cleaned up we may end up not having to do + // an animation at all, therefore we should check this before issuing a post + // digest callback. Structural animations will always run no matter what. + var isValidAnimation = newAnimation.structural; + if (!isValidAnimation) { + // animate (from/to) can be quickly checked first, otherwise we check if any classes are present + isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0) + || hasAnimationClasses(newAnimation.options); + } + + if (!isValidAnimation) { + close(); + clearElementAnimationState(element); + return runner; + } + + if (isStructural) { + closeParentClassBasedAnimations(parent); + } + + // the counter keeps track of cancelled animations + var counter = (existingAnimation.counter || 0) + 1; + newAnimation.counter = counter; + + markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation); + + $rootScope.$$postDigest(function() { + var animationDetails = activeAnimationsLookup.get(node); + var animationCancelled = !animationDetails; + animationDetails = animationDetails || {}; + + // if addClass/removeClass is called before something like enter then the + // registered parent element may not be present. The code below will ensure + // that a final value for parent element is obtained + var parentElement = element.parent() || []; + + // animate/structural/class-based animations all have requirements. Otherwise there + // is no point in performing an animation. The parent node must also be set. + var isValidAnimation = parentElement.length > 0 + && (animationDetails.event === 'animate' + || animationDetails.structural + || hasAnimationClasses(animationDetails.options)); + + // this means that the previous animation was cancelled + // even if the follow-up animation is the same event + if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) { + // if another animation did not take over then we need + // to make sure that the domOperation and options are + // handled accordingly + if (animationCancelled) { + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + } + + // if the event changed from something like enter to leave then we do + // it, otherwise if it's the same then the end result will be the same too + if (animationCancelled || (isStructural && animationDetails.event !== event)) { + options.domOperation(); + runner.end(); + } + + // in the event that the element animation was not cancelled or a follow-up animation + // isn't allowed to animate from here then we need to clear the state of the element + // so that any future animations won't read the expired animation data. + if (!isValidAnimation) { + clearElementAnimationState(element); + } + + return; + } + + // this combined multiple class to addClass / removeClass into a setClass event + // so long as a structural event did not take over the animation + event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true) + ? 'setClass' + : animationDetails.event; + + if (animationDetails.structural) { + closeParentClassBasedAnimations(parentElement); + } + + markElementAnimationState(element, RUNNING_STATE); + var realRunner = $$animation(element, event, animationDetails.options); + realRunner.done(function(status) { + close(!status); + var animationDetails = activeAnimationsLookup.get(node); + if (animationDetails && animationDetails.counter === counter) { + clearElementAnimationState(getDomNode(element)); + } + notifyProgress(runner, event, 'close', {}); + }); + + // this will update the runner's flow-control events based on + // the `realRunner` object. + runner.setHost(realRunner); + notifyProgress(runner, event, 'start', {}); + }); + + return runner; + + function notifyProgress(runner, event, phase, data) { + triggerCallback(event, element, phase, data); + runner.progress(event, phase, data); + } + + function close(reject) { // jshint ignore:line + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + runner.complete(!reject); + } + } + + function closeChildAnimations(element) { + var node = getDomNode(element); + var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); + forEach(children, function(child) { + var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME)); + var animationDetails = activeAnimationsLookup.get(child); + switch (state) { + case RUNNING_STATE: + animationDetails.runner.end(); + /* falls through */ + case PRE_DIGEST_STATE: + if (animationDetails) { + activeAnimationsLookup.remove(child); + } + break; + } + }); + } + + function clearElementAnimationState(element) { + var node = getDomNode(element); + node.removeAttribute(NG_ANIMATE_ATTR_NAME); + activeAnimationsLookup.remove(node); + } + + function isMatchingElement(nodeOrElmA, nodeOrElmB) { + return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); + } + + function closeParentClassBasedAnimations(startingElement) { + var parentNode = getDomNode(startingElement); + do { + if (!parentNode || parentNode.nodeType !== ELEMENT_NODE) break; + + var animationDetails = activeAnimationsLookup.get(parentNode); + if (animationDetails) { + examineParentAnimation(parentNode, animationDetails); + } + + parentNode = parentNode.parentNode; + } while (true); + + // since animations are detected from CSS classes, we need to flush all parent + // class-based animations so that the parent classes are all present for child + // animations to properly function (otherwise any CSS selectors may not work) + function examineParentAnimation(node, animationDetails) { + // enter/leave/move always have priority + if (animationDetails.structural || !hasAnimationClasses(animationDetails.options)) return; + + if (animationDetails.state === RUNNING_STATE) { + animationDetails.runner.end(); + } + clearElementAnimationState(node); + } + } + + function areAnimationsAllowed(element, parentElement, event) { + var bodyElementDetected = false; + var rootElementDetected = false; + var parentAnimationDetected = false; + var animateChildren; + + var parentHost = element.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } + + while (parentElement && parentElement.length) { + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + } + + var parentNode = parentElement[0]; + if (parentNode.nodeType !== ELEMENT_NODE) { + // no point in inspecting the #document element + break; + } + + var details = activeAnimationsLookup.get(parentNode) || {}; + // either an enter, leave or move animation will commence + // therefore we can't allow any animations to take place + // but if a parent animation is class-based then that's ok + if (!parentAnimationDetected) { + parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode); + } + + if (isUndefined(animateChildren) || animateChildren === true) { + var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA); + if (isDefined(value)) { + animateChildren = value; + } + } + + // there is no need to continue traversing at this point + if (parentAnimationDetected && animateChildren === false) break; + + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + if (!rootElementDetected) { + parentHost = parentElement.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } + } + } + + if (!bodyElementDetected) { + // we also need to ensure that the element is or will be apart of the body element + // otherwise it is pointless to even issue an animation to be rendered + bodyElementDetected = isMatchingElement(parentElement, bodyElement); + } + + parentElement = parentElement.parent(); + } + + var allowAnimation = !parentAnimationDetected || animateChildren; + return allowAnimation && rootElementDetected && bodyElementDetected; + } + + function markElementAnimationState(element, state, details) { + details = details || {}; + details.state = state; + + var node = getDomNode(element); + node.setAttribute(NG_ANIMATE_ATTR_NAME, state); + + var oldValue = activeAnimationsLookup.get(node); + var newValue = oldValue + ? extend(oldValue, details) + : details; + activeAnimationsLookup.put(node, newValue); + } + }]; +}]; + +var $$rAFMutexFactory = ['$$rAF', function($$rAF) { + return function() { + var passed = false; + $$rAF(function() { + passed = true; + }); + return function(fn) { + passed ? fn() : $$rAF(fn); + }; + }; +}]; + +var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + function AnimateRunner(host) { + this.setHost(host); + + this._doneCallbacks = []; + this._runInAnimationFrame = $$rAFMutex(); + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + return AnimateRunner; +}]; + +var $$AnimationProvider = ['$animateProvider', function($animateProvider) { + var NG_ANIMATE_REF_ATTR = 'ng-animate-ref'; + + var drivers = this.drivers = []; + + var RUNNER_STORAGE_KEY = '$$animationRunner'; + + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } + + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } + + this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$rAFScheduler', + function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$rAFScheduler) { + + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var totalPendingClassBasedAnimations = 0; + var totalActiveClassBasedAnimations = 0; + var classBasedAnimationsQueue = []; + + // TODO(matsko): document the signature in a better way + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // there is no animation at the current moment, however + // these runner methods will get later updated with the + // methods leading into the driver's end/cancel methods + // for now they just stop the animation from starting + var runner = new $$AnimateRunner({ + end: function() { close(); }, + cancel: function() { close(true); } + }); + + if (!drivers.length) { + close(); + return runner; + } + + setRunner(element, runner); + + var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += ' ' + tempClasses; + options.tempClasses = null; + } + + var classBasedIndex; + if (!isStructural) { + classBasedIndex = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations += 1; + } + + animationQueue.push({ + // this data is used by the postDigest code and passed into + // the driver step function + element: element, + classes: classes, + event: event, + classBasedIndex: classBasedIndex, + structural: isStructural, + options: options, + beforeStart: beforeStart, + close: close + }); + + element.on('$destroy', handleDestroyedElement); + + // we only want there to be one function called within the post digest + // block. This way we can group animations for all the animations that + // were apart of the same postDigest flush call. + if (animationQueue.length > 1) return runner; + + $rootScope.$$postDigest(function() { + totalActiveClassBasedAnimations = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations = 0; + classBasedAnimationsQueue.length = 0; + + var animations = []; + forEach(animationQueue, function(entry) { + // the element was destroyed early on which removed the runner + // form its storage. This means we can't animate this element + // at all and it already has been closed due to destruction. + if (getRunner(entry.element)) { + animations.push(entry); + } + }); + + // now any future animations will be in another postDigest + animationQueue.length = 0; + + forEach(groupAnimations(animations), function(animationEntry) { + if (animationEntry.structural) { + triggerAnimationStart(); + } else { + classBasedAnimationsQueue.push({ + node: getDomNode(animationEntry.element), + fn: triggerAnimationStart + }); + + if (animationEntry.classBasedIndex === totalActiveClassBasedAnimations - 1) { + // we need to sort each of the animations in order of parent to child + // relationships. This ensures that the child classes are applied at the + // right time. + classBasedAnimationsQueue = classBasedAnimationsQueue.sort(function(a,b) { + return b.node.contains(a.node); + }).map(function(entry) { + return entry.fn; + }); + + $$rAFScheduler(classBasedAnimationsQueue); + } + } + + function triggerAnimationStart() { + // it's important that we apply the `ng-animate` CSS class and the + // temporary classes before we do any driver invoking since these + // CSS classes may be required for proper CSS detection. + animationEntry.beforeStart(); + + var startAnimationFn, closeFn = animationEntry.close; + + // in the event that the element was removed before the digest runs or + // during the RAF sequencing then we should not trigger the animation. + var targetElement = animationEntry.anchors + ? (animationEntry.from.element || animationEntry.to.element) + : animationEntry.element; + + if (getRunner(targetElement) && getDomNode(targetElement).parentNode) { + var operation = invokeFirstDriver(animationEntry); + if (operation) { + startAnimationFn = operation.start; + } + } + + if (!startAnimationFn) { + closeFn(); + } else { + var animationRunner = startAnimationFn(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + } + }); + }); + + return runner; + + // TODO(matsko): change to reference nodes + function getAnchorNodes(node) { + var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']'; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) + ? [node] + : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = getDomNode(element); + var event = animation.event; + var enterOrMove = ['enter', 'move'].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + + if (anchorNodes.length) { + var direction = enterOrMove ? 'to' : 'from'; + + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); + + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + + if (!from || !to) { + // only one of these is set therefore we can't have an + // anchor animation since all three pieces are required + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } + + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + structural: true, + beforeStart: function() { + fromAnimation.beforeStart(); + toAnimation.beforeStart(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] // TODO(matsko): change to reference nodes + }; + + // the anchor animations require that the from and to elements both have at least + // one shared CSS class which effictively marries the two elements together to use + // the same animation driver and to properly sequence the anchor animation. + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } + + anchorGroups[lookupKey].anchors.push({ + 'out': from.element, 'in': to.element + }); + }); + + return preparedAnimations; + } + + function cssClassesIntersection(a,b) { + a = a.split(' '); + b = b.split(' '); + var matches = []; + + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0,3) === 'ng-') continue; + + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + + return matches.join(' '); + } + + function invokeFirstDriver(animationDetails) { + // we loop in reverse order since the more general drivers (like CSS and JS) + // may attempt more elements, but custom drivers are more particular + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check + + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } + } + + function beforeStart() { + element.addClass(NG_ANIMATE_CLASSNAME); + if (tempClasses) { + $$jqLite.addClass(element, tempClasses); + } + } + + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + + function update(element) { + getRunner(element).setHost(newRunner); + } + } + + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== 'leave' || !options.$$domOperationFired)) { + runner.end(); + } + } + + function close(rejected) { // jshint ignore:line + element.off('$destroy', handleDestroyedElement); + removeRunner(element); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + + element.removeClass(NG_ANIMATE_CLASSNAME); + runner.complete(!rejected); + } + }; + }]; +}]; + +/* global angularAnimateModule: true, + + $$rAFMutexFactory, + $$rAFSchedulerFactory, + $$AnimateChildrenDirective, + $$AnimateRunnerFactory, + $$AnimateQueueProvider, + $$AnimationProvider, + $AnimateCssProvider, + $$AnimateCssDriverProvider, + $$AnimateJsProvider, + $$AnimateJsDriverProvider, +*/ + +/** + * @ngdoc module + * @name ngAnimate + * @description + * + * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via + * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app. + * + *
+ * + * # Usage + * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based + * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For + * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within + * the HTML element that the animation will be triggered on. + * + * ## Directive Support + * The following directives are "animation aware": + * + * | Directive | Supported Animations | + * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| + * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | + * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | + * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | + * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | + * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | + * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | + * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | + * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | + * | {@link module:ngMessages#animations ngMessage} | enter and leave | + * + * (More information can be found by visiting each the documentation associated with each directive.) + * + * ## CSS-based Animations + * + * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML + * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation. + * + * The example below shows how an `enter` animation can be made possible on a element using `ng-if`: + * + * ```html + *
+ * Fade me in out + *
+ * + * + * ``` + * + * Notice the CSS class **fade**? We can now create the CSS transition code that references this class: + * + * ```css + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter { + * transition:0.5s linear all; + * opacity:0; + * } + * + * /* The finishing CSS styles for the enter animation */ + * .fade.ng-enter.ng-enter-active { + * opacity:1; + * } + * ``` + * + * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two + * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition + * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards. + * + * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions: + * + * ```css + * /* now the element will fade out before it is removed from the DOM */ + * .fade.ng-leave { + * transition:0.5s linear all; + * opacity:1; + * } + * .fade.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class: + * + * ```css + * /* there is no need to define anything inside of the destination + * CSS class since the keyframe will take charge of the animation */ + * .fade.ng-leave { + * animation: my_fade_animation 0.5s linear; + * -webkit-animation: my_fade_animation 0.5s linear; + * } + * + * @keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * + * @-webkit-keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * ``` + * + * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element. + * + * ### CSS Class-based Animations + * + * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different + * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added + * and removed. + * + * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class: + * + * ```html + *
+ * Show and hide me + *
+ * + * + * + * ``` + * + * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since + * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest. + * + * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation + * with CSS styles. + * + * ```html + *
+ * Highlight this box + *
+ * + * + * + * ``` + * + * We can also make use of CSS keyframes by placing them within the CSS classes. + * + * + * ### CSS Staggering Animations + * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a + * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be + * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for + * the animation. The style property expected within the stagger class can either be a **transition-delay** or an + * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). + * + * ```css + * .my-animation.ng-enter { + * /* standard transition code */ + * transition: 1s linear all; + * opacity:0; + * } + * .my-animation.ng-enter-stagger { + * /* this will have a 100ms delay between each successive leave animation */ + * transition-delay: 0.1s; + * + * /* in case the stagger doesn't work then the duration value + * must be set to 0 to avoid an accidental CSS inheritance */ + * transition-duration: 0s; + * } + * .my-animation.ng-enter.ng-enter-active { + * /* standard transition styles */ + * opacity:1; + * } + * ``` + * + * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations + * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this + * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation + * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired. + * + * The following code will issue the **ng-leave-stagger** event on the element provided: + * + * ```js + * var kids = parent.children(); + * + * $animate.leave(kids[0]); //stagger index=0 + * $animate.leave(kids[1]); //stagger index=1 + * $animate.leave(kids[2]); //stagger index=2 + * $animate.leave(kids[3]); //stagger index=3 + * $animate.leave(kids[4]); //stagger index=4 + * + * window.requestAnimationFrame(function() { + * //stagger has reset itself + * $animate.leave(kids[5]); //stagger index=0 + * $animate.leave(kids[6]); //stagger index=1 + * + * $scope.$digest(); + * }); + * ``` + * + * Stagger animations are currently only supported within CSS-defined animations. + * + * ### The `ng-animate` CSS class + * + * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation. + * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations). + * + * Therefore, animations can be applied to an element using this temporary class directly via CSS. + * + * ```css + * .zipper.ng-animate { + * transition:0.5s linear all; + * } + * .zipper.ng-enter { + * opacity:0; + * } + * .zipper.ng-enter.ng-enter-active { + * opacity:1; + * } + * .zipper.ng-leave { + * opacity:1; + * } + * .zipper.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove + * the CSS class once an animation has completed.) + * + * + * ## JavaScript-based Animations + * + * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared + * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the + * `module.animation()` module function we can register the ainmation. + * + * Let's see an example of a enter/leave animation using `ngRepeat`: + * + * ```html + *
+ * {{ item }} + *
+ * ``` + * + * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`: + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * // make note that other events (like addClass/removeClass) + * // have different function input parameters + * enter: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * + * // remember to call doneFn so that angular + * // knows that the animation has concluded + * }, + * + * move: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * }, + * + * leave: function(element, doneFn) { + * jQuery(element).fadeOut(1000, doneFn); + * } + * } + * }] + * ``` + * + * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as + * greensock.js and velocity.js. + * + * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define + * our animations inside of the same registered animation, however, the function input arguments are a bit different: + * + * ```html + *
+ * this box is moody + *
+ * + * + * + * ``` + * + * ```js + * myModule.animation('.colorful', [function() { + * return { + * addClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * removeClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * setClass: function(element, addedClass, removedClass, doneFn) { + * // do some cool animation and call the doneFn + * } + * } + * }] + * ``` + * + * ## CSS + JS Animations Together + * + * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular, + * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking + * charge of the animation**: + * + * ```html + *
+ * Slide in and out + *
+ * ``` + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * enter: function(element, doneFn) { + * jQuery(element).slideIn(1000, doneFn); + * } + * } + * }] + * ``` + * + * ```css + * .slide.ng-enter { + * transition:0.5s linear all; + * transform:translateY(-100px); + * } + * .slide.ng-enter.ng-enter-active { + * transform:translateY(0); + * } + * ``` + * + * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the + * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from + * our own JS-based animation code: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { +* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`. + * var runner = $animateCss(element, { + * event: 'enter', + * structural: true + * }).start(); +* runner.done(doneFn); + * } + * } + * }] + * ``` + * + * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework. + * + * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or + * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that + * data into `$animateCss` directly: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var runner = $animateCss(element, { + * event: 'enter', + * addClass: 'maroon-setting', + * from: { height:0 }, + * to: { height: 200 } + * }).start(); + * + * runner.done(doneFn); + * } + * } + * }] + * ``` + * + * Now we can fill in the rest via our transition CSS code: + * + * ```css + * /* the transition tells ngAnimate to make the animation happen */ + * .slide.ng-enter { transition:0.5s linear all; } + * + * /* this extra CSS class will be absorbed into the transition + * since the $animateCss code is adding the class */ + * .maroon-setting { background:red; } + * ``` + * + * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over. + * + * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}. + * + * ## Animation Anchoring (via `ng-animate-ref`) + * + * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between + * structural areas of an application (like views) by pairing up elements using an attribute + * called `ng-animate-ref`. + * + * Let's say for example we have two views that are managed by `ng-view` and we want to show + * that there is a relationship between two components situated in within these views. By using the + * `ng-animate-ref` attribute we can identify that the two components are paired together and we + * can then attach an animation, which is triggered when the view changes. + * + * Say for example we have the following template code: + * + * ```html + * + *
+ *
+ * + * + * + * + * + * + * + * + * ``` + * + * Now, when the view changes (once the link is clicked), ngAnimate will examine the + * HTML contents to see if there is a match reference between any components in the view + * that is leaving and the view that is entering. It will scan both the view which is being + * removed (leave) and inserted (enter) to see if there are any paired DOM elements that + * contain a matching ref value. + * + * The two images match since they share the same ref value. ngAnimate will now create a + * transport element (which is a clone of the first image element) and it will then attempt + * to animate to the position of the second image element in the next view. For the animation to + * work a special CSS class called `ng-anchor` will be added to the transported element. + * + * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then + * ngAnimate will handle the entire transition for us as well as the addition and removal of + * any changes of CSS classes between the elements: + * + * ```css + * .banner.ng-anchor { + * /* this animation will last for 1 second since there are + * two phases to the animation (an `in` and an `out` phase) */ + * transition:0.5s linear all; + * } + * ``` + * + * We also **must** include animations for the views that are being entered and removed + * (otherwise anchoring wouldn't be possible since the new view would be inserted right away). + * + * ```css + * .view-animation.ng-enter, .view-animation.ng-leave { + * transition:0.5s linear all; + * position:fixed; + * left:0; + * top:0; + * width:100%; + * } + * .view-animation.ng-enter { + * transform:translateX(100%); + * } + * .view-animation.ng-leave, + * .view-animation.ng-enter.ng-enter-active { + * transform:translateX(0%); + * } + * .view-animation.ng-leave.ng-leave-active { + * transform:translateX(-100%); + * } + * ``` + * + * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur: + * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away + * from its origin. Once that animation is over then the `in` stage occurs which animates the + * element to its destination. The reason why there are two animations is to give enough time + * for the enter animation on the new element to be ready. + * + * The example above sets up a transition for both the in and out phases, but we can also target the out or + * in phases directly via `ng-anchor-out` and `ng-anchor-in`. + * + * ```css + * .banner.ng-anchor-out { + * transition: 0.5s linear all; + * + * /* the scale will be applied during the out animation, + * but will be animated away when the in animation runs */ + * transform: scale(1.2); + * } + * + * .banner.ng-anchor-in { + * transition: 1s linear all; + * } + * ``` + * + * + * + * + * ### Anchoring Demo + * + + + Home +
+
+
+
+
+ + angular.module('anchoringExample', ['ngAnimate', 'ngRoute']) + .config(['$routeProvider', function($routeProvider) { + $routeProvider.when('/', { + templateUrl: 'home.html', + controller: 'HomeController as home' + }); + $routeProvider.when('/profile/:id', { + templateUrl: 'profile.html', + controller: 'ProfileController as profile' + }); + }]) + .run(['$rootScope', function($rootScope) { + $rootScope.records = [ + { id:1, title: "Miss Beulah Roob" }, + { id:2, title: "Trent Morissette" }, + { id:3, title: "Miss Ava Pouros" }, + { id:4, title: "Rod Pouros" }, + { id:5, title: "Abdul Rice" }, + { id:6, title: "Laurie Rutherford Sr." }, + { id:7, title: "Nakia McLaughlin" }, + { id:8, title: "Jordon Blanda DVM" }, + { id:9, title: "Rhoda Hand" }, + { id:10, title: "Alexandrea Sauer" } + ]; + }]) + .controller('HomeController', [function() { + //empty + }]) + .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) { + var index = parseInt($routeParams.id, 10); + var record = $rootScope.records[index - 1]; + + this.title = record.title; + this.id = record.id; + }]); + + +

Welcome to the home page

+

Please click on an element

+ + {{ record.title }} + +
+ +
+ {{ profile.title }} +
+
+ + .record { + display:block; + font-size:20px; + } + .profile { + background:black; + color:white; + font-size:100px; + } + .view-container { + position:relative; + } + .view-container > .view.ng-animate { + position:absolute; + top:0; + left:0; + width:100%; + min-height:500px; + } + .view.ng-enter, .view.ng-leave, + .record.ng-anchor { + transition:0.5s linear all; + } + .view.ng-enter { + transform:translateX(100%); + } + .view.ng-enter.ng-enter-active, .view.ng-leave { + transform:translateX(0%); + } + .view.ng-leave.ng-leave-active { + transform:translateX(-100%); + } + .record.ng-anchor-out { + background:red; + } + +
+ * + * ### How is the element transported? + * + * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting + * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element + * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The + * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match + * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied + * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class + * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element + * will become visible since the shim class will be removed. + * + * ### How is the morphing handled? + * + * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out + * what CSS classes differ between the starting element and the destination element. These different CSS classes + * will be added/removed on the anchor element and a transition will be applied (the transition that is provided + * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will + * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that + * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since + * the cloned element is placed inside of root element which is likely close to the body element). + * + * Note that if the root element is on the `` element then the cloned node will be placed inside of body. + * + * + * ## Using $animate in your directive code + * + * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application? + * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's + * imagine we have a greeting box that shows and hides itself when the data changes + * + * ```html + * Hi there + * ``` + * + * ```js + * ngModule.directive('greetingBox', ['$animate', function($animate) { + * return function(scope, element, attrs) { + * attrs.$observe('active', function(value) { + * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on'); + * }); + * }); + * }]); + * ``` + * + * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element + * in our HTML code then we can trigger a CSS or JS animation to happen. + * + * ```css + * /* normally we would create a CSS class to reference on the element */ + * greeting-box.on { transition:0.5s linear all; background:green; color:white; } + * ``` + * + * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's + * possible be sure to visit the {@link ng.$animate $animate service API page}. + * + * + * ### Preventing Collisions With Third Party Libraries + * + * Some third-party frameworks place animation duration defaults across many element or className + * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which + * is expecting actual animations on these elements and has to wait for their completion. + * + * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * + * ```css + * /* prefixed with animate- */ + * .animate-fade-add.animate-fade-add-active { + * transition:1s linear all; + * opacity:0; + * } + * ``` + * + * You then configure `$animate` to enforce this prefix: + * + * ```js + * $animateProvider.classNameFilter(/animate-/); + * ``` + * + * This also may provide your application with a speed boost since only specific elements containing CSS class prefix + * will be evaluated for animation when any DOM changes occur in the application. + * + * ## Callbacks and Promises + * + * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger + * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has + * ended by chaining onto the returned promise that animation method returns. + * + * ```js + * // somewhere within the depths of the directive + * $animate.enter(element, parent).then(function() { + * //the animation has completed + * }); + * ``` + * + * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case + * anymore.) + * + * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view + * routing controller to hook into that: + * + * ```js + * ngModule.controller('HomePageController', ['$animate', function($animate) { + * $animate.on('enter', ngViewElement, function(element) { + * // the animation for this route has completed + * }]); + * }]) + * ``` + * + * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.) + */ + +/** + * @ngdoc service + * @name $animate + * @kind object + * + * @description + * The ngAnimate `$animate` service documentation is the same for the core `$animate` service. + * + * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}. + */ +angular.module('ngAnimate', []) + .directive('ngAnimateChildren', $$AnimateChildrenDirective) + + .factory('$$rAFMutex', $$rAFMutexFactory) + .factory('$$rAFScheduler', $$rAFSchedulerFactory) + + .factory('$$AnimateRunner', $$AnimateRunnerFactory) + + .provider('$$animateQueue', $$AnimateQueueProvider) + .provider('$$animation', $$AnimationProvider) + + .provider('$animateCss', $AnimateCssProvider) + .provider('$$animateCssDriver', $$AnimateCssDriverProvider) + + .provider('$$animateJs', $$AnimateJsProvider) + .provider('$$animateJsDriver', $$AnimateJsDriverProvider); + + +})(window, window.angular); diff --git a/LiveChat/ClientComponents/angularjs/angular-resource.js b/LiveChat/ClientComponents/angularjs/angular-resource.js new file mode 100644 index 0000000..797f9ee --- /dev/null +++ b/LiveChat/ClientComponents/angularjs/angular-resource.js @@ -0,0 +1,669 @@ +/** + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +var $resourceMinErr = angular.$$minErr('$resource'); + +// Helper functions and regex to lookup a dotted path on an object +// stopping at undefined/null. The path must be composed of ASCII +// identifiers (just like $parse) +var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/; + +function isValidDottedPath(path) { + return (path != null && path !== '' && path !== 'hasOwnProperty' && + MEMBER_NAME_REGEX.test('.' + path)); +} + +function lookupDottedPath(obj, path) { + if (!isValidDottedPath(path)) { + throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path); + } + var keys = path.split('.'); + for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) { + var key = keys[i]; + obj = (obj !== null) ? obj[key] : undefined; + } + return obj; +} + +/** + * Create a shallow copy of an object and clear other fields from the destination + */ +function shallowClearAndCopy(src, dst) { + dst = dst || {}; + + angular.forEach(dst, function(value, key) { + delete dst[key]; + }); + + for (var key in src) { + if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + + return dst; +} + +/** + * @ngdoc module + * @name ngResource + * @description + * + * # ngResource + * + * The `ngResource` module provides interaction support with RESTful services + * via the $resource service. + * + * + *
+ * + * See {@link ngResource.$resource `$resource`} for usage. + */ + +/** + * @ngdoc service + * @name $resource + * @requires $http + * + * @description + * A factory which creates a resource object that lets you interact with + * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. + * + * The returned resource object has action methods which provide high-level behaviors without + * the need to interact with the low level {@link ng.$http $http} service. + * + * Requires the {@link ngResource `ngResource`} module to be installed. + * + * By default, trailing slashes will be stripped from the calculated URLs, + * which can pose problems with server backends that do not expect that + * behavior. This can be disabled by configuring the `$resourceProvider` like + * this: + * + * ```js + app.config(['$resourceProvider', function($resourceProvider) { + // Don't strip trailing slashes from calculated URLs + $resourceProvider.defaults.stripTrailingSlashes = false; + }]); + * ``` + * + * @param {string} url A parameterized URL template with parameters prefixed by `:` as in + * `/user/:username`. If you are using a URL with a port number (e.g. + * `http://example.com:8080/api`), it will be respected. + * + * If you are using a url with a suffix, just add the suffix, like this: + * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` + * or even `$resource('http://example.com/resource/:resource_id.:format')` + * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be + * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you + * can escape it with `/\.`. + * + * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in + * `actions` methods. If any of the parameter value is a function, it will be executed every time + * when a param value needs to be obtained for a request (unless the param was overridden). + * + * Each key value in the parameter object is first bound to url template if present and then any + * excess keys are appended to the url search query after the `?`. + * + * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in + * URL `/path/greet?salutation=Hello`. + * + * If the parameter value is prefixed with `@` then the value for that parameter will be extracted + * from the corresponding property on the `data` object (provided when calling an action method). For + * example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam` + * will be `data.someProp`. + * + * @param {Object.=} actions Hash with declaration of custom actions that should extend + * the default set of resource actions. The declaration should be created in the format of {@link + * ng.$http#usage $http.config}: + * + * {action1: {method:?, params:?, isArray:?, headers:?, ...}, + * action2: {method:?, params:?, isArray:?, headers:?, ...}, + * ...} + * + * Where: + * + * - **`action`** – {string} – The name of action. This name becomes the name of the method on + * your resource object. + * - **`method`** – {string} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`, + * `DELETE`, `JSONP`, etc). + * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of + * the parameter value is a function, it will be executed every time when a param value needs to + * be obtained for a request (unless the param was overridden). + * - **`url`** – {string} – action specific `url` override. The url templating is supported just + * like for the resource-level urls. + * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, + * see `returns` section. + * - **`transformRequest`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * By default, transformRequest will contain one function that checks if the request data is + * an object and serializes to using `angular.toJson`. To prevent this behavior, set + * `transformRequest` to an empty array: `transformRequest: []` + * - **`transformResponse`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body and headers and returns its transformed (typically deserialized) version. + * By default, transformResponse will contain one function that checks if the response looks like + * a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set + * `transformResponse` to an empty array: `transformResponse: []` + * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that + * should abort the request when resolved. + * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See + * [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5) + * for more information. + * - **`responseType`** - `{string}` - see + * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - + * `response` and `responseError`. Both `response` and `responseError` interceptors get called + * with `http response` object. See {@link ng.$http $http interceptors}. + * + * @param {Object} options Hash with custom settings that should extend the + * default `$resourceProvider` behavior. The only supported option is + * + * Where: + * + * - **`stripTrailingSlashes`** – {boolean} – If true then the trailing + * slashes from any calculated URL will be stripped. (Defaults to true.) + * + * @returns {Object} A resource "class" object with methods for the default set of resource actions + * optionally extended with custom `actions`. The default set contains these actions: + * ```js + * { 'get': {method:'GET'}, + * 'save': {method:'POST'}, + * 'query': {method:'GET', isArray:true}, + * 'remove': {method:'DELETE'}, + * 'delete': {method:'DELETE'} }; + * ``` + * + * Calling these methods invoke an {@link ng.$http} with the specified http method, + * destination and parameters. When the data is returned from the server then the object is an + * instance of the resource class. The actions `save`, `remove` and `delete` are available on it + * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, + * read, update, delete) on server-side data like this: + * ```js + * var User = $resource('/user/:userId', {userId:'@id'}); + * var user = User.get({userId:123}, function() { + * user.abc = true; + * user.$save(); + * }); + * ``` + * + * It is important to realize that invoking a $resource object method immediately returns an + * empty reference (object or array depending on `isArray`). Once the data is returned from the + * server the existing reference is populated with the actual data. This is a useful trick since + * usually the resource is assigned to a model which is then rendered by the view. Having an empty + * object results in no rendering, once the data arrives from the server then the object is + * populated with the data and the view automatically re-renders itself showing the new data. This + * means that in most cases one never has to write a callback function for the action methods. + * + * The action methods on the class object or instance object can be invoked with the following + * parameters: + * + * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` + * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` + * - non-GET instance actions: `instance.$action([parameters], [success], [error])` + * + * + * Success callback is called with (value, responseHeaders) arguments, where the value is + * the populated resource instance or collection object. The error callback is called + * with (httpResponse) argument. + * + * Class actions return empty instance (with additional properties below). + * Instance actions return promise of the action. + * + * The Resource instances and collection have these additional properties: + * + * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this + * instance or collection. + * + * On success, the promise is resolved with the same resource instance or collection object, + * updated with data from server. This makes it easy to use in + * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view + * rendering until the resource(s) are loaded. + * + * On failure, the promise is resolved with the {@link ng.$http http response} object, without + * the `resource` property. + * + * If an interceptor object was provided, the promise will instead be resolved with the value + * returned by the interceptor. + * + * - `$resolved`: `true` after first server interaction is completed (either with success or + * rejection), `false` before that. Knowing if the Resource has been resolved is useful in + * data-binding. + * + * @example + * + * # Credit card resource + * + * ```js + // Define CreditCard class + var CreditCard = $resource('/user/:userId/card/:cardId', + {userId:123, cardId:'@id'}, { + charge: {method:'POST', params:{charge:true}} + }); + + // We can retrieve a collection from the server + var cards = CreditCard.query(function() { + // GET: /user/123/card + // server returns: [ {id:456, number:'1234', name:'Smith'} ]; + + var card = cards[0]; + // each item is an instance of CreditCard + expect(card instanceof CreditCard).toEqual(true); + card.name = "J. Smith"; + // non GET methods are mapped onto the instances + card.$save(); + // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'} + // server returns: {id:456, number:'1234', name: 'J. Smith'}; + + // our custom method is mapped as well. + card.$charge({amount:9.99}); + // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'} + }); + + // we can create an instance as well + var newCard = new CreditCard({number:'0123'}); + newCard.name = "Mike Smith"; + newCard.$save(); + // POST: /user/123/card {number:'0123', name:'Mike Smith'} + // server returns: {id:789, number:'0123', name: 'Mike Smith'}; + expect(newCard.id).toEqual(789); + * ``` + * + * The object returned from this function execution is a resource "class" which has "static" method + * for each action in the definition. + * + * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and + * `headers`. + * When the data is returned from the server then the object is an instance of the resource type and + * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD + * operations (create, read, update, delete) on server-side data. + + ```js + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}, function(user) { + user.abc = true; + user.$save(); + }); + ``` + * + * It's worth noting that the success callback for `get`, `query` and other methods gets passed + * in the response that came from the server as well as $http header getter function, so one + * could rewrite the above example and get access to http headers as: + * + ```js + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}, function(u, getResponseHeaders){ + u.abc = true; + u.$save(function(u, putResponseHeaders) { + //u => saved user object + //putResponseHeaders => $http header getter + }); + }); + ``` + * + * You can also access the raw `$http` promise via the `$promise` property on the object returned + * + ``` + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}) + .$promise.then(function(user) { + $scope.user = user; + }); + ``` + + * # Creating a custom 'PUT' request + * In this example we create a custom method on our resource to make a PUT request + * ```js + * var app = angular.module('app', ['ngResource', 'ngRoute']); + * + * // Some APIs expect a PUT request in the format URL/object/ID + * // Here we are creating an 'update' method + * app.factory('Notes', ['$resource', function($resource) { + * return $resource('/notes/:id', null, + * { + * 'update': { method:'PUT' } + * }); + * }]); + * + * // In our controller we get the ID from the URL using ngRoute and $routeParams + * // We pass in $routeParams and our Notes factory along with $scope + * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes', + function($scope, $routeParams, Notes) { + * // First get a note object from the factory + * var note = Notes.get({ id:$routeParams.id }); + * $id = note.id; + * + * // Now call update passing in the ID first then the object you are updating + * Notes.update({ id:$id }, note); + * + * // This will PUT /notes/ID with the note object in the request payload + * }]); + * ``` + */ +angular.module('ngResource', ['ng']). + provider('$resource', function() { + var provider = this; + + this.defaults = { + // Strip slashes by default + stripTrailingSlashes: true, + + // Default actions configuration + actions: { + 'get': {method: 'GET'}, + 'save': {method: 'POST'}, + 'query': {method: 'GET', isArray: true}, + 'remove': {method: 'DELETE'}, + 'delete': {method: 'DELETE'} + } + }; + + this.$get = ['$http', '$q', function($http, $q) { + + var noop = angular.noop, + forEach = angular.forEach, + extend = angular.extend, + copy = angular.copy, + isFunction = angular.isFunction; + + /** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set + * (pchar) allowed in path segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); + } + + + /** + * This method is intended for encoding *key* or *value* parts of query component. We need a + * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); + } + + function Route(template, defaults) { + this.template = template; + this.defaults = extend({}, provider.defaults, defaults); + this.urlParams = {}; + } + + Route.prototype = { + setUrlParams: function(config, params, actionUrl) { + var self = this, + url = actionUrl || self.template, + val, + encodedVal; + + var urlParams = self.urlParams = {}; + forEach(url.split(/\W/), function(param) { + if (param === 'hasOwnProperty') { + throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); + } + if (!(new RegExp("^\\d+$").test(param)) && param && + (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { + urlParams[param] = true; + } + }); + url = url.replace(/\\:/g, ':'); + + params = params || {}; + forEach(self.urlParams, function(_, urlParam) { + val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; + if (angular.isDefined(val) && val !== null) { + encodedVal = encodeUriSegment(val); + url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) { + return encodedVal + p1; + }); + } else { + url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, + leadingSlashes, tail) { + if (tail.charAt(0) == '/') { + return tail; + } else { + return leadingSlashes + tail; + } + }); + } + }); + + // strip trailing slashes and set the url (unless this behavior is specifically disabled) + if (self.defaults.stripTrailingSlashes) { + url = url.replace(/\/+$/, '') || '/'; + } + + // then replace collapse `/.` if found in the last URL path segment before the query + // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` + url = url.replace(/\/\.(?=\w+($|\?))/, '.'); + // replace escaped `/\.` with `/.` + config.url = url.replace(/\/\\\./, '/.'); + + + // set params - delegate param encoding to $http + forEach(params, function(value, key) { + if (!self.urlParams[key]) { + config.params = config.params || {}; + config.params[key] = value; + } + }); + } + }; + + + function resourceFactory(url, paramDefaults, actions, options) { + var route = new Route(url, options); + + actions = extend({}, provider.defaults.actions, actions); + + function extractParams(data, actionParams) { + var ids = {}; + actionParams = extend({}, paramDefaults, actionParams); + forEach(actionParams, function(value, key) { + if (isFunction(value)) { value = value(); } + ids[key] = value && value.charAt && value.charAt(0) == '@' ? + lookupDottedPath(data, value.substr(1)) : value; + }); + return ids; + } + + function defaultResponseInterceptor(response) { + return response.resource; + } + + function Resource(value) { + shallowClearAndCopy(value || {}, this); + } + + Resource.prototype.toJSON = function() { + var data = extend({}, this); + delete data.$promise; + delete data.$resolved; + return data; + }; + + forEach(actions, function(action, name) { + var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); + + Resource[name] = function(a1, a2, a3, a4) { + var params = {}, data, success, error; + + /* jshint -W086 */ /* (purposefully fall through case statements) */ + switch (arguments.length) { + case 4: + error = a4; + success = a3; + //fallthrough + case 3: + case 2: + if (isFunction(a2)) { + if (isFunction(a1)) { + success = a1; + error = a2; + break; + } + + success = a2; + error = a3; + //fallthrough + } else { + params = a1; + data = a2; + success = a3; + break; + } + case 1: + if (isFunction(a1)) success = a1; + else if (hasBody) data = a1; + else params = a1; + break; + case 0: break; + default: + throw $resourceMinErr('badargs', + "Expected up to 4 arguments [params, data, success, error], got {0} arguments", + arguments.length); + } + /* jshint +W086 */ /* (purposefully fall through case statements) */ + + var isInstanceCall = this instanceof Resource; + var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); + var httpConfig = {}; + var responseInterceptor = action.interceptor && action.interceptor.response || + defaultResponseInterceptor; + var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || + undefined; + + forEach(action, function(value, key) { + if (key != 'params' && key != 'isArray' && key != 'interceptor') { + httpConfig[key] = copy(value); + } + }); + + if (hasBody) httpConfig.data = data; + route.setUrlParams(httpConfig, + extend({}, extractParams(data, action.params || {}), params), + action.url); + + var promise = $http(httpConfig).then(function(response) { + var data = response.data, + promise = value.$promise; + + if (data) { + // Need to convert action.isArray to boolean in case it is undefined + // jshint -W018 + if (angular.isArray(data) !== (!!action.isArray)) { + throw $resourceMinErr('badcfg', + 'Error in resource configuration for action `{0}`. Expected response to ' + + 'contain an {1} but got an {2} (Request: {3} {4})', name, action.isArray ? 'array' : 'object', + angular.isArray(data) ? 'array' : 'object', httpConfig.method, httpConfig.url); + } + // jshint +W018 + if (action.isArray) { + value.length = 0; + forEach(data, function(item) { + if (typeof item === "object") { + value.push(new Resource(item)); + } else { + // Valid JSON values may be string literals, and these should not be converted + // into objects. These items will not have access to the Resource prototype + // methods, but unfortunately there + value.push(item); + } + }); + } else { + shallowClearAndCopy(data, value); + value.$promise = promise; + } + } + + value.$resolved = true; + + response.resource = value; + + return response; + }, function(response) { + value.$resolved = true; + + (error || noop)(response); + + return $q.reject(response); + }); + + promise = promise.then( + function(response) { + var value = responseInterceptor(response); + (success || noop)(value, response.headers); + return value; + }, + responseErrorInterceptor); + + if (!isInstanceCall) { + // we are creating instance / collection + // - set the initial promise + // - return the instance / collection + value.$promise = promise; + value.$resolved = false; + + return value; + } + + // instance call + return promise; + }; + + + Resource.prototype['$' + name] = function(params, success, error) { + if (isFunction(params)) { + error = success; success = params; params = {}; + } + var result = Resource[name].call(this, params, this, success, error); + return result.$promise || result; + }; + }); + + Resource.bind = function(additionalParamDefaults) { + return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); + }; + + return Resource; + } + + return resourceFactory; + }]; + }); + + +})(window, window.angular); diff --git a/LiveChat/ClientComponents/angularjs/angular-route.js b/LiveChat/ClientComponents/angularjs/angular-route.js new file mode 100644 index 0000000..40536ad --- /dev/null +++ b/LiveChat/ClientComponents/angularjs/angular-route.js @@ -0,0 +1,992 @@ +/** + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/** + * @ngdoc module + * @name ngRoute + * @description + * + * # ngRoute + * + * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * + *
+ */ + /* global -ngRouteModule */ +var ngRouteModule = angular.module('ngRoute', ['ng']). + provider('$route', $RouteProvider), + $routeMinErr = angular.$$minErr('ngRoute'); + +/** + * @ngdoc provider + * @name $routeProvider + * + * @description + * + * Used for configuring routes. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * ## Dependencies + * Requires the {@link ngRoute `ngRoute`} module to be installed. + */ +function $RouteProvider() { + function inherit(parent, extra) { + return angular.extend(Object.create(parent), extra); + } + + var routes = {}; + + /** + * @ngdoc method + * @name $routeProvider#when + * + * @param {string} path Route path (matched against `$location.path`). If `$location.path` + * contains redundant trailing slash or is missing one, the route will still match and the + * `$location.path` will be updated to add or drop the trailing slash to exactly match the + * route definition. + * + * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up + * to the next slash are matched and stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain named groups starting with a colon and ending with a star: + * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain optional named groups with a question mark: e.g.`:name?`. + * + * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match + * `/color/brown/largecode/code/with/slashes/edit` and extract: + * + * * `color: brown` + * * `largecode: code/with/slashes`. + * + * + * @param {Object} route Mapping information to be assigned to `$route.current` on route + * match. + * + * Object properties: + * + * - `controller` – `{(string|function()=}` – Controller fn that should be associated with + * newly created scope or the name of a {@link angular.Module#controller registered + * controller} if passed as a string. + * - `controllerAs` – `{string=}` – An identifier name for a reference to the controller. + * If present, the controller will be published to scope under the `controllerAs` name. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used by {@link + * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. + * This property takes precedence over `templateUrl`. + * + * If `template` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used by {@link ngRoute.directive:ngView ngView}. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `resolve` - `{Object.=}` - An optional map of dependencies which should + * be injected into the controller. If any of these dependencies are promises, the router + * will wait for them all to be resolved or one to be rejected before the controller is + * instantiated. + * If all the promises are resolved successfully, the values of the resolved promises are + * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is + * fired. If any of the promises are rejected the + * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object + * is: + * + * - `key` – `{string}`: a name of a dependency to be injected into the controller. + * - `factory` - `{string|function}`: If `string` then it is an alias for a service. + * Otherwise if function, then it is {@link auto.$injector#invoke injected} + * and the return value is treated as the dependency. If the result is a promise, it is + * resolved before its value is injected into the controller. Be aware that + * `ngRoute.$routeParams` will still refer to the previous route within these resolve + * functions. Use `$route.current.params` to access the new route parameters, instead. + * + * - `redirectTo` – {(string|function())=} – value to update + * {@link ng.$location $location} path with and trigger route redirection. + * + * If `redirectTo` is a function, it will be called with the following parameters: + * + * - `{Object.}` - route parameters extracted from the current + * `$location.path()` by applying the current route templateUrl. + * - `{string}` - current `$location.path()` + * - `{Object}` - current `$location.search()` + * + * The custom `redirectTo` function is expected to return a string which will be used + * to update `$location.path()` and `$location.search()`. + * + * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` + * or `$location.hash()` changes. + * + * If the option is set to `false` and url in the browser changes, then + * `$routeUpdate` event is broadcasted on the root scope. + * + * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive + * + * If the option is set to `true`, then the particular route can be matched without being + * case sensitive + * + * @returns {Object} self + * + * @description + * Adds a new route definition to the `$route` service. + */ + this.when = function(path, route) { + //copy original route object to preserve params inherited from proto chain + var routeCopy = angular.copy(route); + if (angular.isUndefined(routeCopy.reloadOnSearch)) { + routeCopy.reloadOnSearch = true; + } + if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) { + routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch; + } + routes[path] = angular.extend( + routeCopy, + path && pathRegExp(path, routeCopy) + ); + + // create redirection for trailing slashes + if (path) { + var redirectPath = (path[path.length - 1] == '/') + ? path.substr(0, path.length - 1) + : path + '/'; + + routes[redirectPath] = angular.extend( + {redirectTo: path}, + pathRegExp(redirectPath, routeCopy) + ); + } + + return this; + }; + + /** + * @ngdoc property + * @name $routeProvider#caseInsensitiveMatch + * @description + * + * A boolean property indicating if routes defined + * using this provider should be matched using a case insensitive + * algorithm. Defaults to `false`. + */ + this.caseInsensitiveMatch = false; + + /** + * @param path {string} path + * @param opts {Object} options + * @return {?Object} + * + * @description + * Normalizes the given path, returning a regular expression + * and the original path. + * + * Inspired by pathRexp in visionmedia/express/lib/utils.js. + */ + function pathRegExp(path, opts) { + var insensitive = opts.caseInsensitiveMatch, + ret = { + originalPath: path, + regexp: path + }, + keys = ret.keys = []; + + path = path + .replace(/([().])/g, '\\$1') + .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) { + var optional = option === '?' ? option : null; + var star = option === '*' ? option : null; + keys.push({ name: key, optional: !!optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + + (optional || ''); + }) + .replace(/([\/$\*])/g, '\\$1'); + + ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); + return ret; + } + + /** + * @ngdoc method + * @name $routeProvider#otherwise + * + * @description + * Sets route definition that will be used on route change when no other route definition + * is matched. + * + * @param {Object|string} params Mapping information to be assigned to `$route.current`. + * If called with a string, the value maps to `redirectTo`. + * @returns {Object} self + */ + this.otherwise = function(params) { + if (typeof params === 'string') { + params = {redirectTo: params}; + } + this.when(null, params); + return this; + }; + + + this.$get = ['$rootScope', + '$location', + '$routeParams', + '$q', + '$injector', + '$templateRequest', + '$sce', + function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) { + + /** + * @ngdoc service + * @name $route + * @requires $location + * @requires $routeParams + * + * @property {Object} current Reference to the current route definition. + * The route definition contains: + * + * - `controller`: The controller constructor as define in route definition. + * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for + * controller instantiation. The `locals` contain + * the resolved values of the `resolve` map. Additionally the `locals` also contain: + * + * - `$scope` - The current route scope. + * - `$template` - The current route template HTML. + * + * @property {Object} routes Object with all route configuration Objects as its properties. + * + * @description + * `$route` is used for deep-linking URLs to controllers and views (HTML partials). + * It watches `$location.url()` and tries to map the path to an existing route definition. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. + * + * The `$route` service is typically used in conjunction with the + * {@link ngRoute.directive:ngView `ngView`} directive and the + * {@link ngRoute.$routeParams `$routeParams`} service. + * + * @example + * This example shows how changing the URL hash causes the `$route` to match a route against the + * URL, and the `ngView` pulls in the partial. + * + * + * + *
+ * Choose: + * Moby | + * Moby: Ch1 | + * Gatsby | + * Gatsby: Ch4 | + * Scarlet Letter
+ * + *
+ * + *
+ * + *
$location.path() = {{$location.path()}}
+ *
$route.current.templateUrl = {{$route.current.templateUrl}}
+ *
$route.current.params = {{$route.current.params}}
+ *
$route.current.scope.name = {{$route.current.scope.name}}
+ *
$routeParams = {{$routeParams}}
+ *
+ *
+ * + * + * controller: {{name}}
+ * Book Id: {{params.bookId}}
+ *
+ * + * + * controller: {{name}}
+ * Book Id: {{params.bookId}}
+ * Chapter Id: {{params.chapterId}} + *
+ * + * + * angular.module('ngRouteExample', ['ngRoute']) + * + * .controller('MainController', function($scope, $route, $routeParams, $location) { + * $scope.$route = $route; + * $scope.$location = $location; + * $scope.$routeParams = $routeParams; + * }) + * + * .controller('BookController', function($scope, $routeParams) { + * $scope.name = "BookController"; + * $scope.params = $routeParams; + * }) + * + * .controller('ChapterController', function($scope, $routeParams) { + * $scope.name = "ChapterController"; + * $scope.params = $routeParams; + * }) + * + * .config(function($routeProvider, $locationProvider) { + * $routeProvider + * .when('/Book/:bookId', { + * templateUrl: 'book.html', + * controller: 'BookController', + * resolve: { + * // I will cause a 1 second delay + * delay: function($q, $timeout) { + * var delay = $q.defer(); + * $timeout(delay.resolve, 1000); + * return delay.promise; + * } + * } + * }) + * .when('/Book/:bookId/ch/:chapterId', { + * templateUrl: 'chapter.html', + * controller: 'ChapterController' + * }); + * + * // configure html5 to get links working on jsfiddle + * $locationProvider.html5Mode(true); + * }); + * + * + * + * + * it('should load and compile correct template', function() { + * element(by.linkText('Moby: Ch1')).click(); + * var content = element(by.css('[ng-view]')).getText(); + * expect(content).toMatch(/controller\: ChapterController/); + * expect(content).toMatch(/Book Id\: Moby/); + * expect(content).toMatch(/Chapter Id\: 1/); + * + * element(by.partialLinkText('Scarlet')).click(); + * + * content = element(by.css('[ng-view]')).getText(); + * expect(content).toMatch(/controller\: BookController/); + * expect(content).toMatch(/Book Id\: Scarlet/); + * }); + * + *
+ */ + + /** + * @ngdoc event + * @name $route#$routeChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a route change. At this point the route services starts + * resolving all of the dependencies needed for the route change to occur. + * Typically this involves fetching the view template as well as any dependencies + * defined in `resolve` route property. Once all of the dependencies are resolved + * `$routeChangeSuccess` is fired. + * + * The route change (and the `$location` change that triggered it) can be prevented + * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} + * for more details about event object. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} next Future route information. + * @param {Route} current Current route information. + */ + + /** + * @ngdoc event + * @name $route#$routeChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a route change has happened successfully. + * The `resolve` dependencies are now available in the `current.locals` property. + * + * {@link ngRoute.directive:ngView ngView} listens for the directive + * to instantiate the controller and render the view. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} current Current route information. + * @param {Route|Undefined} previous Previous route information, or undefined if current is + * first route entered. + */ + + /** + * @ngdoc event + * @name $route#$routeChangeError + * @eventType broadcast on root scope + * @description + * Broadcasted if any of the resolve promises are rejected. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current route information. + * @param {Route} previous Previous route information. + * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. + */ + + /** + * @ngdoc event + * @name $route#$routeUpdate + * @eventType broadcast on root scope + * @description + * The `reloadOnSearch` property has been set to false, and we are reusing the same + * instance of the Controller. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current/previous route information. + */ + + var forceReload = false, + preparedRoute, + preparedRouteIsUpdateOnly, + $route = { + routes: routes, + + /** + * @ngdoc method + * @name $route#reload + * + * @description + * Causes `$route` service to reload the current route even if + * {@link ng.$location $location} hasn't changed. + * + * As a result of that, {@link ngRoute.directive:ngView ngView} + * creates new scope and reinstantiates the controller. + */ + reload: function() { + forceReload = true; + $rootScope.$evalAsync(function() { + // Don't support cancellation of a reload for now... + prepareRoute(); + commitRoute(); + }); + }, + + /** + * @ngdoc method + * @name $route#updateParams + * + * @description + * Causes `$route` service to update the current URL, replacing + * current route parameters with those specified in `newParams`. + * Provided property names that match the route's path segment + * definitions will be interpolated into the location's path, while + * remaining properties will be treated as query params. + * + * @param {!Object} newParams mapping of URL parameter names to values + */ + updateParams: function(newParams) { + if (this.current && this.current.$$route) { + newParams = angular.extend({}, this.current.params, newParams); + $location.path(interpolate(this.current.$$route.originalPath, newParams)); + // interpolate modifies newParams, only query params are left + $location.search(newParams); + } else { + throw $routeMinErr('norout', 'Tried updating route when with no current route'); + } + } + }; + + $rootScope.$on('$locationChangeStart', prepareRoute); + $rootScope.$on('$locationChangeSuccess', commitRoute); + + return $route; + + ///////////////////////////////////////////////////// + + /** + * @param on {string} current url + * @param route {Object} route regexp to match the url against + * @return {?Object} + * + * @description + * Check if the route matches the current url. + * + * Inspired by match in + * visionmedia/express/lib/router/router.js. + */ + function switchRouteMatcher(on, route) { + var keys = route.keys, + params = {}; + + if (!route.regexp) return null; + + var m = route.regexp.exec(on); + if (!m) return null; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = m[i]; + + if (key && val) { + params[key.name] = val; + } + } + return params; + } + + function prepareRoute($locationEvent) { + var lastRoute = $route.current; + + preparedRoute = parseRoute(); + preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route + && angular.equals(preparedRoute.pathParams, lastRoute.pathParams) + && !preparedRoute.reloadOnSearch && !forceReload; + + if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) { + if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) { + if ($locationEvent) { + $locationEvent.preventDefault(); + } + } + } + } + + function commitRoute() { + var lastRoute = $route.current; + var nextRoute = preparedRoute; + + if (preparedRouteIsUpdateOnly) { + lastRoute.params = nextRoute.params; + angular.copy(lastRoute.params, $routeParams); + $rootScope.$broadcast('$routeUpdate', lastRoute); + } else if (nextRoute || lastRoute) { + forceReload = false; + $route.current = nextRoute; + if (nextRoute) { + if (nextRoute.redirectTo) { + if (angular.isString(nextRoute.redirectTo)) { + $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params) + .replace(); + } else { + $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search())) + .replace(); + } + } + } + + $q.when(nextRoute). + then(function() { + if (nextRoute) { + var locals = angular.extend({}, nextRoute.resolve), + template, templateUrl; + + angular.forEach(locals, function(value, key) { + locals[key] = angular.isString(value) ? + $injector.get(value) : $injector.invoke(value, null, null, key); + }); + + if (angular.isDefined(template = nextRoute.template)) { + if (angular.isFunction(template)) { + template = template(nextRoute.params); + } + } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) { + if (angular.isFunction(templateUrl)) { + templateUrl = templateUrl(nextRoute.params); + } + if (angular.isDefined(templateUrl)) { + nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl); + template = $templateRequest(templateUrl); + } + } + if (angular.isDefined(template)) { + locals['$template'] = template; + } + return $q.all(locals); + } + }). + then(function(locals) { + // after route change + if (nextRoute == $route.current) { + if (nextRoute) { + nextRoute.locals = locals; + angular.copy(nextRoute.params, $routeParams); + } + $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute); + } + }, function(error) { + if (nextRoute == $route.current) { + $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error); + } + }); + } + } + + + /** + * @returns {Object} the current active route, by matching it against the URL + */ + function parseRoute() { + // Match a route + var params, match; + angular.forEach(routes, function(route, path) { + if (!match && (params = switchRouteMatcher($location.path(), route))) { + match = inherit(route, { + params: angular.extend({}, $location.search(), params), + pathParams: params}); + match.$$route = route; + } + }); + // No route matched; fallback to "otherwise" route + return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); + } + + /** + * @returns {string} interpolation of the redirect path with the parameters + */ + function interpolate(string, params) { + var result = []; + angular.forEach((string || '').split(':'), function(segment, i) { + if (i === 0) { + result.push(segment); + } else { + var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/); + var key = segmentMatch[1]; + result.push(params[key]); + result.push(segmentMatch[2] || ''); + delete params[key]; + } + }); + return result.join(''); + } + }]; +} + +ngRouteModule.provider('$routeParams', $RouteParamsProvider); + + +/** + * @ngdoc service + * @name $routeParams + * @requires $route + * + * @description + * The `$routeParams` service allows you to retrieve the current set of route parameters. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * The route parameters are a combination of {@link ng.$location `$location`}'s + * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}. + * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. + * + * In case of parameter name collision, `path` params take precedence over `search` params. + * + * The service guarantees that the identity of the `$routeParams` object will remain unchanged + * (but its properties will likely change) even when a route change occurs. + * + * Note that the `$routeParams` are only updated *after* a route change completes successfully. + * This means that you cannot rely on `$routeParams` being correct in route resolve functions. + * Instead you can use `$route.current.params` to access the new route's parameters. + * + * @example + * ```js + * // Given: + * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby + * // Route: /Chapter/:chapterId/Section/:sectionId + * // + * // Then + * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'} + * ``` + */ +function $RouteParamsProvider() { + this.$get = function() { return {}; }; +} + +ngRouteModule.directive('ngView', ngViewFactory); +ngRouteModule.directive('ngView', ngViewFillContentFactory); + + +/** + * @ngdoc directive + * @name ngView + * @restrict ECA + * + * @description + * # Overview + * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by + * including the rendered template of the current route into the main layout (`index.html`) file. + * Every time the current route changes, the included view changes with it according to the + * configuration of the `$route` service. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * @animations + * enter - animation is used to bring new content into the browser. + * leave - animation is used to animate existing content away. + * + * The enter and leave animation occur concurrently. + * + * @scope + * @priority 400 + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll + * $anchorScroll} to scroll the viewport after the view is updated. + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated + * as an expression yields a truthy value. + * @example + + +
+ Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
+ +
+
+
+
+ +
$location.path() = {{main.$location.path()}}
+
$route.current.templateUrl = {{main.$route.current.templateUrl}}
+
$route.current.params = {{main.$route.current.params}}
+
$routeParams = {{main.$routeParams}}
+
+
+ + +
+ controller: {{book.name}}
+ Book Id: {{book.params.bookId}}
+
+
+ + +
+ controller: {{chapter.name}}
+ Book Id: {{chapter.params.bookId}}
+ Chapter Id: {{chapter.params.chapterId}} +
+
+ + + .view-animate-container { + position:relative; + height:100px!important; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .view-animate { + padding:10px; + } + + .view-animate.ng-enter, .view-animate.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + + display:block; + width:100%; + border-left:1px solid black; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + padding:10px; + } + + .view-animate.ng-enter { + left:100%; + } + .view-animate.ng-enter.ng-enter-active { + left:0; + } + .view-animate.ng-leave.ng-leave-active { + left:-100%; + } + + + + angular.module('ngViewExample', ['ngRoute', 'ngAnimate']) + .config(['$routeProvider', '$locationProvider', + function($routeProvider, $locationProvider) { + $routeProvider + .when('/Book/:bookId', { + templateUrl: 'book.html', + controller: 'BookCtrl', + controllerAs: 'book' + }) + .when('/Book/:bookId/ch/:chapterId', { + templateUrl: 'chapter.html', + controller: 'ChapterCtrl', + controllerAs: 'chapter' + }); + + $locationProvider.html5Mode(true); + }]) + .controller('MainCtrl', ['$route', '$routeParams', '$location', + function($route, $routeParams, $location) { + this.$route = $route; + this.$location = $location; + this.$routeParams = $routeParams; + }]) + .controller('BookCtrl', ['$routeParams', function($routeParams) { + this.name = "BookCtrl"; + this.params = $routeParams; + }]) + .controller('ChapterCtrl', ['$routeParams', function($routeParams) { + this.name = "ChapterCtrl"; + this.params = $routeParams; + }]); + + + + + it('should load and compile correct template', function() { + element(by.linkText('Moby: Ch1')).click(); + var content = element(by.css('[ng-view]')).getText(); + expect(content).toMatch(/controller\: ChapterCtrl/); + expect(content).toMatch(/Book Id\: Moby/); + expect(content).toMatch(/Chapter Id\: 1/); + + element(by.partialLinkText('Scarlet')).click(); + + content = element(by.css('[ng-view]')).getText(); + expect(content).toMatch(/controller\: BookCtrl/); + expect(content).toMatch(/Book Id\: Scarlet/); + }); + +
+ */ + + +/** + * @ngdoc event + * @name ngView#$viewContentLoaded + * @eventType emit on the current ngView scope + * @description + * Emitted every time the ngView content is reloaded. + */ +ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate']; +function ngViewFactory($route, $anchorScroll, $animate) { + return { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + link: function(scope, $element, attr, ctrl, $transclude) { + var currentScope, + currentElement, + previousLeaveAnimation, + autoScrollExp = attr.autoscroll, + onloadExp = attr.onload || ''; + + scope.$on('$routeChangeSuccess', update); + update(); + + function cleanupLastView() { + if (previousLeaveAnimation) { + $animate.cancel(previousLeaveAnimation); + previousLeaveAnimation = null; + } + + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + previousLeaveAnimation = $animate.leave(currentElement); + previousLeaveAnimation.then(function() { + previousLeaveAnimation = null; + }); + currentElement = null; + } + } + + function update() { + var locals = $route.current && $route.current.locals, + template = locals && locals.$template; + + if (angular.isDefined(template)) { + var newScope = scope.$new(); + var current = $route.current; + + // Note: This will also link all children of ng-view that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-view on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, function(clone) { + $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() { + if (angular.isDefined(autoScrollExp) + && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }); + cleanupLastView(); + }); + + currentElement = clone; + currentScope = current.scope = newScope; + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } else { + cleanupLastView(); + } + } + } + }; +} + +// This directive is called during the $transclude call of the first `ngView` directive. +// It will replace and compile the content of the element with the loaded template. +// We need this directive so that the element content is already filled when +// the link function of another directive on the same element as ngView +// is called. +ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route']; +function ngViewFillContentFactory($compile, $controller, $route) { + return { + restrict: 'ECA', + priority: -400, + link: function(scope, $element) { + var current = $route.current, + locals = current.locals; + + $element.html(locals.$template); + + var link = $compile($element.contents()); + + if (current.controller) { + locals.$scope = scope; + var controller = $controller(current.controller, locals); + if (current.controllerAs) { + scope[current.controllerAs] = controller; + } + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } + + link(scope); + } + }; +} + + +})(window, window.angular); diff --git a/LiveChat/ClientComponents/angularjs/angular-sanitize.js b/LiveChat/ClientComponents/angularjs/angular-sanitize.js new file mode 100644 index 0000000..bebe1a7 --- /dev/null +++ b/LiveChat/ClientComponents/angularjs/angular-sanitize.js @@ -0,0 +1,683 @@ +/** + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $sanitizeMinErr = angular.$$minErr('$sanitize'); + +/** + * @ngdoc module + * @name ngSanitize + * @description + * + * # ngSanitize + * + * The `ngSanitize` module provides functionality to sanitize HTML. + * + * + *
+ * + * See {@link ngSanitize.$sanitize `$sanitize`} for usage. + */ + +/* + * HTML Parser By Misko Hevery (misko@hevery.com) + * based on: HTML Parser By John Resig (ejohn.org) + * Original code by Erik Arvidsson, Mozilla Public License + * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js + * + * // Use like so: + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + */ + + +/** + * @ngdoc service + * @name $sanitize + * @kind function + * + * @description + * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are + * then serialized back to properly escaped html string. This means that no unsafe input can make + * it into the returned string, however, since our parser is more strict than a typical browser + * parser, it's possible that some obscure input, which would be recognized as valid HTML by a + * browser, won't make it through the sanitizer. The input may also contain SVG markup. + * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and + * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. + * + * @param {string} html HTML input. + * @returns {string} Sanitized HTML. + * + * @example + + + +
+ Snippet: + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value +
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
+</div>
+
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
+
+
+ + it('should sanitize the html snippet by default', function() { + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('

an html\nclick here\nsnippet

'); + }); + + it('should inline raw snippet if bound to a trusted value', function() { + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). + toBe("

an html\n" + + "click here\n" + + "snippet

"); + }); + + it('should escape snippet without any filter', function() { + expect(element(by.css('#bind-default div')).getInnerHtml()). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new text'); + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('new text'); + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( + 'new text'); + expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( + "new <b onclick=\"alert(1)\">text</b>"); + }); +
+
+ */ +function $SanitizeProvider() { + this.$get = ['$$sanitizeUri', function($$sanitizeUri) { + return function(html) { + var buf = []; + htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { + return !/^unsafe/.test($$sanitizeUri(uri, isImage)); + })); + return buf.join(''); + }; + }]; +} + +function sanitizeText(chars) { + var buf = []; + var writer = htmlSanitizeWriter(buf, angular.noop); + writer.chars(chars); + return buf.join(''); +} + + +// Regular Expressions for parsing tags and attributes +var START_TAG_REGEXP = + /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/, + END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/, + ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, + BEGIN_TAG_REGEXP = /^/g, + DOCTYPE_REGEXP = /]*?)>/i, + CDATA_REGEXP = //g, + SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + // Match everything outside of normal chars and " (quote character) + NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + + +// Good source of info about elements and attributes +// http://dev.w3.org/html5/spec/Overview.html#semantics +// http://simon.html5.org/html-elements + +// Safe Void Elements - HTML5 +// http://dev.w3.org/html5/spec/Overview.html#void-elements +var voidElements = makeMap("area,br,col,hr,img,wbr"); + +// Elements that you can, intentionally, leave open (and which close themselves) +// http://dev.w3.org/html5/spec/Overview.html#optional-tags +var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), + optionalEndTagInlineElements = makeMap("rp,rt"), + optionalEndTagElements = angular.extend({}, + optionalEndTagInlineElements, + optionalEndTagBlockElements); + +// Safe Block Elements - HTML5 +var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); + +// Inline Elements - HTML5 +var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); + +// SVG Elements +// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements +// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted. +// They can potentially allow for arbitrary javascript to be executed. See #11290 +var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," + + "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," + + "radialGradient,rect,stop,svg,switch,text,title,tspan,use"); + +// Special Elements (can contain anything) +var specialElements = makeMap("script,style"); + +var validElements = angular.extend({}, + voidElements, + blockElements, + inlineElements, + optionalEndTagElements, + svgElements); + +//Attributes that have href and hence need to be sanitized +var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href"); + +var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + + 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' + + 'valign,value,vspace,width'); + +// SVG attributes (without "id" and "name" attributes) +// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes +var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + + 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + + 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + + 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + + 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + + 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + + 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + + 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + + 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + + 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + + 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + + 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true); + +var validAttrs = angular.extend({}, + uriAttrs, + svgAttrs, + htmlAttrs); + +function makeMap(str, lowercaseKeys) { + var obj = {}, items = str.split(','), i; + for (i = 0; i < items.length; i++) { + obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true; + } + return obj; +} + + +/** + * @example + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + * @param {string} html string + * @param {object} handler + */ +function htmlParser(html, handler) { + if (typeof html !== 'string') { + if (html === null || typeof html === 'undefined') { + html = ''; + } else { + html = '' + html; + } + } + var index, chars, match, stack = [], last = html, text; + stack.last = function() { return stack[stack.length - 1]; }; + + while (html) { + text = ''; + chars = true; + + // Make sure we're not in a script or style element + if (!stack.last() || !specialElements[stack.last()]) { + + // Comment + if (html.indexOf("", index) === index) { + if (handler.comment) handler.comment(html.substring(4, index)); + html = html.substring(index + 3); + chars = false; + } + // DOCTYPE + } else if (DOCTYPE_REGEXP.test(html)) { + match = html.match(DOCTYPE_REGEXP); + + if (match) { + html = html.replace(match[0], ''); + chars = false; + } + // end tag + } else if (BEGING_END_TAGE_REGEXP.test(html)) { + match = html.match(END_TAG_REGEXP); + + if (match) { + html = html.substring(match[0].length); + match[0].replace(END_TAG_REGEXP, parseEndTag); + chars = false; + } + + // start tag + } else if (BEGIN_TAG_REGEXP.test(html)) { + match = html.match(START_TAG_REGEXP); + + if (match) { + // We only have a valid start-tag if there is a '>'. + if (match[4]) { + html = html.substring(match[0].length); + match[0].replace(START_TAG_REGEXP, parseStartTag); + } + chars = false; + } else { + // no ending tag found --- this piece should be encoded as an entity. + text += '<'; + html = html.substring(1); + } + } + + if (chars) { + index = html.indexOf("<"); + + text += index < 0 ? html : html.substring(0, index); + html = index < 0 ? "" : html.substring(index); + + if (handler.chars) handler.chars(decodeEntities(text)); + } + + } else { + // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w]. + html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), + function(all, text) { + text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); + + if (handler.chars) handler.chars(decodeEntities(text)); + + return ""; + }); + + parseEndTag("", stack.last()); + } + + if (html == last) { + throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + + "of html: {0}", html); + } + last = html; + } + + // Clean up any remaining tags + parseEndTag(); + + function parseStartTag(tag, tagName, rest, unary) { + tagName = angular.lowercase(tagName); + if (blockElements[tagName]) { + while (stack.last() && inlineElements[stack.last()]) { + parseEndTag("", stack.last()); + } + } + + if (optionalEndTagElements[tagName] && stack.last() == tagName) { + parseEndTag("", tagName); + } + + unary = voidElements[tagName] || !!unary; + + if (!unary) { + stack.push(tagName); + } + + var attrs = {}; + + rest.replace(ATTR_REGEXP, + function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { + var value = doubleQuotedValue + || singleQuotedValue + || unquotedValue + || ''; + + attrs[name] = decodeEntities(value); + }); + if (handler.start) handler.start(tagName, attrs, unary); + } + + function parseEndTag(tag, tagName) { + var pos = 0, i; + tagName = angular.lowercase(tagName); + if (tagName) { + // Find the closest opened tag of the same type + for (pos = stack.length - 1; pos >= 0; pos--) { + if (stack[pos] == tagName) break; + } + } + + if (pos >= 0) { + // Close all the open elements, up the stack + for (i = stack.length - 1; i >= pos; i--) + if (handler.end) handler.end(stack[i]); + + // Remove the open elements from the stack + stack.length = pos; + } + } +} + +var hiddenPre=document.createElement("pre"); +/** + * decodes all entities into regular string + * @param value + * @returns {string} A string with decoded entities. + */ +function decodeEntities(value) { + if (!value) { return ''; } + + hiddenPre.innerHTML = value.replace(//g, '>'); +} + +/** + * create an HTML/XML writer which writes to buffer + * @param {Array} buf use buf.jain('') to get out sanitized html string + * @returns {object} in the form of { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * } + */ +function htmlSanitizeWriter(buf, uriValidator) { + var ignore = false; + var out = angular.bind(buf, buf.push); + return { + start: function(tag, attrs, unary) { + tag = angular.lowercase(tag); + if (!ignore && specialElements[tag]) { + ignore = tag; + } + if (!ignore && validElements[tag] === true) { + out('<'); + out(tag); + angular.forEach(attrs, function(value, key) { + var lkey=angular.lowercase(key); + var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); + if (validAttrs[lkey] === true && + (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { + out(' '); + out(key); + out('="'); + out(encodeEntities(value)); + out('"'); + } + }); + out(unary ? '/>' : '>'); + } + }, + end: function(tag) { + tag = angular.lowercase(tag); + if (!ignore && validElements[tag] === true) { + out(''); + } + if (tag == ignore) { + ignore = false; + } + }, + chars: function(chars) { + if (!ignore) { + out(encodeEntities(chars)); + } + } + }; +} + + +// define ngSanitize module and register $sanitize service +angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); + +/* global sanitizeText: false */ + +/** + * @ngdoc filter + * @name linky + * @kind function + * + * @description + * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and + * plain email address links. + * + * Requires the {@link ngSanitize `ngSanitize`} module to be installed. + * + * @param {string} text Input text. + * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. + * @returns {string} Html-linkified text. + * + * @usage + + * + * @example + + + +
+ Snippet: + + + + + + + + + + + + + + + + + + + + + +
FilterSourceRendered
linky filter +
<div ng-bind-html="snippet | linky">
</div>
+
+
+
linky target +
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
+
+
+
no filter
<div ng-bind="snippet">
</div>
+ + + it('should linkify the snippet with urls', function() { + expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). + toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); + expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); + }); + + it('should not linkify snippet without the linky filter', function() { + expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). + toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); + expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new http://link.'); + expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). + toBe('new http://link.'); + expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); + expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) + .toBe('new http://link.'); + }); + + it('should work with the target property', function() { + expect(element(by.id('linky-target')). + element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). + toBe('http://angularjs.org/'); + expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); + }); + + + */ +angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { + var LINKY_URL_REGEXP = + /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/i, + MAILTO_REGEXP = /^mailto:/i; + + return function(text, target) { + if (!text) return text; + var match; + var raw = text; + var html = []; + var url; + var i; + while ((match = raw.match(LINKY_URL_REGEXP))) { + // We can not end in these as they are sometimes found at the end of the sentence + url = match[0]; + // if we did not match ftp/http/www/mailto then assume mailto + if (!match[2] && !match[4]) { + url = (match[3] ? 'http://' : 'mailto:') + url; + } + i = match.index; + addText(raw.substr(0, i)); + addLink(url, match[0].replace(MAILTO_REGEXP, '')); + raw = raw.substring(i + match[0].length); + } + addText(raw); + return $sanitize(html.join('')); + + function addText(text) { + if (!text) { + return; + } + html.push(sanitizeText(text)); + } + + function addLink(url, text) { + html.push(''); + addText(text); + html.push(''); + } + }; +}]); + + +})(window, window.angular); diff --git a/LiveChat/ClientComponents/angularjs/angular.min.js b/LiveChat/ClientComponents/angularjs/angular.min.js new file mode 100644 index 0000000..2c28ef9 --- /dev/null +++ b/LiveChat/ClientComponents/angularjs/angular.min.js @@ -0,0 +1,290 @@ +/* + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(O,U,t){'use strict';function J(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.3/"+(b?b+"/":"")+a;for(a=1;a").append(b).html();try{return b[0].nodeType===Na?M(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+M(b)})}catch(d){return M(c)}}function yc(b){try{return decodeURIComponent(b)}catch(a){}}function zc(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g, +"%20").split("="),d=yc(c[0]),w(d)&&(b=w(c[1])?yc(c[1]):!0,Xa.call(a,d)?G(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];m(b,function(b,d){G(b)?m(b,function(b){a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))}):a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))});return a.length?a.join("&"):""}function ob(b){return ma(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ma(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g, +"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Yd(b,a){var c,d,e=Oa.length;for(d=0;d/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=eb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e= +/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(c.debugInfoEnabled=!0,O.name=O.name.replace(e,""));if(O&&!f.test(O.name))return d();O.name=O.name.replace(f,"");ca.resumeBootstrap=function(b){m(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function $d(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function ae(b){b=ca.element(b).injector();if(!b)throw Fa("test");return b.get("$$testability")}function Bc(b,a){a=a|| +"_";return b.replace(be,function(b,d){return(d?a:"")+b.toLowerCase()})}function ce(){var b;if(!Cc){var a=pb();la=O.jQuery;w(a)&&(la=null===a?t:O[a]);la&&la.fn.on?(y=la,P(la.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):y=Q;ca.element=y;Cc=!0}}function Sb(b, +a,c){if(!b)throw Fa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&G(b)&&(b=b[b.length-1]);Sb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ra(b,a){if("hasOwnProperty"===b)throw Fa("badname",a);}function Dc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g")+d[2];for(d=d[0];d--;)c=c.lastChild;f=cb(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";m(f,function(a){e.appendChild(a)});return e}function Q(b){if(b instanceof Q)return b;var a;L(b)&&(b=R(b),a=!0);if(!(this instanceof Q)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new Q(b)}if(a){a=U; +var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Nc(b,a))?c.childNodes:[]}Oc(this,b)}function Vb(b){return b.cloneNode(!0)}function tb(b,a){a||ub(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;dk&&this.remove(s.key);return b}},get:function(a){if(k").parent()[0])});var f=S(a,b,a,c,d,e);Z.$$addScopeClass(a); +var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?y(Yb(g,y("
").append(a).html())):c?Pa.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);Z.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a,b,c,d,e,f){function g(a, +c,d,e){var f,k,l,s,n,B,C;if(p)for(C=Array(c.length),s=0;sE.priority)break;if(v=E.scope)E.templateUrl|| +(H(v)?(O("new/isolated scope",u||$,E,ba),u=E):O("new/isolated scope",u,E,ba)),$=$||E;w=E.name;!E.templateUrl&&E.controller&&(v=E.controller,N=N||ga(),O("'"+w+"' controller",N[w],E,ba),N[w]=E);if(v=E.transclude)K=!0,E.$$tlb||(O("transclusion",m,E,ba),m=E),"element"==v?(q=!0,F=E.priority,v=ba,ba=d.$$element=y(U.createComment(" "+w+": "+d[w]+" ")),b=ba[0],T(f,za.call(v,0),b),A=Z(v,e,F,g&&g.name,{nonTlbTranscludeDirective:m})):(v=y(Vb(b)).contents(),ba.empty(),A=Z(v,e));if(E.template)if(I=!0,O("template", +D,E,ba),D=E,v=z(E.template)?E.template(ba,d):E.template,v=fa(v),E.replace){g=E;v=Tb.test(v)?$c(Yb(E.templateNamespace,R(v))):[];b=v[0];if(1!=v.length||b.nodeType!==qa)throw ea("tplrt",w,"");T(f,ba,b);Ta={$attr:{}};v=ha(b,[],Ta);var Q=a.splice(xa+1,a.length-(xa+1));u&&ad(v);a=a.concat(v).concat(Q);J(d,Ta);Ta=a.length}else ba.html(v);if(E.templateUrl)I=!0,O("template",D,E,ba),D=E,E.replace&&(g=E),S=Lf(a.splice(xa,a.length-xa),ba,d,f,K&&A,h,k,{controllerDirectives:N,newScopeDirective:$!==E&&$,newIsolateScopeDirective:u, +templateDirective:D,nonTlbTranscludeDirective:m}),Ta=a.length;else if(E.compile)try{Aa=E.compile(ba,d,A),z(Aa)?n(null,Aa,M,P):Aa&&n(Aa.pre,Aa.post,M,P)}catch(Kf){c(Kf,ua(ba))}E.terminal&&(S.terminal=!0,F=Math.max(F,E.priority))}S.scope=$&&!0===$.scope;S.transcludeOnThisElement=K;S.templateOnThisElement=I;S.transclude=A;s.hasElementTranscludeDirective=q;return S}function ad(a){for(var b=0,c=a.length;bn.priority)&&-1!=n.restrict.indexOf(f)&&(k&&(n=Ob(n,{$$start:k,$$end:l})),b.push(n),h=n)}catch(x){c(x)}}return h}function A(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d"+b+"";return c.childNodes[0].childNodes;default:return b}}function Q(a,b){if("srcdoc"==b)return I.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b|| +"ngSrc"==b))return I.RESOURCE_URL}function V(a,c,d,e,f){var g=Q(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ta(a))throw ea("selmulti",ua(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents");var s=h[e];s!==d&&(l=s&&b(s,!0,g,f),d=s);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e, +a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=a)return b;for(;a--;)8=== +b[a].nodeType&&Mf.call(b,a,1);return b}function Xe(){var b={},a=!1;this.register=function(a,d){Ra(a,"controller");H(a)?P(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!H(a.$scope))throw J("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,l){var k,n,r;h=!0===h;l&&L(l)&&(r=l);if(L(f)){l=f.match(Xc);if(!l)throw Nf("ctrlfmt",f);n=l[1];r=r||l[3];f=b.hasOwnProperty(n)?b[n]:Dc(g.$scope,n,!0)||(a?Dc(d,n,!0):t);Qa(f, +n,!0)}if(h)return h=(G(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),r&&e(g,r,k,n||f.name),P(function(){var a=c.invoke(f,k,g,n);a!==k&&(H(a)||z(a))&&(k=a,r&&e(g,r,k,n||f.name));return k},{instance:k,identifier:r});k=c.instantiate(f,g,n);r&&e(g,r,k,n||f.name);return k}}]}function Ye(){this.$get=["$window",function(b){return y(b.document)}]}function Ze(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return H(b)?aa(b)?b.toISOString():db(b):b} +function cf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||A(b)||(G(b)?m(b,function(b,c){a.push(ma(d)+"="+ma(Zb(b)))}):a.push(ma(d)+"="+ma(Zb(b))))});return a.join("&")}}}function df(){this.$get=function(){return function(b){function a(b,e,f){null===b||A(b)||(G(b)?m(b,function(b){a(b,e+"[]")}):H(b)&&!aa(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ma(e)+"="+ma(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b, +a){if(L(b)){var c=b.replace(Of,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(cd))||(d=(d=c.match(Pf))&&Qf[d[0]].test(c));d&&(b=wc(c))}}return b}function dd(b){var a=ga(),c;L(b)?m(b.split("\n"),function(b){c=b.indexOf(":");var e=M(R(b.substr(0,c)));b=R(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):H(b)&&m(b,function(b,c){var f=M(c),g=R(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function ed(b){var a;return function(c){a||(a=dd(b));return c?(c=a[M(c)],void 0===c&&(c=null),c):a}}function fd(b, +a,c,d){if(z(d))return d(b,a,c);m(d,function(d){b=d(b,a,c)});return b}function bf(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return H(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?db(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return w(b)? +(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=P({},a);b.data=a.data?fd(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c,e={};m(a,function(a,d){z(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!ca.isObject(a))throw J("$http")("badreq",a);var e=P({method:"get",transformRequest:b.transformRequest, +transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=P({},a.headers),f,g,h,c=P({},c.common,c[M(a.method)]);a:for(f in c){g=M(f);for(h in e)if(M(h)===g)continue a;e[f]=c[f]}return d(e,ia(a))}(a);e.method=rb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer):e.paramSerializer;var f=[function(a){var d=a.headers,e=fd(a.data,ed(d),t,a.transformRequest);A(e)&&m(d,function(a,b){"content-type"===M(b)&&delete d[b]});A(a.withCredentials)&& +!A(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},t],g=h.when(e);for(m(x,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Qa(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Qa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g} +function n(c,f){function l(b,c,d,e){function f(){n(c,b,d,e)}N&&(200<=b&&300>b?N.put(S,[b,c,dd(d),e]):N.remove(S));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function n(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:ed(d),config:c,statusText:e})}function x(a){n(a.data,a.status,ia(a.headers()),a.statusText)}function m(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),B=I.promise,N,D,q=c.headers,S=r(c.url,c.paramSerializer(c.params)); +k.pendingRequests.push(c);B.then(m,m);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(N=H(c.cache)?c.cache:H(b.cache)?b.cache:s);N&&(D=N.get(S),w(D)?D&&z(D.then)?D.then(x,x):G(D)?n(D[1],D[0],ia(D[2]),D[3]):n(D,200,{},"OK"):N.put(S,B));A(D)&&((D=gd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(q[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,S,f,l,q,c.timeout,c.withCredentials,c.responseType));return B}function r(a,b){0=l&&(u.resolve(C),x(p.$$intervalId),delete f[p.$$intervalId]);F||b.$apply()},h);f[p.$$intervalId]=u;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function ge(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".", +GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), +SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=ob(b[a]);return b.join("/")}function hd(b,a){var c=Ba(b);a.$$protocol=c.protocol; +a.$$host=c.hostname;a.$$port=W(c.port)||Tf[c.protocol]||null}function id(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=zc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ja(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/, +"$1")}function cc(b){return b.substr(0,Ja(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);hd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);id(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), +!0;var f,g;(f=ya(b,d))!==t?(g=f,g=(f=ya(a,f))!==t?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);hd(b,this);this.$$parse=function(d){var e=ya(b,d)||ya(c,d),f;A(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",A(e)&&(b=d,this.replace())):(f=ya(a,e),A(f)&&(f=e));id(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose= +function(){var c=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ja(b)==Ja(a)?(this.$$parse(a),!0):!1}}function jd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ja(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c= +Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function kd(b,a){return function(c){if(A(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ff(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return w(a)?(b=a,this):b};this.html5Mode=function(b){return ab(b)?(a.enabled=b,this):H(b)?(ab(b.enabled)&&(a.enabled=b.enabled), +ab(b.requireBase)&&(a.requireBase=b.requireBase),ab(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var r=d.url(),s;if(a.enabled){if(!n&&a.requireBase)throw Cb("nobase");s=r.substring(0, +r.indexOf("/",r.indexOf("//")+2))+(n||"/");n=e.history?dc:jd}else s=Ja(r),n=ec;k=new n(s,"#"+b);k.$$parseLinkUrl(r,r);k.$$state=d.state();var x=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=y(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);x.test(h)|| +!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(r)&&d.url(k.absUrl(),!0);var C=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(C=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a= +Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace,n=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(C||n)C=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(n&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function gf(){var b=!0,a=this;this.debugEnabled=function(a){return w(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&& +(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];m(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]} +function Ca(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw da("isecfld",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b.window===b)throw da("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw da("isecdom",a);if(b===Object)throw da("isecobj",a);}return b}function ld(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b===Uf||b===Vf||b===Wf)throw da("isecff",a); +}}function Xf(b,a){return"undefined"!==typeof b?b:a}function md(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function T(b,a){var c,d;switch(b.type){case q.Program:c=!0;m(b.body,function(b){T(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case q.Literal:b.constant=!0;b.toWatch=[];break;case q.UnaryExpression:T(b.argument,a);b.constant=b.argument.constant;b.toWatch=b.argument.toWatch;break;case q.BinaryExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&& +b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case q.LogicalExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case q.ConditionalExpression:T(b.test,a);T(b.alternate,a);T(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case q.Identifier:b.constant=!1;b.toWatch=[b];break;case q.MemberExpression:T(b.object,a);b.computed&&T(b.property,a); +b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case q.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];m(b.arguments,function(b){T(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case q.AssignmentExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=[b];break;case q.ArrayExpression:c=!0;d=[];m(b.elements,function(b){T(b,a);c= +c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case q.ObjectExpression:c=!0;d=[];m(b.properties,function(b){T(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case q.ThisExpression:b.constant=!1,b.toWatch=[]}}function nd(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:t}}function od(b){return b.type===q.Identifier||b.type===q.MemberExpression}function pd(b){if(1=== +b.body.length&&od(b.body[0].expression))return{type:q.AssignmentExpression,left:b.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function qd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===q.Literal||b.body[0].expression.type===q.ArrayExpression||b.body[0].expression.type===q.ObjectExpression)}function rd(b,a){this.astBuilder=b;this.$filter=a}function sd(b,a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){oa(b,d);a=a.split(".");for(var e,f=0;1< +a.length;f++){e=Ca(a.shift(),d);var g=oa(b[e],d);g||(g={},b[e]=g);b=g}e=Ca(a.shift(),d);oa(b[e],d);return b[e]=c}function Fb(b){return"constructor"==b}function fc(b){return z(b.valueOf)?b.valueOf():Yf.call(b)}function hf(){var b=ga(),a=ga();this.$get=["$filter","$sniffer",function(c,d){function e(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function f(a,b,c,d,f){var g=d.inputs,h;if(1===g.length){var k=e,g=g[0];return a.$watch(function(a){var b= +g(a);e(b,k)||(h=d(a,t,t,[b]),k=b&&fc(b));return h},b,c,f)}for(var l=[],n=[],r=0,m=g.length;r=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;fa)for(b in l++,f)e.hasOwnProperty(b)|| +(m--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,g,k=1m&&(E=4-m,u[E]||(u[E]=[]),u[E].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){s=!1;break a}}catch(A){g(A)}if(!(k=x.$$watchersCount&&x.$$childHead||x!==this&&x.$$nextSibling))for(;x!== +this&&!(k=x.$$nextSibling);)x=x.$parent}while(x=k);if((s||t.length)&&!m--)throw p.$$phase=null,c("infdig",a,u);}while(s||t.length);for(p.$$phase=null;w.length;)try{w.shift()()}catch(y){g(y)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();s(this,-this.$$watchersCount);for(var b in this.$$listenerCount)x(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail== +this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=v;this.$on=this.$watch=this.$watchGroup=function(){return v};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)}, +$evalAsync:function(a,b){p.$$phase||t.length||l.defer(function(){t.length&&p.$digest()});t.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){w.push(a)},$apply:function(a){try{return r("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&I.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]|| +(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,x(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=cb([h],arguments,1),l,n;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(n=d.length;lUa)throw Da("iequirks");var d=ia(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs= +d.getTrusted=function(a,b){return b},d.valueOf=Ya);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;m(pa,function(a,b){var c=M(b);d[hb("parse_as_"+c)]=function(b){return e(a,b)};d[hb("get_trusted_"+c)]=function(b){return f(a,b)};d[hb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function of(){this.$get=["$window","$document",function(b,a){var c={},d=W((/android (\d+)/.exec(M((b.navigator|| +{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var r in l)if(k=h.exec(r)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in l);!d||k&&n||(k=L(l.webkitTransition),n=L(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"=== +a&&11>=Ua)return!1;if(A(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:fb(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function qf(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;L(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=a.defaults&&a.defaults.transformResponse;G(h)?h=h.filter(function(a){return a!==$b}):h===$b&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){b.put(f, +a.data);return a.data},function(a){if(!g)throw ea("tpload",f,a.status,a.statusText);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function rf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];m(a,function(a){var d=ca.element(a).data("$binding");d&&m(d,function(d){c?(new RegExp("(^|\\s)"+ud(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a, +b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;hb;b=Math.abs(b);var g=Infinity===b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,n=[];g&&(l="\u221e"); +if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Dd)[1]||"").length;A(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Dd),h=g[0],g=g[1]||"",r=0,s=a.lgSize,m=a.gSize;if(h.length>=s+m)for(r=h.length-s,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=rb(a?"SHORT"+b:b);return d[f][e]}}function Ed(b){var a= +(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Fd(b){return function(a){var c=Ed(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function zd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=W(b[9]+b[10]),g=W(b[9]+b[11]));h.call(a,W(b[1]), +W(b[2])-1,W(b[3]));f=W(b[4]||0)-f;g=W(b[5]||0)-g;h=W(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=fg.test(c)?W(c):a(c));V(c)&&(c=new Date(c));if(!aa(c)||!isFinite(c.getTime()))return c;for(;e;)(k=gg.exec(e))?(h=cb(h,k,1),e=h.pop()):(h.push(e),e=null);var n=c.getTimezoneOffset(); +f&&(n=xc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));m(h,function(a){l=hg[a];g+=l?l(c,b.DATETIME_FORMATS,n):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function ag(){return function(b,a){A(a)&&(a=2);return db(b,a)}}function bg(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):W(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!G(b)&&!L(b))return b;c=!c||isNaN(c)?0:W(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0, +c+a),c)}}function Bd(b){function a(a,c){c=c?-1:1;return a.map(function(a){var d=1,h=Ya;if(z(a))h=a;else if(L(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))d="-"==a.charAt(0)?-1:1,a=a.substring(1);if(""!==a&&(h=b(a),h.constant))var l=h(),h=function(a){return a[l]}}return{get:h,descending:d*c}})}function c(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(b,e,f){if(!Ea(b))return b;G(e)||(e=[e]);0===e.length&&(e=["+"]);var g=a(e,f);b=Array.prototype.map.call(b, +function(a,b){return{value:a,predicateValues:g.map(function(d){var e=d.get(a);d=typeof e;if(null===e)d="string",e="null";else if("string"===d)e=e.toLowerCase();else if("object"===d)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),c(e)))break a;if(rc(e)&&(e=e.toString(),c(e)))break a;e=b}return{value:e,type:d}})}});b.sort(function(a,b){for(var c=0,d=0,e=g.length;db||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(aa(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1)); +if(ig.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},m(e,function(b,c){c=F};g.$observe("min",function(a){F=s(a);h.$validate()})}if(w(g.max)||g.ngMax){var u; +h.$validators.max=function(a){return!r(a)||A(u)||c(a)<=u};g.$observe("max",function(a){u=s(a);h.$validate()})}}}function Id(b,a,c,d){(d.$$hasNativeValidators=H(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?t:b})}function Jd(b,a,c,d,e){if(w(d)){b=b(d);if(!b.constant)throw J("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,na={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};na.optgroup=na.option;na.tbody=na.tfoot=na.colgroup=na.caption=na.thead; +na.th=na.td;var Pa=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===U.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),Q(O).on("load",a))},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:kg,sort:[].sort,splice:[].splice},Ab={};m("multiple selected checked disabled readOnly required open".split(" "),function(b){Ab[M(b)]=b});var Tc={};m("input select option textarea button form details".split(" "), +function(b){Tc[b]=!0});var Uc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};m({data:Wb,removeData:ub,hasData:function(b){for(var a in ib[b.ng339])return!0;return!1}},function(b,a){Q[a]=b});m({data:Wb,inheritedData:zb,scope:function(b){return y.data(b,"$scope")||zb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return y.data(b,"$isolateScope")||y.data(b,"$isolateScopeNoTemplate")},controller:Qc,injector:function(b){return zb(b, +"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:wb,css:function(b,a,c){a=hb(a);if(w(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==Na&&2!==d&&8!==d)if(d=M(a),Ab[d])if(w(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:t;else if(w(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(w(c))b[a]=c;else return b[a]}, +text:function(){function b(a,b){if(A(b)){var d=a.nodeType;return d===qa||d===Na?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(A(a)){if(b.multiple&&"select"===ta(b)){var c=[];m(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(A(a))return b.innerHTML;tb(b,!0);b.innerHTML=a},empty:Rc},function(b,a){Q.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Rc&&(2==b.length&&b!==wb&&b!==Qc? +a:d)===t){if(H(a)){for(e=0;e <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var qg={n:"\n",f:"\f",r:"\r", +t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a|| +"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=w(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw da("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">=");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:c.text, +left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=fa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant(): +this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===c.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:q.CallExpression,callee:this.identifier(), +arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break; +a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;c={type:q.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}}, +throwError:function(a,c){throw da("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw da("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw da("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a]; +var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0},"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:t},"this":{type:q.ThisExpression}}};rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[], +body:[],own:{}},inputs:[]};T(e,d.$filter);var f="",g;this.stage="assign";if(g=pd(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l");g=nd(e.body);d.stage="inputs";m(g,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+ +"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus","text",f))(this.$filter,Ca,oa,ld,Xf,md,a);this.state=this.stage=t;f.literal=qd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;m(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")}, +generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;m(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,n,r;e=e||v;if(!g&&w(a.watchId))c=c||this.nextId(),this.if_("i", +this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case q.Program:m(a.body,function(c,d){k.recurse(c.expression,t,t,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case q.Literal:r=this.escape(a.value);this.assign(c,r);e(r);break;case q.UnaryExpression:this.recurse(a.argument,t,t,function(a){l=a});r=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,r);e(r);break;case q.BinaryExpression:this.recurse(a.left, +t,t,function(a){h=a});this.recurse(a.right,t,t,function(a){l=a});r="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l,0):"("+h+")"+a.operator+"("+l+")";this.assign(c,r);e(r);break;case q.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case q.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c); +break;case q.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ca(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l", +a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case q.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId();k.recurse(a.object,h,t,function(){k.if_(k.notNull(h),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),r=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,r),d&&(d.computed=!0,d.name=l);else{Ca(a.property.name); +f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));r=k.nonComputedMember(h,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))r=k.ensureSafeObject(r);k.assign(c,r);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case q.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),n=[],m(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);n.push(c)}),r=l+ +"("+n.join(",")+")",k.assign(c,r),e(c)):(l=k.nextId(),h={},n=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);m(a.arguments,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(k.ensureSafeObject(a))})});h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),r=k.member(h.context,h.name,h.computed)+"("+n.join(",")+")"):r=l+"("+n.join(",")+")";r=k.ensureSafeObject(r);k.assign(c,r)},function(){k.assign(c,"undefined")});e(c)}));break;case q.AssignmentExpression:l= +this.nextId();h={};if(!od(a.left))throw da("lval");this.recurse(a.left,t,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));r=k.member(h.context,h.name,h.computed)+a.operator+l;k.assign(c,r);e(c||r)})},1);break;case q.ArrayExpression:n=[];m(a.elements,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(a)})});r="["+n.join(",")+"]";this.assign(c,r);e(r);break;case q.ObjectExpression:n=[];m(a.properties,function(a){k.recurse(a.value, +k.nextId(),t,function(c){n.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+c)})});r="{"+n.join(",")+"}";this.assign(c,r);e(r);break;case q.ThisExpression:this.assign(c,"s");e("s");break;case q.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)|| +(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+ +"."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+ +a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true"; +if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw da("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}};sd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;T(e,d.$filter);var f,g;if(f=pd(e))g=this.recurse(f);f=nd(e.body);var h;f&&(h=[],m(f,function(a,c){var e=d.recurse(a); +a.input=e;h.push(e);a.watchId=c}));var l=[];m(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;m(l,function(e){d=e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs=h);f.literal=qd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,c);case q.UnaryExpression:return f= +this.recurse(a.argument),this["unary"+a.operator](f,c);case q.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case q.Identifier:return Ca(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name), +c,d,g.expression);case q.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ca(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f,g.expensiveChecks,c,d,g.expression);case q.CallExpression:return h=[],m(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var m= +[],q=0;q":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e, +f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c? +{context:t,name:t,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g?g[a]:t;c&&oa(h,f);return d?{context:g,name:a,value:h}:h}},computedMember:function(a,c,d,e,f){return function(g,h,l,k){var n=a(g,h,l,k),m,s;null!=n&&(m=c(g,h,l,k),Ca(m,f),e&&1!==e&&n&&!n[m]&&(n[m]={}),s=n[m],oa(s,f));return d?{context:n,name:m,value:s}:s}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,n){h=a(h,l,k,n);f&&1!==f&&h&&!h[c]&&(h[c]={}); +l=null!=h?h[c]:t;(d||Fb(c))&&oa(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]:a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new sd(this.ast,c):new rd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Yf=Object.prototype.valueOf,Da=J("$sce"),pa={HTML:"html",CSS:"css",URL:"url", +RESOURCE_URL:"resourceUrl",JS:"js"},ea=J("$compile"),X=U.createElement("a"),wd=Ba(O.location.href);xd.$inject=["$document"];Lc.$inject=["$provide"];yd.$inject=["$locale"];Ad.$inject=["$locale"];var Dd=".",hg={yyyy:Y("FullYear",4),yy:Y("FullYear",2,0,!0),y:Y("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:Y("Month",2,1),M:Y("Month",1,1),dd:Y("Date",2),d:Y("Date",1),HH:Y("Hours",2),H:Y("Hours",1),hh:Y("Hours",2,-12),h:Y("Hours",1,-12),mm:Y("Minutes",2),m:Y("Minutes",1),ss:Y("Seconds",2),s:Y("Seconds", +1),sss:Y("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},gg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,fg=/^\-?\d+$/;zd.$inject=["$locale"];var cg=ra(M),dg=ra(rb);Bd.$inject= +["$parse"];var ie=ra({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===sa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),sb={};m(Ab,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=wa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});sb[e]=function(){return{restrict:"A", +priority:100,link:f}}}});m(Uc,function(a,c){sb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(jg))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});m(["src","srcset","href"],function(a){var c=wa("ng-"+a);sb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href", +g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ua&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:v,$$renameControl:function(a,c){a.$name=c},$removeControl:v,$setValidity:v,$setDirty:v,$setPristine:v,$setSubmitted:v};Gd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Od=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Gd,compile:function(d,e){d.addClass(Va).addClass(mb);var f=e.name?"name":a&&e.ngForm?"ngForm": +!1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var m=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,t,k.$name),m.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){m.$removeControl(k);f&&Eb(a,e[f],t, +k.$name);P(k,Ib)})}}}}}]},je=Od(),we=Od(!0),ig=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,rg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,sg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,tg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Pd=/^(\d{4})-(\d{2})-(\d{2})$/,Qd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Rd=/^(\d{4})-(\d\d)$/, +Sd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Td={text:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e)},date:lb("date",Pd,Kb(Pd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":lb("datetimelocal",Qd,Kb(Qd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:lb("time",Sd,Kb(Sd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:lb("week",mc,function(a,c){if(aa(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Ed(e),f=7*(f-1);c&&(d=c.getHours(),g= +c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:lb("month",Rd,Kb(Rd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Id(a,c,d,e);kb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:tg.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)|| +A(h)||a>=h};d.$observe("min",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(w(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||A(l)||a<=l};d.$observe("max",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},email:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e); +e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||sg.test(d)}},radio:function(a,c,d,e){A(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Jd(l,a,"ngTrueValue",d.ngTrueValue,!0),n=Jd(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&& +a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:v,button:v,submit:v,reset:v,file:v},Fc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Td[M(h.type)]||Td.text)(f,g,h,l[0],c,a,d,e)}}}}],ug=/^(true|false|\d+)$/,Oe=function(){return{restrict:"A",priority:100,compile:function(a, +c){return ug.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},oe=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],qe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate)); +c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],pe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Ne=ra({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}), +re=lc("",!0),te=lc("Odd",0),se=lc("Even",1),ue=Ma({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),ve=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Kc={},vg={blur:!0,focus:!0};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=wa("ng-"+a);Kc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h= +d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};vg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ye=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=U.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k= +qb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ze=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,m,s,q){var t=0,F,u,p,v=function(){u&&(u.remove(),u=null);F&&(F.$destroy(),F=null);p&&(d.leave(p).then(function(){u=null}),u=p,p=null)};e.$watch(g,function(g){var m=function(){!w(l)||l&&!e.$eval(l)|| +c()},r=++t;g?(a(g,!0).then(function(a){if(r===t){var c=e.$new();s.template=a;a=q(c,function(a){v();d.enter(a,null,f).then(m)});F=c;p=a;F.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){r===t&&(v(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(v(),s.template=null)})}}}}],Qe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Nc(f.template,U).childNodes)(c,function(a){d.append(a)}, +{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],Ae=Ma({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Me=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?R(f):f;e.$parsers.push(function(a){if(!A(a)){var c=[];a&&m(a.split(h),function(a){a&&c.push(g?R(a):a)});return c}});e.$formatters.push(function(a){return G(a)?a.join(f):t});e.$isEmpty=function(a){return!a|| +!a.length}}}},mb="ng-valid",Kd="ng-invalid",Va="ng-pristine",Jb="ng-dirty",Md="ng-pending",Lb=new J("ngModel"),wg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty= +!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=t;this.$name=n(d.name||"",!1)(a);var r=f(d.ngModel),s=r.assign,q=r,C=s,F=null,u,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");q=function(a){var d=r(a);z(d)&&(d=c(a));return d};C=function(a,c){z(r(a))?g(a,{$$$p:p.$modelValue}):s(a,p.$modelValue)}}else if(!r.assign)throw Lb("nonassign",d.ngModel,ua(e));};this.$render=v;this.$isEmpty=function(a){return A(a)|| +""===a||null===a||a!==a};var K=e.inheritedData("$formController")||Ib,y=0;Hd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:K,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Va)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Va);g.addClass(e,Jb);K.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched= +function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators= +function(a,c,d){function e(){var d=!0;m(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(m(p.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;m(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!z(k.then))throw Lb("$asyncValidators",k);g(h,t);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},v):h(!0)}function g(a,c){l===y&&p.$setValidity(a,c)}function h(a){l===y&&d(a)}y++;var l=y;(function(){var a= +p.$$parserName||"parse";if(u===t)g(a,null);else return u||(m(p.$validators,function(a,c){g(c,null)}),m(p.$asyncValidators,function(a,c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(F);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(u=A(c)?t:!0)for(var d= +0;df||e.$isEmpty(c)||c.length<=f}}}}},Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=W(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(ce(),ee(ca),y(U).ready(function(){Zd(U,Ac)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend(''); +//# sourceMappingURL=angular.min.js.map diff --git a/LiveChat/ClientComponents/angularjs/loading-bar.min.js b/LiveChat/ClientComponents/angularjs/loading-bar.min.js new file mode 100644 index 0000000..5026baf --- /dev/null +++ b/LiveChat/ClientComponents/angularjs/loading-bar.min.js @@ -0,0 +1,7 @@ +/*! + * angular-loading-bar v0.8.0 + * https://chieffancypants.github.io/angular-loading-bar + * Copyright (c) 2015 Wes Cruver + * License: MIT + */ +!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(a){var b=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(b,c,d,e,f,g){function h(){d.cancel(j),g.complete(),l=0,k=0}function i(b){var d,e=c.get("$http"),f=a.defaults;!b.cache&&!f.cache||b.cache===!1||"GET"!==b.method&&"JSONP"!==b.method||(d=angular.isObject(b.cache)?b.cache:angular.isObject(f.cache)?f.cache:e);var g=void 0!==d?void 0!==d.get(b.url):!1;return void 0!==b.cached&&g!==b.cached?b.cached:(b.cached=g,g)}var j,k=0,l=0,m=g.latencyThreshold;return{request:function(a){return a.ignoreLoadingBar||i(a)||(e.$broadcast("cfpLoadingBar:loading",{url:a.url}),0===k&&(j=d(function(){g.start()},m)),k++,g.set(l/k)),a},response:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),l>=k?h():g.set(l/k)),a):(f.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),a)},responseError:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),l>=k?h():g.set(l/k)),b.reject(a)):(f.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),b.reject(a))}}}];a.interceptors.push(b)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.autoIncrement=!0,this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='
',this.loadingBarTemplate='
',this.$get=["$injector","$document","$timeout","$rootScope",function(a,b,c,d){function e(){k||(k=a.get("$animate"));var e=b.find(n).eq(0);c.cancel(m),r||(d.$broadcast("cfpLoadingBar:started"),r=!0,v&&k.enter(o,e,angular.element(e[0].lastChild)),u&&k.enter(q,e,angular.element(e[0].lastChild)),f(w))}function f(a){if(r){var b=100*a+"%";p.css("width",b),s=a,t&&(c.cancel(l),l=c(function(){g()},250))}}function g(){if(!(h()>=1)){var a=0,b=h();a=b>=0&&.25>b?(3*Math.random()+3)/100:b>=.25&&.65>b?3*Math.random()/100:b>=.65&&.9>b?2*Math.random()/100:b>=.9&&.99>b?.005:0;var c=h()+a;f(c)}}function h(){return s}function i(){s=0,r=!1}function j(){k||(k=a.get("$animate")),d.$broadcast("cfpLoadingBar:completed"),f(1),c.cancel(m),m=c(function(){var a=k.leave(o,i);a&&a.then&&a.then(i),k.leave(q)},500)}var k,l,m,n=this.parentSelector,o=angular.element(this.loadingBarTemplate),p=o.find("div").eq(0),q=angular.element(this.spinnerTemplate),r=!1,s=0,t=this.autoIncrement,u=this.includeSpinner,v=this.includeBar,w=this.startSize;return{start:e,set:f,status:h,inc:g,complete:j,autoIncrement:this.autoIncrement,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}(); \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css b/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css new file mode 100644 index 0000000..c702161 --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css @@ -0,0 +1,366 @@ +/*! + * Datetimepicker for Bootstrap 3 + * ! version : 4.7.14 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */ +.bootstrap-datetimepicker-widget { + list-style: none; +} +.bootstrap-datetimepicker-widget.dropdown-menu { + margin: 2px 0; + padding: 4px; + width: 19em; +} +@media (min-width: 768px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 992px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 1200px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +.bootstrap-datetimepicker-widget.dropdown-menu:before, +.bootstrap-datetimepicker-widget.dropdown-menu:after { + content: ''; + display: inline-block; + position: absolute; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #cccccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + top: -7px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + top: -6px; + left: 8px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #cccccc; + border-top-color: rgba(0, 0, 0, 0.2); + bottom: -7px; + left: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid white; + bottom: -6px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { + left: auto; + right: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { + left: auto; + right: 7px; +} +.bootstrap-datetimepicker-widget .list-unstyled { + margin: 0; +} +.bootstrap-datetimepicker-widget a[data-action] { + padding: 6px 0; +} +.bootstrap-datetimepicker-widget a[data-action]:active { + box-shadow: none; +} +.bootstrap-datetimepicker-widget .timepicker-hour, +.bootstrap-datetimepicker-widget .timepicker-minute, +.bootstrap-datetimepicker-widget .timepicker-second { + width: 54px; + font-weight: bold; + font-size: 1.2em; + margin: 0; +} +.bootstrap-datetimepicker-widget button[data-action] { + padding: 6px; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle AM/PM"; +} +.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Clear the picker"; +} +.bootstrap-datetimepicker-widget .btn[data-action="today"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Set the date to today"; +} +.bootstrap-datetimepicker-widget .picker-switch { + text-align: center; +} +.bootstrap-datetimepicker-widget .picker-switch::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle Date and Time Screens"; +} +.bootstrap-datetimepicker-widget .picker-switch td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; +} +.bootstrap-datetimepicker-widget .picker-switch td span { + line-height: 2.5; + height: 2.5em; + width: 100%; +} +.bootstrap-datetimepicker-widget table { + width: 100%; + margin: 0; +} +.bootstrap-datetimepicker-widget table td, +.bootstrap-datetimepicker-widget table th { + text-align: center; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table th { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table th.picker-switch { + width: 145px; +} +.bootstrap-datetimepicker-widget table th.disabled, +.bootstrap-datetimepicker-widget table th.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table th.prev::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Previous Month"; +} +.bootstrap-datetimepicker-widget table th.next::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Next Month"; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th { + cursor: pointer; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td { + height: 54px; + line-height: 54px; + width: 54px; +} +.bootstrap-datetimepicker-widget table td.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: #777777; +} +.bootstrap-datetimepicker-widget table td.day { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table td.day:hover, +.bootstrap-datetimepicker-widget table td.hour:hover, +.bootstrap-datetimepicker-widget table td.minute:hover, +.bootstrap-datetimepicker-widget table td.second:hover { + background: #eeeeee; + cursor: pointer; +} +.bootstrap-datetimepicker-widget table td.old, +.bootstrap-datetimepicker-widget table td.new { + color: #777777; +} +.bootstrap-datetimepicker-widget table td.today { + position: relative; +} +.bootstrap-datetimepicker-widget table td.today:before { + content: ''; + display: inline-block; + border: 0 0 7px 7px solid transparent; + border-bottom-color: #337ab7; + border-top-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: 4px; + right: 4px; +} +.bootstrap-datetimepicker-widget table td.active, +.bootstrap-datetimepicker-widget table td.active:hover { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td.active.today:before { + border-bottom-color: #fff; +} +.bootstrap-datetimepicker-widget table td.disabled, +.bootstrap-datetimepicker-widget table td.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table td span { + display: inline-block; + width: 54px; + height: 54px; + line-height: 54px; + margin: 2px 1.5px; + cursor: pointer; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table td span:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td span.active { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td span.old { + color: #777777; +} +.bootstrap-datetimepicker-widget table td span.disabled, +.bootstrap-datetimepicker-widget table td span.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget.usetwentyfour td.hour { + height: 27px; + line-height: 27px; +} +.input-group.date .input-group-addon { + cursor: pointer; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} diff --git a/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js b/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js new file mode 100644 index 0000000..a60af89 --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js @@ -0,0 +1,8 @@ +/*! version : 4.7.14 + ========================================================= + bootstrap-datetimejs + https://github.com/Eonasdan/bootstrap-datetimepicker + Copyright (c) 2015 Jonathan Peterson + ========================================================= + */ +!function(a){"use strict";if("function"==typeof define&&define.amd)define(["jquery","moment"],a);else if("object"==typeof exports)a(require("jquery"),require("moment"));else{if("undefined"==typeof jQuery)throw"bootstrap-datetimepicker requires jQuery to be loaded first";if("undefined"==typeof moment)throw"bootstrap-datetimepicker requires Moment.js to be loaded first";a(jQuery,moment)}}(function(a,b){"use strict";if(!b)throw new Error("bootstrap-datetimepicker requires Moment.js to be loaded first");var c=function(c,d){var e,f,g,h,i,j={},k=b().startOf("d"),l=k.clone(),m=!0,n=!1,o=!1,p=0,q=[{clsName:"days",navFnc:"M",navStep:1},{clsName:"months",navFnc:"y",navStep:1},{clsName:"years",navFnc:"y",navStep:10}],r=["days","months","years"],s=["top","bottom","auto"],t=["left","right","auto"],u=["default","top","bottom"],v={up:38,38:"up",down:40,40:"down",left:37,37:"left",right:39,39:"right",tab:9,9:"tab",escape:27,27:"escape",enter:13,13:"enter",pageUp:33,33:"pageUp",pageDown:34,34:"pageDown",shift:16,16:"shift",control:17,17:"control",space:32,32:"space",t:84,84:"t","delete":46,46:"delete"},w={},x=function(a){if("string"!=typeof a||a.length>1)throw new TypeError("isEnabled expects a single character string parameter");switch(a){case"y":return-1!==g.indexOf("Y");case"M":return-1!==g.indexOf("M");case"d":return-1!==g.toLowerCase().indexOf("d");case"h":case"H":return-1!==g.toLowerCase().indexOf("h");case"m":return-1!==g.indexOf("m");case"s":return-1!==g.indexOf("s");default:return!1}},y=function(){return x("h")||x("m")||x("s")},z=function(){return x("y")||x("M")||x("d")},A=function(){var b=a("").append(a("").append(a("").addClass("prev").attr("data-action","previous").append(a("").addClass(d.icons.previous))).append(a("").addClass("picker-switch").attr("data-action","pickerSwitch").attr("colspan",d.calendarWeeks?"6":"5")).append(a("").addClass("next").attr("data-action","next").append(a("").addClass(d.icons.next)))),c=a("").append(a("").append(a("").attr("colspan",d.calendarWeeks?"8":"7")));return[a("
").addClass("datepicker-days").append(a("").addClass("table-condensed").append(b).append(a(""))),a("
").addClass("datepicker-months").append(a("
").addClass("table-condensed").append(b.clone()).append(c.clone())),a("
").addClass("datepicker-years").append(a("
").addClass("table-condensed").append(b.clone()).append(c.clone()))]},B=function(){var b=a(""),c=a(""),e=a("");return x("h")&&(b.append(a("
").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","incrementHours").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-hour").attr("data-time-component","hours").attr("data-action","showHours"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","decrementHours").append(a("").addClass(d.icons.down))))),x("m")&&(x("h")&&(b.append(a("").addClass("separator")),c.append(a("").addClass("separator").html(":")),e.append(a("").addClass("separator"))),b.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","incrementMinutes").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-minute").attr("data-time-component","minutes").attr("data-action","showMinutes"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","decrementMinutes").append(a("").addClass(d.icons.down))))),x("s")&&(x("m")&&(b.append(a("").addClass("separator")),c.append(a("").addClass("separator").html(":")),e.append(a("").addClass("separator"))),b.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","incrementSeconds").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-second").attr("data-time-component","seconds").attr("data-action","showSeconds"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","decrementSeconds").append(a("").addClass(d.icons.down))))),f||(b.append(a("").addClass("separator")),c.append(a("").append(a("").addClass("separator"))),a("
").addClass("timepicker-picker").append(a("").addClass("table-condensed").append([b,c,e]))},C=function(){var b=a("
").addClass("timepicker-hours").append(a("
").addClass("table-condensed")),c=a("
").addClass("timepicker-minutes").append(a("
").addClass("table-condensed")),d=a("
").addClass("timepicker-seconds").append(a("
").addClass("table-condensed")),e=[B()];return x("h")&&e.push(b),x("m")&&e.push(c),x("s")&&e.push(d),e},D=function(){var b=[];return d.showTodayButton&&b.push(a("
").append(a("").attr("data-action","today").append(a("").addClass(d.icons.today)))),!d.sideBySide&&z()&&y()&&b.push(a("").append(a("").attr("data-action","togglePicker").append(a("").addClass(d.icons.time)))),d.showClear&&b.push(a("").append(a("").attr("data-action","clear").append(a("").addClass(d.icons.clear)))),d.showClose&&b.push(a("").append(a("").attr("data-action","close").append(a("").addClass(d.icons.close)))),a("").addClass("table-condensed").append(a("").append(a("").append(b)))},E=function(){var b=a("
").addClass("bootstrap-datetimepicker-widget dropdown-menu"),c=a("
").addClass("datepicker").append(A()),e=a("
").addClass("timepicker").append(C()),g=a("
    ").addClass("list-unstyled"),h=a("
  • ").addClass("picker-switch"+(d.collapse?" accordion-toggle":"")).append(D());return d.inline&&b.removeClass("dropdown-menu"),f&&b.addClass("usetwentyfour"),d.sideBySide&&z()&&y()?(b.addClass("timepicker-sbs"),b.append(a("
    ").addClass("row").append(c.addClass("col-sm-6")).append(e.addClass("col-sm-6"))),b.append(h),b):("top"===d.toolbarPlacement&&g.append(h),z()&&g.append(a("
  • ").addClass(d.collapse&&y()?"collapse in":"").append(c)),"default"===d.toolbarPlacement&&g.append(h),y()&&g.append(a("
  • ").addClass(d.collapse&&z()?"collapse":"").append(e)),"bottom"===d.toolbarPlacement&&g.append(h),b.append(g))},F=function(){var b,e={};return b=c.is("input")||d.inline?c.data():c.find("input").data(),b.dateOptions&&b.dateOptions instanceof Object&&(e=a.extend(!0,e,b.dateOptions)),a.each(d,function(a){var c="date"+a.charAt(0).toUpperCase()+a.slice(1);void 0!==b[c]&&(e[a]=b[c])}),e},G=function(){var b,e=(n||c).position(),f=(n||c).offset(),g=d.widgetPositioning.vertical,h=d.widgetPositioning.horizontal;if(d.widgetParent)b=d.widgetParent.append(o);else if(c.is("input"))b=c.parent().append(o);else{if(d.inline)return void(b=c.append(o));b=c,c.children().first().after(o)}if("auto"===g&&(g=f.top+1.5*o.height()>=a(window).height()+a(window).scrollTop()&&o.height()+c.outerHeight()a(window).width()?"right":"left"),"top"===g?o.addClass("top").removeClass("bottom"):o.addClass("bottom").removeClass("top"),"right"===h?o.addClass("pull-right"):o.removeClass("pull-right"),"relative"!==b.css("position")&&(b=b.parents().filter(function(){return"relative"===a(this).css("position")}).first()),0===b.length)throw new Error("datetimepicker component should be placed within a relative positioned container");o.css({top:"top"===g?"auto":e.top+c.outerHeight(),bottom:"top"===g?e.top+c.outerHeight():"auto",left:"left"===h?b.css("padding-left"):"auto",right:"left"===h?"auto":b.width()-c.outerWidth()})},H=function(a){"dp.change"===a.type&&(a.date&&a.date.isSame(a.oldDate)||!a.date&&!a.oldDate)||c.trigger(a)},I=function(a){o&&(a&&(i=Math.max(p,Math.min(2,i+a))),o.find(".datepicker > div").hide().filter(".datepicker-"+q[i].clsName).show())},J=function(){var b=a("
"),c=l.clone().startOf("w");for(d.calendarWeeks===!0&&b.append(a(""),d.calendarWeeks&&e.append('"),i.push(e)),f="",c.isBefore(l,"M")&&(f+=" old"),c.isAfter(l,"M")&&(f+=" new"),c.isSame(k,"d")&&!m&&(f+=" active"),M(c,"d")||(f+=" disabled"),c.isSame(b(),"d")&&(f+=" today"),(0===c.day()||6===c.day())&&(f+=" weekend"),e.append('"),c.add(1,"d");g.find("tbody").empty().append(i),O(),P()}},R=function(){var b=o.find(".timepicker-hours table"),c=l.clone().startOf("d"),d=[],e=a("");for(l.hour()>11&&!f&&c.hour(12);c.isSame(l,"d")&&(f||l.hour()<12&&c.hour()<12||l.hour()>11);)c.hour()%4===0&&(e=a(""),d.push(e)),e.append('"),c.add(1,"h");b.empty().append(d)},S=function(){for(var b=o.find(".timepicker-minutes table"),c=l.clone().startOf("h"),e=[],f=a(""),g=1===d.stepping?5:d.stepping;l.isSame(c,"h");)c.minute()%(4*g)===0&&(f=a(""),e.push(f)),f.append('"),c.add(g,"m");b.empty().append(e)},T=function(){for(var b=o.find(".timepicker-seconds table"),c=l.clone().startOf("m"),d=[],e=a("");l.isSame(c,"m");)c.second()%20===0&&(e=a(""),d.push(e)),e.append('"),c.add(5,"s");b.empty().append(d)},U=function(){var a=o.find(".timepicker span[data-time-component]");f||o.find(".timepicker [data-action=togglePeriod]").text(k.format("A")),a.filter("[data-time-component=hours]").text(k.format(f?"HH":"hh")),a.filter("[data-time-component=minutes]").text(k.format("mm")),a.filter("[data-time-component=seconds]").text(k.format("ss")),R(),S(),T()},V=function(){o&&(Q(),U())},W=function(a){var b=m?null:k;return a?(a=a.clone().locale(d.locale),1!==d.stepping&&a.minutes(Math.round(a.minutes()/d.stepping)*d.stepping%60).seconds(0),void(M(a)?(k=a,l=k.clone(),e.val(k.format(g)),c.data("date",k.format(g)),V(),m=!1,H({type:"dp.change",date:k.clone(),oldDate:b})):(d.keepInvalid||e.val(m?"":k.format(g)),H({type:"dp.error",date:a})))):(m=!0,e.val(""),c.data("date",""),H({type:"dp.change",date:null,oldDate:b}),void V())},X=function(){var b=!1;return o?(o.find(".collapse").each(function(){var c=a(this).data("collapse");return c&&c.transitioning?(b=!0,!1):!0}),b?j:(n&&n.hasClass("btn")&&n.toggleClass("active"),o.hide(),a(window).off("resize",G),o.off("click","[data-action]"),o.off("mousedown",!1),o.remove(),o=!1,H({type:"dp.hide",date:k.clone()}),j)):j},Y=function(){W(null)},Z={next:function(){l.add(q[i].navStep,q[i].navFnc),Q()},previous:function(){l.subtract(q[i].navStep,q[i].navFnc),Q()},pickerSwitch:function(){I(1)},selectMonth:function(b){var c=a(b.target).closest("tbody").find("span").index(a(b.target));l.month(c),i===p?(W(k.clone().year(l.year()).month(l.month())),d.inline||X()):(I(-1),Q())},selectYear:function(b){var c=parseInt(a(b.target).text(),10)||0;l.year(c),i===p?(W(k.clone().year(l.year())),d.inline||X()):(I(-1),Q())},selectDay:function(b){var c=l.clone();a(b.target).is(".old")&&c.subtract(1,"M"),a(b.target).is(".new")&&c.add(1,"M"),W(c.date(parseInt(a(b.target).text(),10))),y()||d.keepOpen||d.inline||X()},incrementHours:function(){W(k.clone().add(1,"h"))},incrementMinutes:function(){W(k.clone().add(d.stepping,"m"))},incrementSeconds:function(){W(k.clone().add(1,"s"))},decrementHours:function(){W(k.clone().subtract(1,"h"))},decrementMinutes:function(){W(k.clone().subtract(d.stepping,"m"))},decrementSeconds:function(){W(k.clone().subtract(1,"s"))},togglePeriod:function(){W(k.clone().add(k.hours()>=12?-12:12,"h"))},togglePicker:function(b){var c,e=a(b.target),f=e.closest("ul"),g=f.find(".in"),h=f.find(".collapse:not(.in)");if(g&&g.length){if(c=g.data("collapse"),c&&c.transitioning)return;g.collapse?(g.collapse("hide"),h.collapse("show")):(g.removeClass("in"),h.addClass("in")),e.is("span")?e.toggleClass(d.icons.time+" "+d.icons.date):e.find("span").toggleClass(d.icons.time+" "+d.icons.date)}},showPicker:function(){o.find(".timepicker > div:not(.timepicker-picker)").hide(),o.find(".timepicker .timepicker-picker").show()},showHours:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-hours").show()},showMinutes:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-minutes").show()},showSeconds:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-seconds").show()},selectHour:function(b){var c=parseInt(a(b.target).text(),10);f||(k.hours()>=12?12!==c&&(c+=12):12===c&&(c=0)),W(k.clone().hours(c)),Z.showPicker.call(j)},selectMinute:function(b){W(k.clone().minutes(parseInt(a(b.target).text(),10))),Z.showPicker.call(j)},selectSecond:function(b){W(k.clone().seconds(parseInt(a(b.target).text(),10))),Z.showPicker.call(j)},clear:Y,today:function(){W(b())},close:X},$=function(b){return a(b.currentTarget).is(".disabled")?!1:(Z[a(b.currentTarget).data("action")].apply(j,arguments),!1)},_=function(){var c,f={year:function(a){return a.month(0).date(1).hours(0).seconds(0).minutes(0)},month:function(a){return a.date(1).hours(0).seconds(0).minutes(0)},day:function(a){return a.hours(0).seconds(0).minutes(0)},hour:function(a){return a.seconds(0).minutes(0)},minute:function(a){return a.seconds(0)}};return e.prop("disabled")||!d.ignoreReadonly&&e.prop("readonly")||o?j:(d.useCurrent&&m&&(e.is("input")&&0===e.val().trim().length||d.inline)&&(c=b(),"string"==typeof d.useCurrent&&(c=f[d.useCurrent](c)),W(c)),o=E(),J(),N(),o.find(".timepicker-hours").hide(),o.find(".timepicker-minutes").hide(),o.find(".timepicker-seconds").hide(),V(),I(),a(window).on("resize",G),o.on("click","[data-action]",$),o.on("mousedown",!1),n&&n.hasClass("btn")&&n.toggleClass("active"),o.show(),G(),e.is(":focus")||e.focus(),H({type:"dp.show"}),j)},ab=function(){return o?X():_()},bb=function(a){return a=b.isMoment(a)||a instanceof Date?b(a):b(a,h,d.useStrict),a.locale(d.locale),a},cb=function(a){var b,c,e,f,g=null,h=[],i={},k=a.which,l="p";w[k]=l;for(b in w)w.hasOwnProperty(b)&&w[b]===l&&(h.push(b),parseInt(b,10)!==k&&(i[b]=!0));for(b in d.keyBinds)if(d.keyBinds.hasOwnProperty(b)&&"function"==typeof d.keyBinds[b]&&(e=b.split(" "),e.length===h.length&&v[k]===e[e.length-1])){for(f=!0,c=e.length-2;c>=0;c--)if(!(v[e[c]]in i)){f=!1;break}if(f){g=d.keyBinds[b];break}}g&&(g.call(j,o),a.stopPropagation(),a.preventDefault())},db=function(a){w[a.which]="r",a.stopPropagation(),a.preventDefault()},eb=function(b){var c=a(b.target).val().trim(),d=c?bb(c):null;return W(d),b.stopImmediatePropagation(),!1},fb=function(){e.on({change:eb,blur:d.debug?"":X,keydown:cb,keyup:db}),c.is("input")?e.on({focus:_}):n&&(n.on("click",ab),n.on("mousedown",!1))},gb=function(){e.off({change:eb,blur:X,keydown:cb,keyup:db}),c.is("input")?e.off({focus:_}):n&&(n.off("click",ab),n.off("mousedown",!1))},hb=function(b){var c={};return a.each(b,function(){var a=bb(this);a.isValid()&&(c[a.format("YYYY-MM-DD")]=!0)}),Object.keys(c).length?c:!1},ib=function(){var a=d.format||"L LT";g=a.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){var b=k.localeData().longDateFormat(a)||a;return b.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){return k.localeData().longDateFormat(a)||a})}),h=d.extraFormats?d.extraFormats.slice():[],h.indexOf(a)<0&&h.indexOf(g)<0&&h.push(g),f=g.toLowerCase().indexOf("a")<1&&g.indexOf("h")<1,x("y")&&(p=2),x("M")&&(p=1),x("d")&&(p=0),i=Math.max(p,i),m||W(k)};if(j.destroy=function(){X(),gb(),c.removeData("DateTimePicker"),c.removeData("date")},j.toggle=ab,j.show=_,j.hide=X,j.disable=function(){return X(),n&&n.hasClass("btn")&&n.addClass("disabled"),e.prop("disabled",!0),j},j.enable=function(){return n&&n.hasClass("btn")&&n.removeClass("disabled"),e.prop("disabled",!1),j},j.ignoreReadonly=function(a){if(0===arguments.length)return d.ignoreReadonly;if("boolean"!=typeof a)throw new TypeError("ignoreReadonly () expects a boolean parameter");return d.ignoreReadonly=a,j},j.options=function(b){if(0===arguments.length)return a.extend(!0,{},d);if(!(b instanceof Object))throw new TypeError("options() options parameter should be an object");return a.extend(!0,d,b),a.each(d,function(a,b){if(void 0===j[a])throw new TypeError("option "+a+" is not recognized!");j[a](b)}),j},j.date=function(a){if(0===arguments.length)return m?null:k.clone();if(!(null===a||"string"==typeof a||b.isMoment(a)||a instanceof Date))throw new TypeError("date() parameter must be one of [null, string, moment or Date]");return W(null===a?null:bb(a)),j},j.format=function(a){if(0===arguments.length)return d.format;if("string"!=typeof a&&("boolean"!=typeof a||a!==!1))throw new TypeError("format() expects a sting or boolean:false parameter "+a);return d.format=a,g&&ib(),j},j.dayViewHeaderFormat=function(a){if(0===arguments.length)return d.dayViewHeaderFormat;if("string"!=typeof a)throw new TypeError("dayViewHeaderFormat() expects a string parameter");return d.dayViewHeaderFormat=a,j},j.extraFormats=function(a){if(0===arguments.length)return d.extraFormats;if(a!==!1&&!(a instanceof Array))throw new TypeError("extraFormats() expects an array or false parameter");return d.extraFormats=a,h&&ib(),j},j.disabledDates=function(b){if(0===arguments.length)return d.disabledDates?a.extend({},d.disabledDates):d.disabledDates;if(!b)return d.disabledDates=!1,V(),j;if(!(b instanceof Array))throw new TypeError("disabledDates() expects an array parameter");return d.disabledDates=hb(b),d.enabledDates=!1,V(),j},j.enabledDates=function(b){if(0===arguments.length)return d.enabledDates?a.extend({},d.enabledDates):d.enabledDates;if(!b)return d.enabledDates=!1,V(),j;if(!(b instanceof Array))throw new TypeError("enabledDates() expects an array parameter");return d.enabledDates=hb(b),d.disabledDates=!1,V(),j},j.daysOfWeekDisabled=function(a){if(0===arguments.length)return d.daysOfWeekDisabled.splice(0);if(!(a instanceof Array))throw new TypeError("daysOfWeekDisabled() expects an array parameter");return d.daysOfWeekDisabled=a.reduce(function(a,b){return b=parseInt(b,10),b>6||0>b||isNaN(b)?a:(-1===a.indexOf(b)&&a.push(b),a)},[]).sort(),V(),j},j.maxDate=function(a){if(0===arguments.length)return d.maxDate?d.maxDate.clone():d.maxDate;if("boolean"==typeof a&&a===!1)return d.maxDate=!1,V(),j;"string"==typeof a&&("now"===a||"moment"===a)&&(a=b());var c=bb(a);if(!c.isValid())throw new TypeError("maxDate() Could not parse date parameter: "+a);if(d.minDate&&c.isBefore(d.minDate))throw new TypeError("maxDate() date parameter is before options.minDate: "+c.format(g));return d.maxDate=c,d.maxDate.isBefore(a)&&W(d.maxDate),l.isAfter(c)&&(l=c.clone()),V(),j},j.minDate=function(a){if(0===arguments.length)return d.minDate?d.minDate.clone():d.minDate;if("boolean"==typeof a&&a===!1)return d.minDate=!1,V(),j;"string"==typeof a&&("now"===a||"moment"===a)&&(a=b());var c=bb(a);if(!c.isValid())throw new TypeError("minDate() Could not parse date parameter: "+a);if(d.maxDate&&c.isAfter(d.maxDate))throw new TypeError("minDate() date parameter is after options.maxDate: "+c.format(g));return d.minDate=c,d.minDate.isAfter(a)&&W(d.minDate),l.isBefore(c)&&(l=c.clone()),V(),j},j.defaultDate=function(a){if(0===arguments.length)return d.defaultDate?d.defaultDate.clone():d.defaultDate;if(!a)return d.defaultDate=!1,j;"string"==typeof a&&("now"===a||"moment"===a)&&(a=b());var c=bb(a);if(!c.isValid())throw new TypeError("defaultDate() Could not parse date parameter: "+a);if(!M(c))throw new TypeError("defaultDate() date passed is invalid according to component setup validations");return d.defaultDate=c,d.defaultDate&&""===e.val().trim()&&void 0===e.attr("placeholder")&&W(d.defaultDate),j},j.locale=function(a){if(0===arguments.length)return d.locale;if(!b.localeData(a))throw new TypeError("locale() locale "+a+" is not loaded from moment locales!");return d.locale=a,k.locale(d.locale),l.locale(d.locale),g&&ib(),o&&(X(),_()),j},j.stepping=function(a){return 0===arguments.length?d.stepping:(a=parseInt(a,10),(isNaN(a)||1>a)&&(a=1),d.stepping=a,j)},j.useCurrent=function(a){var b=["year","month","day","hour","minute"];if(0===arguments.length)return d.useCurrent;if("boolean"!=typeof a&&"string"!=typeof a)throw new TypeError("useCurrent() expects a boolean or string parameter");if("string"==typeof a&&-1===b.indexOf(a.toLowerCase()))throw new TypeError("useCurrent() expects a string parameter of "+b.join(", "));return d.useCurrent=a,j},j.collapse=function(a){if(0===arguments.length)return d.collapse;if("boolean"!=typeof a)throw new TypeError("collapse() expects a boolean parameter");return d.collapse===a?j:(d.collapse=a,o&&(X(),_()),j)},j.icons=function(b){if(0===arguments.length)return a.extend({},d.icons);if(!(b instanceof Object))throw new TypeError("icons() expects parameter to be an Object");return a.extend(d.icons,b),o&&(X(),_()),j},j.useStrict=function(a){if(0===arguments.length)return d.useStrict;if("boolean"!=typeof a)throw new TypeError("useStrict() expects a boolean parameter");return d.useStrict=a,j},j.sideBySide=function(a){if(0===arguments.length)return d.sideBySide;if("boolean"!=typeof a)throw new TypeError("sideBySide() expects a boolean parameter");return d.sideBySide=a,o&&(X(),_()),j},j.viewMode=function(a){if(0===arguments.length)return d.viewMode;if("string"!=typeof a)throw new TypeError("viewMode() expects a string parameter");if(-1===r.indexOf(a))throw new TypeError("viewMode() parameter must be one of ("+r.join(", ")+") value");return d.viewMode=a,i=Math.max(r.indexOf(a),p),I(),j},j.toolbarPlacement=function(a){if(0===arguments.length)return d.toolbarPlacement;if("string"!=typeof a)throw new TypeError("toolbarPlacement() expects a string parameter");if(-1===u.indexOf(a))throw new TypeError("toolbarPlacement() parameter must be one of ("+u.join(", ")+") value");return d.toolbarPlacement=a,o&&(X(),_()),j},j.widgetPositioning=function(b){if(0===arguments.length)return a.extend({},d.widgetPositioning);if("[object Object]"!=={}.toString.call(b))throw new TypeError("widgetPositioning() expects an object variable");if(b.horizontal){if("string"!=typeof b.horizontal)throw new TypeError("widgetPositioning() horizontal variable must be a string");if(b.horizontal=b.horizontal.toLowerCase(),-1===t.indexOf(b.horizontal))throw new TypeError("widgetPositioning() expects horizontal parameter to be one of ("+t.join(", ")+")");d.widgetPositioning.horizontal=b.horizontal}if(b.vertical){if("string"!=typeof b.vertical)throw new TypeError("widgetPositioning() vertical variable must be a string");if(b.vertical=b.vertical.toLowerCase(),-1===s.indexOf(b.vertical))throw new TypeError("widgetPositioning() expects vertical parameter to be one of ("+s.join(", ")+")");d.widgetPositioning.vertical=b.vertical}return V(),j},j.calendarWeeks=function(a){if(0===arguments.length)return d.calendarWeeks;if("boolean"!=typeof a)throw new TypeError("calendarWeeks() expects parameter to be a boolean value");return d.calendarWeeks=a,V(),j},j.showTodayButton=function(a){if(0===arguments.length)return d.showTodayButton;if("boolean"!=typeof a)throw new TypeError("showTodayButton() expects a boolean parameter");return d.showTodayButton=a,o&&(X(),_()),j},j.showClear=function(a){if(0===arguments.length)return d.showClear;if("boolean"!=typeof a)throw new TypeError("showClear() expects a boolean parameter");return d.showClear=a,o&&(X(),_()),j},j.widgetParent=function(b){if(0===arguments.length)return d.widgetParent;if("string"==typeof b&&(b=a(b)),null!==b&&"string"!=typeof b&&!(b instanceof a))throw new TypeError("widgetParent() expects a string or a jQuery object parameter");return d.widgetParent=b,o&&(X(),_()),j},j.keepOpen=function(a){if(0===arguments.length)return d.keepOpen;if("boolean"!=typeof a)throw new TypeError("keepOpen() expects a boolean parameter");return d.keepOpen=a,j},j.inline=function(a){if(0===arguments.length)return d.inline;if("boolean"!=typeof a)throw new TypeError("inline() expects a boolean parameter");return d.inline=a,j},j.clear=function(){return Y(),j},j.keyBinds=function(a){return d.keyBinds=a,j},j.debug=function(a){if("boolean"!=typeof a)throw new TypeError("debug() expects a boolean parameter");return d.debug=a,j},j.showClose=function(a){if(0===arguments.length)return d.showClose;if("boolean"!=typeof a)throw new TypeError("showClose() expects a boolean parameter");return d.showClose=a,j},j.keepInvalid=function(a){if(0===arguments.length)return d.keepInvalid;if("boolean"!=typeof a)throw new TypeError("keepInvalid() expects a boolean parameter");return d.keepInvalid=a,j},j.datepickerInput=function(a){if(0===arguments.length)return d.datepickerInput;if("string"!=typeof a)throw new TypeError("datepickerInput() expects a string parameter");return d.datepickerInput=a,j},c.is("input"))e=c;else if(e=c.find(d.datepickerInput),0===e.size())e=c.find("input");else if(!e.is("input"))throw new Error('CSS class "'+d.datepickerInput+'" cannot be applied to non input element');if(c.hasClass("input-group")&&(n=c.find(0===c.find(".datepickerbutton").size()?'[class^="input-group-"]':".datepickerbutton")),!d.inline&&!e.is("input"))throw new Error("Could not initialize DateTimePicker without an input element");return a.extend(!0,d,F()),j.options(d),ib(),fb(),e.prop("disabled")&&j.disable(),e.is("input")&&0!==e.val().trim().length?W(bb(e.val().trim())):d.defaultDate&&void 0===e.attr("placeholder")&&W(d.defaultDate),d.inline&&_(),j};a.fn.datetimepicker=function(b){return this.each(function(){var d=a(this);d.data("DateTimePicker")||(b=a.extend(!0,{},a.fn.datetimepicker.defaults,b),d.data("DateTimePicker",c(d,b)))})},a.fn.datetimepicker.defaults={format:!1,dayViewHeaderFormat:"MMMM YYYY",extraFormats:!1,stepping:1,minDate:!1,maxDate:!1,useCurrent:!0,collapse:!0,locale:b.locale(),defaultDate:!1,disabledDates:!1,enabledDates:!1,icons:{time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down",previous:"glyphicon glyphicon-chevron-left",next:"glyphicon glyphicon-chevron-right",today:"glyphicon glyphicon-screenshot",clear:"glyphicon glyphicon-trash",close:"glyphicon glyphicon-remove"},useStrict:!1,sideBySide:!1,daysOfWeekDisabled:[],calendarWeeks:!1,viewMode:"days",toolbarPlacement:"default",showTodayButton:!1,showClear:!1,showClose:!1,widgetPositioning:{horizontal:"auto",vertical:"auto"},widgetParent:null,ignoreReadonly:!1,keepOpen:!1,inline:!1,keepInvalid:!1,datepickerInput:".datepickerinput",keyBinds:{up:function(a){if(a){var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().subtract(7,"d"):c.clone().add(1,"m"))}},down:function(a){if(!a)return void this.show();var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().add(7,"d"):c.clone().subtract(1,"m"))},"control up":function(a){if(a){var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().subtract(1,"y"):c.clone().add(1,"h"))}},"control down":function(a){if(a){var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().add(1,"y"):c.clone().subtract(1,"h"))}},left:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().subtract(1,"d"))}},right:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().add(1,"d"))}},pageUp:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().subtract(1,"M"))}},pageDown:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().add(1,"M"))}},enter:function(){this.hide()},escape:function(){this.hide()},"control space":function(a){a.find(".timepicker").is(":visible")&&a.find('.btn[data-action="togglePeriod"]').click()},t:function(){this.date(b())},"delete":function(){this.clear()}},debug:!1}}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap-datetimepicker/datetimepickerDirective.js b/LiveChat/ClientComponents/bootstrap-datetimepicker/datetimepickerDirective.js new file mode 100644 index 0000000..99193ba --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-datetimepicker/datetimepickerDirective.js @@ -0,0 +1,14 @@ +app.directive('dDatepicker', function($timeout, $parse) { + return { + link: function($scope, element, $attrs) { + return $timeout(function() { + var ngModelGetter = $parse($attrs['ngModel']); + return $(element).datetimepicker().on('dp.change', function(event) { + $scope.$apply(function() { + return ngModelGetter.assign($scope, event.target.value); + }); + }); + }); + } + }; +}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap-growl/bootstrap-growl.min.js b/LiveChat/ClientComponents/bootstrap-growl/bootstrap-growl.min.js new file mode 100644 index 0000000..df16dd1 --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-growl/bootstrap-growl.min.js @@ -0,0 +1,2 @@ +/* Project: Bootstrap Growl - v2.0.1 | Author: Mouse0270 aka Robert McIntosh | License: MIT License | Website: https://github.com/mouse0270/bootstrap-growl */ +(function(e,t,n,r){var i="growl",s="plugin_"+i,o={element:"body",type:"info",allow_dismiss:true,placement:{from:"top",align:"right"},offset:20,spacing:10,z_index:1031,delay:5e3,timer:1e3,url_target:"_blank",mouse_over:false,animate:{enter:"animated fadeInDown",exit:"animated fadeOutUp"},onShow:null,onShown:null,onHide:null,onHidden:null,icon_type:"class",template:''};var u=function(t,n){o=e.extend(true,{},o,n)},a=function(t){if(!t){e('[data-growl="container"]').find('[data-growl="dismiss"]').trigger("click")}else{e('[data-growl="container"][data-growl-position="'+t+'"]').find('[data-growl="dismiss"]').trigger("click")}},f=function(t,n,r){var n={content:{message:typeof n=="object"?n.message:n,title:n.title?n.title:null,icon:n.icon?n.icon:null,url:n.url?n.url:null}};r=e.extend(true,{},n,r);this.settings=e.extend(true,{},o,r);plugin=this;l(r,this.settings,plugin);this.$template=$template},l=function(e,t,n){var r={settings:t,element:t.element,template:t.template};if(typeof t.offset=="number"){t.offset={x:t.offset,y:t.offset}}$template=c(r);h($template,r.settings);p($template,r.settings);d($template,r.settings,n)},c=function(t){var n=e(t.settings.template);n.addClass("alert-"+t.settings.type);n.attr("data-growl-position",t.settings.placement.from+"-"+t.settings.placement.align);n.find('[data-growl="dismiss"]').css("display","none");n.removeClass("alert-dismissable");if(t.settings.allow_dismiss){n.addClass("alert-dismissable");n.find('[data-growl="dismiss"]').css("display","block")}return n},h=function(e,t){e.find('[data-growl="dismiss"]').css({"z-index":t.z_index-1>=1?t.z_index-1:1});if(t.content.icon){if(t.icon_type.toLowerCase()=="class"){e.find('[data-growl="icon"]').addClass(t.content.icon)}else{if(e.find('[data-growl="icon"]').is("img")){e.find('[data-growl="icon"]').attr("src",t.content.icon)}else{e.find('[data-growl="icon"]').append('')}}}if(t.content.title){e.find('[data-growl="title"]').html(t.content.title)}if(t.content.message){e.find('[data-growl="message"]').html(t.content.message)}if(t.content.url){e.find('[data-growl="url"]').attr("href",t.content.url).attr("target",t.url_target);e.find('[data-growl="url"]').css({position:"absolute",top:0,left:0,width:"100%",height:"100%","z-index":t.z_index-2>=1?t.z_index-2:1})}},p=function(t,n){var r=n.offset.y,i={position:n.element==="body"?"fixed":"absolute",margin:0,"z-index":n.z_index,display:"inline-block"},s=false;e('[data-growl-position="'+n.placement.from+"-"+n.placement.align+'"]').each(function(){return r=Math.max(r,parseInt(e(this).css(n.placement.from))+e(this).outerHeight()+n.spacing)});i[n.placement.from]=r+"px";t.css(i);if(n.onShow){n.onShow(event)}e(n.element).append(t);switch(n.placement.align){case"center":t.css({left:"50%",marginLeft:-(t.outerWidth()/2)+"px"});break;case"left":t.css("left",n.offset.x+"px");break;case"right":t.css("right",n.offset.x+"px");break}t.addClass("growl-animated");t.one("webkitAnimationStart oanimationstart MSAnimationStart animationstart",function(e){s=true});t.one("webkitAnimationEnd oanimationend MSAnimationEnd animationend",function(e){if(n.onShown){n.onShown(e)}});setTimeout(function(){if(!s){if(n.onShown){n.onShown(event)}}},600)},d=function(e,t,n){e.addClass(t.animate.enter);e.find('[data-growl="dismiss"]').on("click",function(){n.close()});e.on("mouseover",function(t){e.addClass("hovering")}).on("mouseout",function(){e.removeClass("hovering")});if(t.delay>=1){e.data("growl-delay",t.delay);var r=setInterval(function(){var i=parseInt(e.data("growl-delay"))-t.timer;if(!e.hasClass("hovering")&&t.mouse_over=="pause"||t.mouse_over!="pause"){e.data("growl-delay",i)}if(i<=0){clearInterval(r);n.close()}},t.timer)}};f.prototype={update:function(e,t){switch(e){case"icon":if(this.settings.icon_type.toLowerCase()=="class"){this.$template.find('[data-growl="icon"]').removeClass(this.settings.content.icon);this.$template.find('[data-growl="icon"]').addClass(t)}else{if(this.$template.find('[data-growl="icon"]').is("img")){this.$template.find('[data-growl="icon"]')}else{this.$template.find('[data-growl="icon"]').find("img").attr().attr("src",t)}}break;case"url":this.$template.find('[data-growl="url"]').attr("href",t);break;case"type":this.$template.removeClass("alert-"+this.settings.type);this.$template.addClass("alert-"+t);break;default:this.$template.find('[data-growl="'+e+'"]').html(t)}return this},close:function(){var t=this.$template,n=this.settings,r=t.css(n.placement.from),i=false;if(n.onHide){n.onHide(event)}t.addClass(this.settings.animate.exit);t.nextAll('[data-growl-position="'+this.settings.placement.from+"-"+this.settings.placement.align+'"]').each(function(){e(this).css(n.placement.from,r);r=parseInt(r)+n.spacing+e(this).outerHeight()});t.one("webkitAnimationStart oanimationstart MSAnimationStart animationstart",function(e){i=true});t.one("webkitAnimationEnd oanimationend MSAnimationEnd animationend",function(t){e(this).remove();if(n.onHidden){n.onHidden(t)}});setTimeout(function(){if(!i){t.remove();if(n.onHidden){n.onHidden(event)}}},100);return this}};e.growl=function(e,t){if(e==false&&t.command=="closeAll"){a(t.position);return false}else if(e==false){u(this,t);return false}var n=new f(this,e,t);return n}})(jQuery,window,document) diff --git a/LiveChat/ClientComponents/bootstrap-select/angular-bootstrap-select.min.js b/LiveChat/ClientComponents/bootstrap-select/angular-bootstrap-select.min.js new file mode 100644 index 0000000..d3581e1 --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-select/angular-bootstrap-select.min.js @@ -0,0 +1 @@ +angular.module("angular-bootstrap-select.extra",[]).directive("toggle",function(){return{restrict:"A",link:function(a,b){var c=b.parent();b.bind("click",function(){c.toggleClass("open")}),b.next().find("li").bind("click",function(){c.toggleClass("open")})}}}),angular.module("angular-bootstrap-select",[]).directive("selectpicker",function(){return{restrict:"CA",require:"?ngModel",compile:function(a){return a.selectpicker(),function(a,b,c,d){d.$render=function(){b.val(d.$viewValue||"").selectpicker("render")},d.$viewValue=b.val()}}}}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.css b/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.css new file mode 100644 index 0000000..76f2ab1 --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap-select v1.7.2 (http://silviomoreto.github.io/bootstrap-select) + * + * Copyright 2013-2015 bootstrap-select + * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) + */.bootstrap-select{width:220px \0}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px}.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;z-index:1035;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1036}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%}select.bs-select-hidden,select.selectpicker{display:none!important}select.mobile-device{position:absolute!important;top:0;left:0;display:block!important;width:100%;height:100%!important;opacity:0} \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.js b/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.js new file mode 100644 index 0000000..63356ae --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap-select v1.7.2 (http://silviomoreto.github.io/bootstrap-select) + * + * Copyright 2013-2015 bootstrap-select + * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) + */ +!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(){!function(a){"use strict";function b(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b.replace(this.re,this.ch)}),b}function c(a){var b={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},c="(?:"+Object.keys(b).join("|")+")",d=new RegExp(c),e=new RegExp(c,"g"),f=null==a?"":""+a;return d.test(f)?f.replace(e,function(a){return b[a]}):f}function d(b,c){var d=arguments,f=b,g=c;[].shift.apply(d);var h,i=this.each(function(){var b=a(this);if(b.is("select")){var c=b.data("selectpicker"),i="object"==typeof f&&f;if(c){if(i)for(var j in i)i.hasOwnProperty(j)&&(c.options[j]=i[j])}else{var k=a.extend({},e.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),i);b.data("selectpicker",c=new e(this,k,g))}"string"==typeof f&&(h=c[f]instanceof Function?c[f].apply(c,d):c.options[f])}});return"undefined"!=typeof h?h:i}String.prototype.includes||!function(){var a={}.toString,b=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),c="".indexOf,d=function(b){if(null==this)throw TypeError();var d=String(this);if(b&&"[object RegExp]"==a.call(b))throw TypeError();var e=d.length,f=String(b),g=f.length,h=arguments.length>1?arguments[1]:void 0,i=h?Number(h):0;i!=i&&(i=0);var j=Math.min(Math.max(i,0),e);return g+j>e?!1:-1!=c.call(d,f,i)};b?b(String.prototype,"includes",{value:d,configurable:!0,writable:!0}):String.prototype.includes=d}(),String.prototype.startsWith||!function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),b={}.toString,c=function(a){if(null==this)throw TypeError();var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw TypeError();var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j'+this.options.header+"":"",g=this.options.liveSearch?'":"",h=this.multiple&&this.options.actionsBox?'
":"",i=this.multiple&&this.options.doneButton?'
":"",j='
";return a(j)},createView:function(){var a=this.createDropdown(),b=this.createLi();return a.find("ul")[0].innerHTML=b,a},reloadLi:function(){this.destroyLi();var a=this.createLi();this.$menuInner[0].innerHTML=a},destroyLi:function(){this.$menu.find("li").remove()},createLi:function(){var d=this,e=[],f=0,g=document.createElement("option"),h=-1,i=function(a,b,c,d){return""+a+""},j=function(a,e,f,g){return'"+a+''};if(this.options.title&&!this.multiple&&(h--,!this.$element.find(".bs-title-option").length)){var k=this.$element[0];g.className="bs-title-option",g.appendChild(document.createTextNode(this.options.title)),g.value="",k.insertBefore(g,k.firstChild),null===k.options[k.selectedIndex].getAttribute("selected")&&(g.selected=!0)}return this.$element.find("option").each(function(b){var c=a(this);if(h++,!c.hasClass("bs-title-option")){var g=this.className||"",k=this.style.cssText,l=c.data("content")?c.data("content"):c.html(),m=c.data("tokens")?c.data("tokens"):null,n="undefined"!=typeof c.data("subtext")?''+c.data("subtext")+"":"",o="undefined"!=typeof c.data("icon")?' ':"",p=this.disabled||"OPTGROUP"===this.parentElement.tagName&&this.parentElement.disabled;if(""!==o&&p&&(o=""+o+""),d.options.hideDisabled&&p)return void h--;if(c.data("content")||(l=o+''+l+n+""),"OPTGROUP"===this.parentElement.tagName&&c.data("divider")!==!0){if(0===c.index()){f+=1;var q=this.parentElement.label,r="undefined"!=typeof c.parent().data("subtext")?''+c.parent().data("subtext")+"":"",s=c.parent().data("icon")?' ':"",t=" "+this.parentElement.className||"";q=s+''+q+r+"",0!==b&&e.length>0&&(h++,e.push(i("",null,"divider",f+"div"))),h++,e.push(i(q,null,"dropdown-header"+t,f))}e.push(i(j(l,"opt "+g+t,k,m),b,"",f))}else c.data("divider")===!0?e.push(i("",b,"divider")):c.data("hidden")===!0?e.push(i(j(l,g,k,m),b,"hidden is-hidden")):(this.previousElementSibling&&"OPTGROUP"===this.previousElementSibling.tagName&&(h++,e.push(i("",null,"divider",f+"div"))),e.push(i(j(l,g,k,m),b)));d.liObj[b]=h}}),this.multiple||0!==this.$element.find("option:selected").length||this.options.title||this.$element.find("option").eq(0).prop("selected",!0).attr("selected","selected"),e.join("")},findLis:function(){return null==this.$lis&&(this.$lis=this.$menu.find("li")),this.$lis},render:function(b){var c,d=this;b!==!1&&this.$element.find("option").each(function(a){var b=d.findLis().eq(d.liObj[a]);d.setDisabled(a,this.disabled||"OPTGROUP"===this.parentElement.tagName&&this.parentElement.disabled,b),d.setSelected(a,this.selected,b)}),this.tabIndex();var e=this.$element.find("option").map(function(){if(this.selected){if(d.options.hideDisabled&&(this.disabled||"OPTGROUP"===this.parentElement.tagName&&this.parentElement.disabled))return!1;var b,c=a(this),e=c.data("icon")&&d.options.showIcon?' ':"";return b=d.options.showSubtext&&c.data("subtext")&&!d.multiple?' '+c.data("subtext")+"":"","undefined"!=typeof c.attr("title")?c.attr("title"):c.data("content")&&d.options.showContent?c.data("content"):e+c.html()+b}}).toArray(),f=this.multiple?e.join(this.options.multipleSeparator):e[0];if(this.multiple&&this.options.selectedTextFormat.indexOf("count")>-1){var g=this.options.selectedTextFormat.split(">");if(g.length>1&&e.length>g[1]||1==g.length&&e.length>=2){c=this.options.hideDisabled?", [disabled]":"";var h=this.$element.find("option").not('[data-divider="true"], [data-hidden="true"]'+c).length,i="function"==typeof this.options.countSelectedText?this.options.countSelectedText(e.length,h):this.options.countSelectedText;f=i.replace("{0}",e.length.toString()).replace("{1}",h.toString())}}void 0==this.options.title&&(this.options.title=this.$element.attr("title")),"static"==this.options.selectedTextFormat&&(f=this.options.title),f||(f="undefined"!=typeof this.options.title?this.options.title:this.options.noneSelectedText),this.$button.attr("title",a.trim(f.replace(/<[^>]*>?/g,""))),this.$button.children(".filter-option").html(f),this.$element.trigger("rendered.bs.select")},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,""));var c=a?a:this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(b){if(b||this.options.size!==!1&&!this.sizeInfo){var c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("ul"),f=document.createElement("li"),g=document.createElement("li"),h=document.createElement("a"),i=document.createElement("span"),j=this.options.header?this.$menu.find(".popover-title")[0].cloneNode(!0):null,k=this.options.liveSearch?document.createElement("div"):null,l=this.options.actionsBox&&this.multiple?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,m=this.options.doneButton&&this.multiple?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null;if(i.className="text",c.className=this.$menu[0].parentNode.className+" open",d.className="dropdown-menu open",e.className="dropdown-menu inner",f.className="divider",i.appendChild(document.createTextNode("Inner text")),h.appendChild(i),g.appendChild(h),e.appendChild(g),e.appendChild(f),j&&d.appendChild(j),k){var n=document.createElement("span");k.className="bs-searchbox",n.className="form-control",k.appendChild(n),d.appendChild(k)}l&&d.appendChild(l),d.appendChild(e),m&&d.appendChild(m),c.appendChild(d),document.body.appendChild(c);var o=h.offsetHeight,p=j?j.offsetHeight:0,q=k?k.offsetHeight:0,r=l?l.offsetHeight:0,s=m?m.offsetHeight:0,t=a(f).outerHeight(!0),u=getComputedStyle?getComputedStyle(d):!1,v=u?a(d):null,w=parseInt(u?u.paddingTop:v.css("paddingTop"))+parseInt(u?u.paddingBottom:v.css("paddingBottom"))+parseInt(u?u.borderTopWidth:v.css("borderTopWidth"))+parseInt(u?u.borderBottomWidth:v.css("borderBottomWidth")),x=w+parseInt(u?u.marginTop:v.css("marginTop"))+parseInt(u?u.marginBottom:v.css("marginBottom"))+2;document.body.removeChild(c),this.sizeInfo={liHeight:o,headerHeight:p,searchHeight:q,actionsHeight:r,doneButtonHeight:s,dividerHeight:t,menuPadding:w,menuExtras:x}}},setSize:function(){this.findLis(),this.liHeight();var b,c,d,e,f=this,g=this.$menu,h=this.$menuInner,i=a(window),j=this.$newElement[0].offsetHeight,k=this.sizeInfo.liHeight,l=this.sizeInfo.headerHeight,m=this.sizeInfo.searchHeight,n=this.sizeInfo.actionsHeight,o=this.sizeInfo.doneButtonHeight,p=this.sizeInfo.dividerHeight,q=this.sizeInfo.menuPadding,r=this.sizeInfo.menuExtras,s=this.options.hideDisabled?".disabled":"",t=function(){d=f.$newElement.offset().top-i.scrollTop(),e=i.height()-d-j};if(t(),this.options.header&&g.css("padding-top",0),"auto"===this.options.size){var u=function(){var i,j=function(b,c){return function(d){return c?d.classList?d.classList.contains(b):a(d).hasClass(b):!(d.classList?d.classList.contains(b):a(d).hasClass(b))}},p=f.$menuInner[0].getElementsByTagName("li"),s=Array.prototype.filter?Array.prototype.filter.call(p,j("hidden",!1)):f.$lis.not(".hidden"),u=Array.prototype.filter?Array.prototype.filter.call(s,j("dropdown-header",!0)):s.filter(".dropdown-header");t(),b=e-r,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&f.$newElement.toggleClass("dropup",d>e&&c>b-r),f.$newElement.hasClass("dropup")&&(b=d-r),i=s.length+u.length>3?3*k+r-2:0,g.css({"max-height":b+"px",overflow:"hidden","min-height":i+l+m+n+o+"px"}),h.css({"max-height":b-l-m-n-o-q+"px","overflow-y":"auto","min-height":Math.max(i-q,0)+"px"})};u(),this.$searchbox.off("input.getSize propertychange.getSize").on("input.getSize propertychange.getSize",u),i.off("resize.getSize scroll.getSize").on("resize.getSize scroll.getSize",u)}else if(this.options.size&&"auto"!=this.options.size&&this.$lis.not(s).length>this.options.size){var v=this.$lis.not(".divider").not(s).children().slice(0,this.options.size).last().parent().index(),w=this.$lis.slice(0,v+1).filter(".divider").length;b=k*this.options.size+w*p+q,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&this.$newElement.toggleClass("dropup",d>e&&c>b-r),g.css({"max-height":b+l+m+n+o+"px",overflow:"hidden","min-height":""}),h.css({"max-height":b-q+"px","overflow-y":"auto","min-height":""})}},setWidth:function(){if("auto"===this.options.width){this.$menu.css("min-width","0");var a=this.$menu.parent().clone().appendTo("body"),b=this.options.container?this.$newElement.clone().appendTo("body"):a,c=a.children(".dropdown-menu").outerWidth(),d=b.css("width","auto").children("button").outerWidth();a.remove(),b.remove(),this.$newElement.css("width",Math.max(c,d)+"px")}else"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width",""));this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement.removeClass("fit-width")},selectPosition:function(){var b,c,d=this,e="
",f=a(e),g=function(a){f.addClass(a.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass("dropup",a.hasClass("dropup")),b=a.offset(),c=a.hasClass("dropup")?0:a[0].offsetHeight,f.css({top:b.top+c,left:b.left,width:a[0].offsetWidth,position:"absolute"})};this.$newElement.on("click",function(){d.isDisabled()||(g(a(this)),f.appendTo(d.options.container),f.toggleClass("open",!a(this).hasClass("open")),f.append(d.$menu))}),a(window).on("resize scroll",function(){g(d.$newElement)}),this.$element.on("hide.bs.select",function(){d.$menu.data("height",d.$menu.height()),f.detach()})},setSelected:function(a,b,c){if(!c)var c=this.findLis().eq(this.liObj[a]);c.toggleClass("selected",b)},setDisabled:function(a,b,c){if(!c)var c=this.findLis().eq(this.liObj[a]);b?c.addClass("disabled").children("a").attr("href","#").attr("tabindex",-1):c.removeClass("disabled").children("a").removeAttr("href").attr("tabindex",0)},isDisabled:function(){return this.$element[0].disabled},checkDisabled:function(){var a=this;this.isDisabled()?(this.$newElement.addClass("disabled"),this.$button.addClass("disabled").attr("tabindex",-1)):(this.$button.hasClass("disabled")&&(this.$newElement.removeClass("disabled"),this.$button.removeClass("disabled")),-1!=this.$button.attr("tabindex")||this.$element.data("tabindex")||this.$button.removeAttr("tabindex")),this.$button.click(function(){return!a.isDisabled()})},tabIndex:function(){this.$element.is("[tabindex]")&&(this.$element.data("tabindex",this.$element.attr("tabindex")),this.$button.attr("tabindex",this.$element.data("tabindex")))},clickListener:function(){var b=this,c=a(document);this.$newElement.on("touchstart.dropdown",".dropdown-menu",function(a){a.stopPropagation()}),c.data("spaceSelect",!1),this.$button.on("keyup",function(a){/(32)/.test(a.keyCode.toString(10))&&c.data("spaceSelect")&&(a.preventDefault(),c.data("spaceSelect",!1))}),this.$newElement.on("click",function(){b.setSize(),b.$element.on("shown.bs.select",function(){if(b.options.liveSearch||b.multiple){if(!b.multiple){var a=b.liObj[b.$element[0].selectedIndex];if("number"!=typeof a)return;var c=b.$lis.eq(a)[0].offsetTop-b.$menuInner[0].offsetTop;c=c-b.$menuInner[0].offsetHeight/2+b.sizeInfo.liHeight/2,b.$menuInner[0].scrollTop=c}}else b.$menu.find(".selected a").focus()})}),this.$menu.on("click","li a",function(c){var d=a(this),e=d.parent().data("originalIndex"),f=b.$element.val(),g=b.$element.prop("selectedIndex");if(b.multiple&&c.stopPropagation(),c.preventDefault(),!b.isDisabled()&&!d.parent().hasClass("disabled")){var h=b.$element.find("option"),i=h.eq(e),j=i.prop("selected"),k=i.parent("optgroup"),l=b.options.maxOptions,m=k.data("maxOptions")||!1;if(b.multiple){if(i.prop("selected",!j),b.setSelected(e,!j),d.blur(),l!==!1||m!==!1){var n=l
');q[2]&&(r=r.replace("{var}",q[2][l>1?0:1]),s=s.replace("{var}",q[2][m>1?0:1])),i.prop("selected",!1),b.$menu.append(t),l&&n&&(t.append(a("
"+r+"
")),b.$element.trigger("maxReached.bs.select")),m&&o&&(t.append(a("
"+s+"
")),b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(e,!1)},10),t.delay(750).fadeOut(300,function(){a(this).remove()})}}}else h.prop("selected",!1),i.prop("selected",!0),b.$menu.find(".selected").removeClass("selected"),b.setSelected(e,!0);b.multiple?b.options.liveSearch&&b.$searchbox.focus():b.$button.focus(),(f!=b.$element.val()&&b.multiple||g!=b.$element.prop("selectedIndex")&&!b.multiple)&&(b.$element.change(),b.$element.trigger("changed.bs.select",[e,i.prop("selected"),j]))}}),this.$menu.on("click","li.disabled a, .popover-title, .popover-title :not(.close)",function(c){c.currentTarget==this&&(c.preventDefault(),c.stopPropagation(),b.options.liveSearch&&!a(c.target).hasClass("close")?b.$searchbox.focus():b.$button.focus())}),this.$menu.on("click","li.divider, li.dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click",".popover-title .close",function(){b.$button.click()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).hasClass("bs-select-all")?b.selectAll():b.deselectAll(),b.$element.change()}),this.$element.change(function(){b.render(!1)})},liveSearchListener:function(){var d=this,e=a('
  • ');this.$newElement.on("click.dropdown.data-api touchstart.dropdown.data-api",function(){d.$menuInner.find(".active").removeClass("active"),d.$searchbox.val()&&(d.$searchbox.val(""),d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove()),d.multiple||d.$menuInner.find(".selected").addClass("active"),setTimeout(function(){d.$searchbox.focus()},10)}),this.$searchbox.on("click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){if(d.$searchbox.val()){var f=d.$lis.not(".is-hidden").removeClass("hidden").children("a");f=d.options.liveSearchNormalize?f.not(":a"+d._searchStyle()+"("+b(d.$searchbox.val())+")"):f.not(":"+d._searchStyle()+"("+d.$searchbox.val()+")"),f.parent().addClass("hidden"),d.$lis.filter(".dropdown-header").each(function(){var b=a(this),c=b.data("optgroup");0===d.$lis.filter("[data-optgroup="+c+"]").not(b).not(".hidden").length&&(b.addClass("hidden"),d.$lis.filter("[data-optgroup="+c+"div]").addClass("hidden"))});var g=d.$lis.not(".hidden");g.each(function(b){var c=a(this);c.hasClass("divider")&&(c.index()===g.eq(0).index()||c.index()===g.last().index()||g.eq(b+1).hasClass("divider"))&&c.addClass("hidden")}),d.$lis.not(".hidden, .no-results").length?e.parent().length&&e.remove():(e.parent().length&&e.remove(),e.html(d.options.noneResultsText.replace("{0}",'"'+c(d.$searchbox.val())+'"')).show(),d.$menuInner.append(e))}else d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove();d.$lis.filter(".active").removeClass("active"),d.$lis.not(".hidden, .divider, .dropdown-header").eq(0).addClass("active").children("a").focus(),a(this).focus()})},_searchStyle:function(){var a="icontains";switch(this.options.liveSearchStyle){case"begins":case"startsWith":a="ibegins";break;case"contains":}return a},val:function(a){return"undefined"!=typeof a?(this.$element.val(a),this.render(),this.$element):this.$element.val()},selectAll:function(){this.findLis(),this.$element.find("option:enabled").not("[data-divider], [data-hidden]").prop("selected",!0),this.$lis.not(".divider, .dropdown-header, .disabled, .hidden").addClass("selected"),this.render(!1)},deselectAll:function(){this.findLis(),this.$element.find("option:enabled").not("[data-divider], [data-hidden]").prop("selected",!1),this.$lis.not(".divider, .dropdown-header, .disabled, .hidden").removeClass("selected"),this.render(!1)},keydown:function(c){var d,e,f,g,h,i,j,k,l,m=a(this),n=m.is("input")?m.parent().parent():m.parent(),o=n.data("this"),p=":not(.disabled, .hidden, .dropdown-header, .divider)",q={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"};if(o.options.liveSearch&&(n=m.parent().parent()),o.options.container&&(n=o.$menu),d=a("[role=menu] li a",n),l=o.$menu.parent().hasClass("open"),!l&&(c.keyCode>=48&&c.keyCode<=57||event.keyCode>=65&&event.keyCode<=90)&&(o.options.container?o.$newElement.trigger("click"):(o.setSize(),o.$menu.parent().addClass("open"),l=!0),o.$searchbox.focus()),o.options.liveSearch&&(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&0===o.$menu.find(".active").length&&(c.preventDefault(),o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus()),d=a("[role=menu] li:not(.disabled, .hidden, .dropdown-header, .divider)",n),m.val()||/(38|40)/.test(c.keyCode.toString(10))||0===d.filter(".active").length&&(d=o.$newElement.find("li"),d=o.options.liveSearchNormalize?d.filter(":a"+o._searchStyle()+"("+b(q[c.keyCode])+")"):d.filter(":"+o._searchStyle()+"("+q[c.keyCode]+")"))),d.length){if(/(38|40)/.test(c.keyCode.toString(10)))e=d.index(d.filter(":focus")),g=d.parent(p).first().data("originalIndex"),h=d.parent(p).last().data("originalIndex"),f=d.eq(e).parent().nextAll(p).eq(0).data("originalIndex"),i=d.eq(e).parent().prevAll(p).eq(0).data("originalIndex"),j=d.eq(f).parent().prevAll(p).eq(0).data("originalIndex"),o.options.liveSearch&&(d.each(function(b){a(this).hasClass("disabled")||a(this).data("index",b)}),e=d.index(d.filter(".active")),g=d.first().data("index"),h=d.last().data("index"),f=d.eq(e).nextAll().eq(0).data("index"),i=d.eq(e).prevAll().eq(0).data("index"),j=d.eq(f).prevAll().eq(0).data("index")),k=m.data("prevIndex"),38==c.keyCode?(o.options.liveSearch&&(e-=1),e!=j&&e>i&&(e=i),g>e&&(e=g),e==k&&(e=h)):40==c.keyCode&&(o.options.liveSearch&&(e+=1),-1==e&&(e=0),e!=j&&f>e&&(e=f),e>h&&(e=h),e==k&&(e=g)),m.data("prevIndex",e),o.options.liveSearch?(c.preventDefault(),m.hasClass("dropdown-toggle")||(d.removeClass("active").eq(e).addClass("active").children("a").focus(),m.focus())):d.eq(e).focus();else if(!m.is("input")){var r,s,t=[];d.each(function(){a(this).parent().hasClass("disabled")||a.trim(a(this).text().toLowerCase()).substring(0,1)==q[c.keyCode]&&t.push(a(this).parent().index())}),r=a(document).data("keycount"),r++,a(document).data("keycount",r),s=a.trim(a(":focus").text().toLowerCase()).substring(0,1),s!=q[c.keyCode]?(r=1,a(document).data("keycount",r)):r>=t.length&&(a(document).data("keycount",0),r>t.length&&(r=1)),d.eq(t[r-1]).focus()}if((/(13|32)/.test(c.keyCode.toString(10))||/(^9$)/.test(c.keyCode.toString(10))&&o.options.selectOnTab)&&l){if(/(32)/.test(c.keyCode.toString(10))||c.preventDefault(),o.options.liveSearch)/(32)/.test(c.keyCode.toString(10))||(o.$menu.find(".active a").click(),m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device").appendTo(this.$newElement),this.options.container&&this.$menu.hide()},refresh:function(){this.$lis=null,this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()}};var f=a.fn.selectpicker;a.fn.selectpicker=d,a.fn.selectpicker.Constructor=e,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=f,this},a(document).data("keycount",0).on("keydown",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',e.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);d.call(b,b.data())})})}(jQuery)}); +//# sourceMappingURL=bootstrap-select.js.map \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap-typeahead/ui-bootstrap-typeahead.min.js b/LiveChat/ClientComponents/bootstrap-typeahead/ui-bootstrap-typeahead.min.js new file mode 100644 index 0000000..7dff4ab --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap-typeahead/ui-bootstrap-typeahead.min.js @@ -0,0 +1,8 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.13.4 - 2015-09-03 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.typeahead","ui.bootstrap.position"]),angular.module("ui.bootstrap.tpls",["template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position"]).factory("typeaheadParser",["$parse",function(e){var t=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(a){var n=a.match(t);if(!n)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+a+'".');return{itemName:n[3],source:e(n[4]),viewMapper:e(n[2]||n[1]),modelMapper:e(n[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$window","$rootScope","$position","typeaheadParser",function(e,t,a,n,i,o,r,p,l){var c=[9,13,27,38,40],s=200;return{require:["ngModel","^?ngModelOptions"],link:function(u,d,h,f){function m(){C.moveInProgress||(C.moveInProgress=!0,C.$digest()),D&&n.cancel(D),D=n(function(){C.matches.length&&g(),C.moveInProgress=!1,C.$digest()},s)}function g(){C.position=E?p.offset(d):p.position(d),C.position.top+=d.prop("offsetHeight")}var v=f[0],$=f[1],y=u.$eval(h.typeaheadMinLength);y||0===y||(y=1);var w,b,x=u.$eval(h.typeaheadWaitMs)||0,I=u.$eval(h.typeaheadEditable)!==!1,M=t(h.typeaheadLoading).assign||angular.noop,S=t(h.typeaheadOnSelect),P=angular.isDefined(h.typeaheadSelectOnBlur)?u.$eval(h.typeaheadSelectOnBlur):!1,U=t(h.typeaheadNoResults).assign||angular.noop,O=h.typeaheadInputFormatter?t(h.typeaheadInputFormatter):void 0,E=h.typeaheadAppendToBody?u.$eval(h.typeaheadAppendToBody):!1,k=u.$eval(h.typeaheadFocusFirst)!==!1,q=h.typeaheadSelectOnExact?u.$eval(h.typeaheadSelectOnExact):!1,T=t(h.ngModel),A=t(h.ngModel+"($$$p)"),V=function(e,t){return angular.isFunction(T(u))&&$&&$.$options&&$.$options.getterSetter?A(e,{$$$p:t}):T.assign(e,t)},_=l.parse(h.typeahead),C=u.$new(),H=u.$on("$destroy",function(){C.$destroy()});C.$on("$destroy",H);var B="typeahead-"+C.$id+"-"+Math.floor(1e4*Math.random());d.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":B});var F=angular.element("
    ");F.attr({id:B,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(h.typeaheadTemplateUrl)&&F.attr("template-url",h.typeaheadTemplateUrl),angular.isDefined(h.typeaheadPopupTemplateUrl)&&F.attr("popup-template-url",h.typeaheadPopupTemplateUrl);var N=function(){C.matches=[],C.activeIdx=-1,d.attr("aria-expanded",!1)},L=function(e){return B+"-option-"+e};C.$watch("activeIdx",function(e){0>e?d.removeAttr("aria-activedescendant"):d.attr("aria-activedescendant",L(e))});var R=function(e,t){return C.matches.length>t&&e?e.toUpperCase()===C.matches[t].label.toUpperCase():!1},W=function(e){var t={$viewValue:e};M(u,!0),U(u,!1),a.when(_.source(u,t)).then(function(a){var n=e===v.$viewValue;if(n&&w)if(a&&a.length>0){C.activeIdx=k?0:-1,U(u,!1),C.matches.length=0;for(var i=0;i=y?x>0?(X(),j(e)):W(e):(M(u,!1),X(),N()),I?e:e?void v.$setValidity("editable",!1):(v.$setValidity("editable",!0),null)}),v.$formatters.push(function(e){var t,a,n={};return I||v.$setValidity("editable",!0),O?(n.$model=e,O(u,n)):(n[_.itemName]=e,t=_.viewMapper(u,n),n[_.itemName]=void 0,a=_.viewMapper(u,n),t!==a?t:e)}),C.select=function(e){var t,a,i={};b=!0,i[_.itemName]=a=C.matches[e].model,t=_.modelMapper(u,i),V(u,t),v.$setValidity("editable",!0),v.$setValidity("parse",!0),S(u,{$item:a,$model:t,$label:_.viewMapper(u,i)}),N(),C.$eval(h.typeaheadFocusOnSelect)!==!1&&n(function(){d[0].focus()},0,!1)},d.bind("keydown",function(e){if(0!==C.matches.length&&-1!==c.indexOf(e.which)){if(-1===C.activeIdx&&(9===e.which||13===e.which))return N(),void C.$digest();e.preventDefault(),40===e.which?(C.activeIdx=(C.activeIdx+1)%C.matches.length,C.$digest()):38===e.which?(C.activeIdx=(C.activeIdx>0?C.activeIdx:C.matches.length)-1,C.$digest()):13===e.which||9===e.which?C.$apply(function(){C.select(C.activeIdx)}):27===e.which&&(e.stopPropagation(),N(),C.$digest())}}),d.bind("blur",function(){P&&C.matches.length&&-1!==C.activeIdx&&!b&&(b=!0,C.$apply(function(){C.select(C.activeIdx)})),w=!1,b=!1});var Y=function(e){d[0]!==e.target&&3!==e.which&&0!==C.matches.length&&(N(),r.$$phase||C.$digest())};i.bind("click",Y),u.$on("$destroy",function(){i.unbind("click",Y),E&&G.remove(),F.remove()});var G=e(F)(C);E?i.find("body").append(G):d.after(G)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(e,t){return t.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(e,t,a){e.templateUrl=a.templateUrl,e.isOpen=function(){return e.matches.length>0},e.isActive=function(t){return e.active==t},e.selectActive=function(t){e.active=t},e.selectMatch=function(t){e.select({activeIdx:t})}}}}).directive("typeaheadMatch",["$templateRequest","$compile","$parse",function(e,t,a){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(n,i,o){var r=a(o.templateUrl)(n.$parent)||"template/typeahead/typeahead-match.html";e(r).then(function(e){t(e.trim())(n,function(e){i.replaceWith(e)})})}}}]).filter("typeaheadHighlight",["$sce","$injector","$log",function(e,t,a){function n(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function i(e){return/<.*>/g.test(e)}var o;return o=t.has("$sanitize"),function(t,r){return!o&&i(t)&&a.warn("Unsafe use of typeahead please use ngSanitize"),t=r?(""+t).replace(new RegExp(n(r),"gi"),"$&"):t,o||(t=e.trustAsHtml(t)),t}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(e,t){function a(e,a){return e.currentStyle?e.currentStyle[a]:t.getComputedStyle?t.getComputedStyle(e)[a]:e.style[a]}function n(e){return"static"===(a(e,"position")||"static")}var i=function(t){for(var a=e[0],i=t.offsetParent||a;i&&i!==a&&n(i);)i=i.offsetParent;return i||a};return{position:function(t){var a=this.offset(t),n={top:0,left:0},o=i(t[0]);o!=e[0]&&(n=this.offset(angular.element(o)),n.top+=o.clientTop-o.scrollTop,n.left+=o.clientLeft-o.scrollLeft);var r=t[0].getBoundingClientRect();return{width:r.width||t.prop("offsetWidth"),height:r.height||t.prop("offsetHeight"),top:a.top-n.top,left:a.left-n.left}},offset:function(a){var n=a[0].getBoundingClientRect();return{width:n.width||a.prop("offsetWidth"),height:n.height||a.prop("offsetHeight"),top:n.top+(t.pageYOffset||e[0].documentElement.scrollTop),left:n.left+(t.pageXOffset||e[0].documentElement.scrollLeft)}},positionElements:function(e,t,a,n){var i,o,r,p,l=a.split("-"),c=l[0],s=l[1]||"center";i=n?this.offset(e):this.position(e),o=t.prop("offsetWidth"),r=t.prop("offsetHeight");var u={center:function(){return i.left+i.width/2-o/2},left:function(){return i.left},right:function(){return i.left+i.width}},d={center:function(){return i.top+i.height/2-r/2},top:function(){return i.top},bottom:function(){return i.top+i.height}};switch(c){case"right":p={top:d[s](),left:u[c]()};break;case"left":p={top:d[s](),left:i.left-o};break;case"bottom":p={top:d[c](),left:u[s]()};break;default:p={top:i.top-r,left:u[s]()}}return p}}}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead-match.html",'\n')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead-popup.html",'\n')}]); \ No newline at end of file diff --git a/LiveChat/ClientComponents/bootstrap/bootstrap.min.js b/LiveChat/ClientComponents/bootstrap/bootstrap.min.js new file mode 100644 index 0000000..c8f82e5 --- /dev/null +++ b/LiveChat/ClientComponents/bootstrap/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/LiveChat/ClientComponents/chosen.jquery/chosen-sprite.png b/LiveChat/ClientComponents/chosen.jquery/chosen-sprite.png new file mode 100644 index 0000000..c57da70 Binary files /dev/null and b/LiveChat/ClientComponents/chosen.jquery/chosen-sprite.png differ diff --git a/LiveChat/ClientComponents/chosen.jquery/chosen.jquery.js b/LiveChat/ClientComponents/chosen.jquery/chosen.jquery.js new file mode 100644 index 0000000..a0d71d8 --- /dev/null +++ b/LiveChat/ClientComponents/chosen.jquery/chosen.jquery.js @@ -0,0 +1,1211 @@ +/*! +Chosen, a Select Box Enhancer for jQuery and Prototype +by Patrick Filler for Harvest, http://getharvest.com + +Version 1.1.0 +Full source at https://github.com/harvesthq/chosen +Copyright (c) 2011 Harvest http://getharvest.com + +MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md +This file is generated by `grunt build`, do not edit it by hand. +*/ + +(function() { + var $, AbstractChosen, Chosen, SelectParser, _ref, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + SelectParser = (function() { + function SelectParser() { + this.options_index = 0; + this.parsed = []; + } + + SelectParser.prototype.add_node = function(child) { + if (child.nodeName.toUpperCase() === "OPTGROUP") { + return this.add_group(child); + } else { + return this.add_option(child); + } + }; + + SelectParser.prototype.add_group = function(group) { + var group_position, option, _i, _len, _ref, _results; + group_position = this.parsed.length; + this.parsed.push({ + array_index: group_position, + group: true, + label: this.escapeExpression(group.label), + children: 0, + disabled: group.disabled + }); + _ref = group.childNodes; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + option = _ref[_i]; + _results.push(this.add_option(option, group_position, group.disabled)); + } + return _results; + }; + + SelectParser.prototype.add_option = function(option, group_position, group_disabled) { + if (option.nodeName.toUpperCase() === "OPTION") { + if (option.text !== "") { + if (group_position != null) { + this.parsed[group_position].children += 1; + } + this.parsed.push({ + array_index: this.parsed.length, + options_index: this.options_index, + value: option.value, + text: option.text, + html: option.innerHTML, + selected: option.selected, + disabled: group_disabled === true ? group_disabled : option.disabled, + group_array_index: group_position, + classes: option.className, + style: option.style.cssText + }); + } else { + this.parsed.push({ + array_index: this.parsed.length, + options_index: this.options_index, + empty: true + }); + } + return this.options_index += 1; + } + }; + + SelectParser.prototype.escapeExpression = function(text) { + var map, unsafe_chars; + if ((text == null) || text === false) { + return ""; + } + if (!/[\&\<\>\"\'\`]/.test(text)) { + return text; + } + map = { + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g; + return text.replace(unsafe_chars, function(chr) { + return map[chr] || "&"; + }); + }; + + return SelectParser; + + })(); + + SelectParser.select_to_array = function(select) { + var child, parser, _i, _len, _ref; + parser = new SelectParser(); + _ref = select.childNodes; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + parser.add_node(child); + } + return parser.parsed; + }; + + AbstractChosen = (function() { + function AbstractChosen(form_field, options) { + this.form_field = form_field; + this.options = options != null ? options : {}; + if (!AbstractChosen.browser_is_supported()) { + return; + } + this.is_multiple = this.form_field.multiple; + this.set_default_text(); + this.set_default_values(); + this.setup(); + this.set_up_html(); + this.register_observers(); + } + + AbstractChosen.prototype.set_default_values = function() { + var _this = this; + this.click_test_action = function(evt) { + return _this.test_active_click(evt); + }; + this.activate_action = function(evt) { + return _this.activate_field(evt); + }; + this.active_field = false; + this.mouse_on_container = false; + this.results_showing = false; + this.result_highlighted = null; + this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; + this.disable_search_threshold = this.options.disable_search_threshold || 0; + this.disable_search = this.options.disable_search || false; + this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true; + this.group_search = this.options.group_search != null ? this.options.group_search : true; + this.search_contains = this.options.search_contains || false; + this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true; + this.max_selected_options = this.options.max_selected_options || Infinity; + this.inherit_select_classes = this.options.inherit_select_classes || false; + this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true; + return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true; + }; + + AbstractChosen.prototype.set_default_text = function() { + if (this.form_field.getAttribute("data-placeholder")) { + this.default_text = this.form_field.getAttribute("data-placeholder"); + } else if (this.is_multiple) { + this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text; + } else { + this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text; + } + return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text; + }; + + AbstractChosen.prototype.mouse_enter = function() { + return this.mouse_on_container = true; + }; + + AbstractChosen.prototype.mouse_leave = function() { + return this.mouse_on_container = false; + }; + + AbstractChosen.prototype.input_focus = function(evt) { + var _this = this; + if (this.is_multiple) { + if (!this.active_field) { + return setTimeout((function() { + return _this.container_mousedown(); + }), 50); + } + } else { + if (!this.active_field) { + return this.activate_field(); + } + } + }; + + AbstractChosen.prototype.input_blur = function(evt) { + var _this = this; + if (!this.mouse_on_container) { + this.active_field = false; + return setTimeout((function() { + return _this.blur_test(); + }), 100); + } + }; + + AbstractChosen.prototype.results_option_build = function(options) { + var content, data, _i, _len, _ref; + content = ''; + _ref = this.results_data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + data = _ref[_i]; + if (data.group) { + content += this.result_add_group(data); + } else { + content += this.result_add_option(data); + } + if (options != null ? options.first : void 0) { + if (data.selected && this.is_multiple) { + this.choice_build(data); + } else if (data.selected && !this.is_multiple) { + this.single_set_selected_text(data.text); + } + } + } + return content; + }; + + AbstractChosen.prototype.result_add_option = function(option) { + var classes, option_el; + if (!option.search_match) { + return ''; + } + if (!this.include_option_in_results(option)) { + return ''; + } + classes = []; + if (!option.disabled && !(option.selected && this.is_multiple)) { + classes.push("active-result"); + } + if (option.disabled && !(option.selected && this.is_multiple)) { + classes.push("disabled-result"); + } + if (option.selected) { + classes.push("result-selected"); + } + if (option.group_array_index != null) { + classes.push("group-option"); + } + if (option.classes !== "") { + classes.push(option.classes); + } + option_el = document.createElement("li"); + option_el.className = classes.join(" "); + option_el.style.cssText = option.style; + option_el.setAttribute("data-option-array-index", option.array_index); + option_el.innerHTML = option.search_text; + return this.outerHTML(option_el); + }; + + AbstractChosen.prototype.result_add_group = function(group) { + var group_el; + if (!(group.search_match || group.group_match)) { + return ''; + } + if (!(group.active_options > 0)) { + return ''; + } + group_el = document.createElement("li"); + group_el.className = "group-result"; + group_el.innerHTML = group.search_text; + return this.outerHTML(group_el); + }; + + AbstractChosen.prototype.results_update_field = function() { + this.set_default_text(); + if (!this.is_multiple) { + this.results_reset_cleanup(); + } + this.result_clear_highlight(); + this.results_build(); + if (this.results_showing) { + return this.winnow_results(); + } + }; + + AbstractChosen.prototype.reset_single_select_options = function() { + var result, _i, _len, _ref, _results; + _ref = this.results_data; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + result = _ref[_i]; + if (result.selected) { + _results.push(result.selected = false); + } else { + _results.push(void 0); + } + } + return _results; + }; + + AbstractChosen.prototype.results_toggle = function() { + if (this.results_showing) { + return this.results_hide(); + } else { + return this.results_show(); + } + }; + + AbstractChosen.prototype.results_search = function(evt) { + if (this.results_showing) { + return this.winnow_results(); + } else { + return this.results_show(); + } + }; + + AbstractChosen.prototype.winnow_results = function() { + var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref; + this.no_results_clear(); + results = 0; + searchText = this.get_search_text(); + escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + regexAnchor = this.search_contains ? "" : "^"; + regex = new RegExp(regexAnchor + escapedSearchText, 'i'); + zregex = new RegExp(escapedSearchText, 'i'); + _ref = this.results_data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + option = _ref[_i]; + option.search_match = false; + results_group = null; + if (this.include_option_in_results(option)) { + if (option.group) { + option.group_match = false; + option.active_options = 0; + } + if ((option.group_array_index != null) && this.results_data[option.group_array_index]) { + results_group = this.results_data[option.group_array_index]; + if (results_group.active_options === 0 && results_group.search_match) { + results += 1; + } + results_group.active_options += 1; + } + if (!(option.group && !this.group_search)) { + option.search_text = option.group ? option.label : option.html; + option.search_match = this.search_string_match(option.search_text, regex); + if (option.search_match && !option.group) { + results += 1; + } + if (option.search_match) { + if (searchText.length) { + startpos = option.search_text.search(zregex); + text = option.search_text.substr(0, startpos + searchText.length) + '' + option.search_text.substr(startpos + searchText.length); + option.search_text = text.substr(0, startpos) + '' + text.substr(startpos); + } + if (results_group != null) { + results_group.group_match = true; + } + } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) { + option.search_match = true; + } + } + } + } + this.result_clear_highlight(); + if (results < 1 && searchText.length) { + this.update_results_content(""); + return this.no_results(searchText); + } else { + this.update_results_content(this.results_option_build()); + return this.winnow_results_set_highlight(); + } + }; + + AbstractChosen.prototype.search_string_match = function(search_string, regex) { + var part, parts, _i, _len; + if (regex.test(search_string)) { + return true; + } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) { + parts = search_string.replace(/\[|\]/g, "").split(" "); + if (parts.length) { + for (_i = 0, _len = parts.length; _i < _len; _i++) { + part = parts[_i]; + if (regex.test(part)) { + return true; + } + } + } + } + }; + + AbstractChosen.prototype.choices_count = function() { + var option, _i, _len, _ref; + if (this.selected_option_count != null) { + return this.selected_option_count; + } + this.selected_option_count = 0; + _ref = this.form_field.options; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + option = _ref[_i]; + if (option.selected) { + this.selected_option_count += 1; + } + } + return this.selected_option_count; + }; + + AbstractChosen.prototype.choices_click = function(evt) { + evt.preventDefault(); + if (!(this.results_showing || this.is_disabled)) { + return this.results_show(); + } + }; + + AbstractChosen.prototype.keyup_checker = function(evt) { + var stroke, _ref; + stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; + this.search_field_scale(); + switch (stroke) { + case 8: + if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) { + return this.keydown_backstroke(); + } else if (!this.pending_backstroke) { + this.result_clear_highlight(); + return this.results_search(); + } + break; + case 13: + evt.preventDefault(); + if (this.results_showing) { + return this.result_select(evt); + } + break; + case 27: + if (this.results_showing) { + this.results_hide(); + } + return true; + case 9: + case 38: + case 40: + case 16: + case 91: + case 17: + break; + default: + return this.results_search(); + } + }; + + AbstractChosen.prototype.clipboard_event_checker = function(evt) { + var _this = this; + return setTimeout((function() { + return _this.results_search(); + }), 50); + }; + + AbstractChosen.prototype.container_width = function() { + if (this.options.width != null) { + return this.options.width; + } else { + return "" + this.form_field.offsetWidth + "px"; + } + }; + + AbstractChosen.prototype.include_option_in_results = function(option) { + if (this.is_multiple && (!this.display_selected_options && option.selected)) { + return false; + } + if (!this.display_disabled_options && option.disabled) { + return false; + } + if (option.empty) { + return false; + } + return true; + }; + + AbstractChosen.prototype.search_results_touchstart = function(evt) { + this.touch_started = true; + return this.search_results_mouseover(evt); + }; + + AbstractChosen.prototype.search_results_touchmove = function(evt) { + this.touch_started = false; + return this.search_results_mouseout(evt); + }; + + AbstractChosen.prototype.search_results_touchend = function(evt) { + if (this.touch_started) { + return this.search_results_mouseup(evt); + } + }; + + AbstractChosen.prototype.outerHTML = function(element) { + var tmp; + if (element.outerHTML) { + return element.outerHTML; + } + tmp = document.createElement("div"); + tmp.appendChild(element); + return tmp.innerHTML; + }; + + AbstractChosen.browser_is_supported = function() { + if (window.navigator.appName === "Microsoft Internet Explorer") { + return document.documentMode >= 8; + } + if (/iP(od|hone)/i.test(window.navigator.userAgent)) { + return false; + } + if (/Android/i.test(window.navigator.userAgent)) { + if (/Mobile/i.test(window.navigator.userAgent)) { + return false; + } + } + return true; + }; + + AbstractChosen.default_multiple_text = "Select Some Options"; + + AbstractChosen.default_single_text = "Select an Option"; + + AbstractChosen.default_no_result_text = "No results match"; + + return AbstractChosen; + + })(); + + $ = jQuery; + + $.fn.extend({ + chosen: function(options) { + if (!AbstractChosen.browser_is_supported()) { + return this; + } + return this.each(function(input_field) { + var $this, chosen; + $this = $(this); + chosen = $this.data('chosen'); + if (options === 'destroy' && chosen) { + chosen.destroy(); + } else if (!chosen) { + $this.data('chosen', new Chosen(this, options)); + } + }); + } + }); + + Chosen = (function(_super) { + __extends(Chosen, _super); + + function Chosen() { + _ref = Chosen.__super__.constructor.apply(this, arguments); + return _ref; + } + + Chosen.prototype.setup = function() { + this.form_field_jq = $(this.form_field); + this.current_selectedIndex = this.form_field.selectedIndex; + return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl"); + }; + + Chosen.prototype.set_up_html = function() { + var container_classes, container_props; + container_classes = ["chosen-container"]; + container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single")); + if (this.inherit_select_classes && this.form_field.className) { + container_classes.push(this.form_field.className); + } + if (this.is_rtl) { + container_classes.push("chosen-rtl"); + } + container_props = { + 'class': container_classes.join(' '), + 'style': "width: " + (this.container_width()) + ";", + 'title': this.form_field.title + }; + if (this.form_field.id.length) { + container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen"; + } + this.container = $("
    ", container_props); + if (this.is_multiple) { + this.container.html('
      '); + } else { + this.container.html('' + this.default_text + '
        '); + } + this.form_field_jq.hide().after(this.container); + this.dropdown = this.container.find('div.chosen-drop').first(); + this.search_field = this.container.find('input').first(); + this.search_results = this.container.find('ul.chosen-results').first(); + this.search_field_scale(); + this.search_no_results = this.container.find('li.no-results').first(); + if (this.is_multiple) { + this.search_choices = this.container.find('ul.chosen-choices').first(); + this.search_container = this.container.find('li.search-field').first(); + } else { + this.search_container = this.container.find('div.chosen-search').first(); + this.selected_item = this.container.find('.chosen-single').first(); + } + this.results_build(); + this.set_tab_index(); + this.set_label_behavior(); + return this.form_field_jq.trigger("chosen:ready", { + chosen: this + }); + }; + + Chosen.prototype.register_observers = function() { + var _this = this; + this.container.bind('mousedown.chosen', function(evt) { + _this.container_mousedown(evt); + }); + this.container.bind('mouseup.chosen', function(evt) { + _this.container_mouseup(evt); + }); + this.container.bind('mouseenter.chosen', function(evt) { + _this.mouse_enter(evt); + }); + this.container.bind('mouseleave.chosen', function(evt) { + _this.mouse_leave(evt); + }); + this.search_results.bind('mouseup.chosen', function(evt) { + _this.search_results_mouseup(evt); + }); + this.search_results.bind('mouseover.chosen', function(evt) { + _this.search_results_mouseover(evt); + }); + this.search_results.bind('mouseout.chosen', function(evt) { + _this.search_results_mouseout(evt); + }); + this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) { + _this.search_results_mousewheel(evt); + }); + this.search_results.bind('touchstart.chosen', function(evt) { + _this.search_results_touchstart(evt); + }); + this.search_results.bind('touchmove.chosen', function(evt) { + _this.search_results_touchmove(evt); + }); + this.search_results.bind('touchend.chosen', function(evt) { + _this.search_results_touchend(evt); + }); + this.form_field_jq.bind("chosen:updated.chosen", function(evt) { + _this.results_update_field(evt); + }); + this.form_field_jq.bind("chosen:activate.chosen", function(evt) { + _this.activate_field(evt); + }); + this.form_field_jq.bind("chosen:open.chosen", function(evt) { + _this.container_mousedown(evt); + }); + this.form_field_jq.bind("chosen:close.chosen", function(evt) { + _this.input_blur(evt); + }); + this.search_field.bind('blur.chosen', function(evt) { + _this.input_blur(evt); + }); + this.search_field.bind('keyup.chosen', function(evt) { + _this.keyup_checker(evt); + }); + this.search_field.bind('keydown.chosen', function(evt) { + _this.keydown_checker(evt); + }); + this.search_field.bind('focus.chosen', function(evt) { + _this.input_focus(evt); + }); + this.search_field.bind('cut.chosen', function(evt) { + _this.clipboard_event_checker(evt); + }); + this.search_field.bind('paste.chosen', function(evt) { + _this.clipboard_event_checker(evt); + }); + if (this.is_multiple) { + return this.search_choices.bind('click.chosen', function(evt) { + _this.choices_click(evt); + }); + } else { + return this.container.bind('click.chosen', function(evt) { + evt.preventDefault(); + }); + } + }; + + Chosen.prototype.destroy = function() { + $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); + if (this.search_field[0].tabIndex) { + this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex; + } + this.container.remove(); + this.form_field_jq.removeData('chosen'); + return this.form_field_jq.show(); + }; + + Chosen.prototype.search_field_disabled = function() { + this.is_disabled = this.form_field_jq[0].disabled; + if (this.is_disabled) { + this.container.addClass('chosen-disabled'); + this.search_field[0].disabled = true; + if (!this.is_multiple) { + this.selected_item.unbind("focus.chosen", this.activate_action); + } + return this.close_field(); + } else { + this.container.removeClass('chosen-disabled'); + this.search_field[0].disabled = false; + if (!this.is_multiple) { + return this.selected_item.bind("focus.chosen", this.activate_action); + } + } + }; + + Chosen.prototype.container_mousedown = function(evt) { + if (!this.is_disabled) { + if (evt && evt.type === "mousedown" && !this.results_showing) { + evt.preventDefault(); + } + if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) { + if (!this.active_field) { + if (this.is_multiple) { + this.search_field.val(""); + } + $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action); + this.results_show(); + } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) { + evt.preventDefault(); + this.results_toggle(); + } + return this.activate_field(); + } + } + }; + + Chosen.prototype.container_mouseup = function(evt) { + if (evt.target.nodeName === "ABBR" && !this.is_disabled) { + return this.results_reset(evt); + } + }; + + Chosen.prototype.search_results_mousewheel = function(evt) { + var delta; + if (evt.originalEvent) { + delta = -evt.originalEvent.wheelDelta || evt.originalEvent.detail; + } + if (delta != null) { + evt.preventDefault(); + if (evt.type === 'DOMMouseScroll') { + delta = delta * 40; + } + return this.search_results.scrollTop(delta + this.search_results.scrollTop()); + } + }; + + Chosen.prototype.blur_test = function(evt) { + if (!this.active_field && this.container.hasClass("chosen-container-active")) { + return this.close_field(); + } + }; + + Chosen.prototype.close_field = function() { + $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action); + this.active_field = false; + this.results_hide(); + this.container.removeClass("chosen-container-active"); + this.clear_backstroke(); + this.show_search_field_default(); + return this.search_field_scale(); + }; + + Chosen.prototype.activate_field = function() { + this.container.addClass("chosen-container-active"); + this.active_field = true; + this.search_field.val(this.search_field.val()); + return this.search_field.focus(); + }; + + Chosen.prototype.test_active_click = function(evt) { + var active_container; + active_container = $(evt.target).closest('.chosen-container'); + if (active_container.length && this.container[0] === active_container[0]) { + return this.active_field = true; + } else { + return this.close_field(); + } + }; + + Chosen.prototype.results_build = function() { + this.parsing = true; + this.selected_option_count = null; + this.results_data = SelectParser.select_to_array(this.form_field); + if (this.is_multiple) { + this.search_choices.find("li.search-choice").remove(); + } else if (!this.is_multiple) { + this.single_set_selected_text(); + if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { + this.search_field[0].readOnly = true; + this.container.addClass("chosen-container-single-nosearch"); + } else { + this.search_field[0].readOnly = false; + this.container.removeClass("chosen-container-single-nosearch"); + } + } + this.update_results_content(this.results_option_build({ + first: true + })); + this.search_field_disabled(); + this.show_search_field_default(); + this.search_field_scale(); + return this.parsing = false; + }; + + Chosen.prototype.result_do_highlight = function(el) { + var high_bottom, high_top, maxHeight, visible_bottom, visible_top; + if (el.length) { + this.result_clear_highlight(); + this.result_highlight = el; + this.result_highlight.addClass("highlighted"); + maxHeight = parseInt(this.search_results.css("maxHeight"), 10); + visible_top = this.search_results.scrollTop(); + visible_bottom = maxHeight + visible_top; + high_top = this.result_highlight.position().top + this.search_results.scrollTop(); + high_bottom = high_top + this.result_highlight.outerHeight(); + if (high_bottom >= visible_bottom) { + return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); + } else if (high_top < visible_top) { + return this.search_results.scrollTop(high_top); + } + } + }; + + Chosen.prototype.result_clear_highlight = function() { + if (this.result_highlight) { + this.result_highlight.removeClass("highlighted"); + } + return this.result_highlight = null; + }; + + Chosen.prototype.results_show = function() { + if (this.is_multiple && this.max_selected_options <= this.choices_count()) { + this.form_field_jq.trigger("chosen:maxselected", { + chosen: this + }); + return false; + } + this.container.addClass("chosen-with-drop"); + this.results_showing = true; + this.search_field.focus(); + this.search_field.val(this.search_field.val()); + this.winnow_results(); + return this.form_field_jq.trigger("chosen:showing_dropdown", { + chosen: this + }); + }; + + Chosen.prototype.update_results_content = function(content) { + return this.search_results.html(content); + }; + + Chosen.prototype.results_hide = function() { + if (this.results_showing) { + this.result_clear_highlight(); + this.container.removeClass("chosen-with-drop"); + this.form_field_jq.trigger("chosen:hiding_dropdown", { + chosen: this + }); + } + return this.results_showing = false; + }; + + Chosen.prototype.set_tab_index = function(el) { + var ti; + if (this.form_field.tabIndex) { + ti = this.form_field.tabIndex; + this.form_field.tabIndex = -1; + return this.search_field[0].tabIndex = ti; + } + }; + + Chosen.prototype.set_label_behavior = function() { + var _this = this; + this.form_field_label = this.form_field_jq.parents("label"); + if (!this.form_field_label.length && this.form_field.id.length) { + this.form_field_label = $("label[for='" + this.form_field.id + "']"); + } + if (this.form_field_label.length > 0) { + return this.form_field_label.bind('click.chosen', function(evt) { + if (_this.is_multiple) { + return _this.container_mousedown(evt); + } else { + return _this.activate_field(); + } + }); + } + }; + + Chosen.prototype.show_search_field_default = function() { + if (this.is_multiple && this.choices_count() < 1 && !this.active_field) { + this.search_field.val(this.default_text); + return this.search_field.addClass("default"); + } else { + this.search_field.val(""); + return this.search_field.removeClass("default"); + } + }; + + Chosen.prototype.search_results_mouseup = function(evt) { + var target; + target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); + if (target.length) { + this.result_highlight = target; + this.result_select(evt); + return this.search_field.focus(); + } + }; + + Chosen.prototype.search_results_mouseover = function(evt) { + var target; + target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); + if (target) { + return this.result_do_highlight(target); + } + }; + + Chosen.prototype.search_results_mouseout = function(evt) { + if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) { + return this.result_clear_highlight(); + } + }; + + Chosen.prototype.choice_build = function(item) { + var choice, close_link, + _this = this; + choice = $('
      • ', { + "class": "search-choice" + }).html("" + item.html + ""); + if (item.disabled) { + choice.addClass('search-choice-disabled'); + } else { + close_link = $('', { + "class": 'search-choice-close', + 'data-option-array-index': item.array_index + }); + close_link.bind('click.chosen', function(evt) { + return _this.choice_destroy_link_click(evt); + }); + choice.append(close_link); + } + return this.search_container.before(choice); + }; + + Chosen.prototype.choice_destroy_link_click = function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + if (!this.is_disabled) { + return this.choice_destroy($(evt.target)); + } + }; + + Chosen.prototype.choice_destroy = function(link) { + if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) { + this.show_search_field_default(); + if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) { + this.results_hide(); + } + link.parents('li').first().remove(); + return this.search_field_scale(); + } + }; + + Chosen.prototype.results_reset = function() { + this.reset_single_select_options(); + this.form_field.options[0].selected = true; + this.single_set_selected_text(); + this.show_search_field_default(); + this.results_reset_cleanup(); + this.form_field_jq.trigger("change"); + if (this.active_field) { + return this.results_hide(); + } + }; + + Chosen.prototype.results_reset_cleanup = function() { + this.current_selectedIndex = this.form_field.selectedIndex; + return this.selected_item.find("abbr").remove(); + }; + + Chosen.prototype.result_select = function(evt) { + var high, item; + if (this.result_highlight) { + high = this.result_highlight; + this.result_clear_highlight(); + if (this.is_multiple && this.max_selected_options <= this.choices_count()) { + this.form_field_jq.trigger("chosen:maxselected", { + chosen: this + }); + return false; + } + if (this.is_multiple) { + high.removeClass("active-result"); + } else { + this.reset_single_select_options(); + } + item = this.results_data[high[0].getAttribute("data-option-array-index")]; + item.selected = true; + this.form_field.options[item.options_index].selected = true; + this.selected_option_count = null; + if (this.is_multiple) { + this.choice_build(item); + } else { + this.single_set_selected_text(item.text); + } + if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) { + this.results_hide(); + } + this.search_field.val(""); + if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) { + this.form_field_jq.trigger("change", { + 'selected': this.form_field.options[item.options_index].value + }); + } + this.current_selectedIndex = this.form_field.selectedIndex; + return this.search_field_scale(); + } + }; + + Chosen.prototype.single_set_selected_text = function(text) { + if (text == null) { + text = this.default_text; + } + if (text === this.default_text) { + this.selected_item.addClass("chosen-default"); + } else { + this.single_deselect_control_build(); + this.selected_item.removeClass("chosen-default"); + } + return this.selected_item.find("span").text(text); + }; + + Chosen.prototype.result_deselect = function(pos) { + var result_data; + result_data = this.results_data[pos]; + if (!this.form_field.options[result_data.options_index].disabled) { + result_data.selected = false; + this.form_field.options[result_data.options_index].selected = false; + this.selected_option_count = null; + this.result_clear_highlight(); + if (this.results_showing) { + this.winnow_results(); + } + this.form_field_jq.trigger("change", { + deselected: this.form_field.options[result_data.options_index].value + }); + this.search_field_scale(); + return true; + } else { + return false; + } + }; + + Chosen.prototype.single_deselect_control_build = function() { + if (!this.allow_single_deselect) { + return; + } + if (!this.selected_item.find("abbr").length) { + this.selected_item.find("span").first().after(""); + } + return this.selected_item.addClass("chosen-single-with-deselect"); + }; + + Chosen.prototype.get_search_text = function() { + if (this.search_field.val() === this.default_text) { + return ""; + } else { + return $('
        ').text($.trim(this.search_field.val())).html(); + } + }; + + Chosen.prototype.winnow_results_set_highlight = function() { + var do_high, selected_results; + selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; + do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); + if (do_high != null) { + return this.result_do_highlight(do_high); + } + }; + + Chosen.prototype.no_results = function(terms) { + var no_results_html; + no_results_html = $('
      • ' + this.results_none_found + ' ""
      • '); + no_results_html.find("span").first().html(terms); + this.search_results.append(no_results_html); + return this.form_field_jq.trigger("chosen:no_results", { + chosen: this + }); + }; + + Chosen.prototype.no_results_clear = function() { + return this.search_results.find(".no-results").remove(); + }; + + Chosen.prototype.keydown_arrow = function() { + var next_sib; + if (this.results_showing && this.result_highlight) { + next_sib = this.result_highlight.nextAll("li.active-result").first(); + if (next_sib) { + return this.result_do_highlight(next_sib); + } + } else { + return this.results_show(); + } + }; + + Chosen.prototype.keyup_arrow = function() { + var prev_sibs; + if (!this.results_showing && !this.is_multiple) { + return this.results_show(); + } else if (this.result_highlight) { + prev_sibs = this.result_highlight.prevAll("li.active-result"); + if (prev_sibs.length) { + return this.result_do_highlight(prev_sibs.first()); + } else { + if (this.choices_count() > 0) { + this.results_hide(); + } + return this.result_clear_highlight(); + } + } + }; + + Chosen.prototype.keydown_backstroke = function() { + var next_available_destroy; + if (this.pending_backstroke) { + this.choice_destroy(this.pending_backstroke.find("a").first()); + return this.clear_backstroke(); + } else { + next_available_destroy = this.search_container.siblings("li.search-choice").last(); + if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) { + this.pending_backstroke = next_available_destroy; + if (this.single_backstroke_delete) { + return this.keydown_backstroke(); + } else { + return this.pending_backstroke.addClass("search-choice-focus"); + } + } + } + }; + + Chosen.prototype.clear_backstroke = function() { + if (this.pending_backstroke) { + this.pending_backstroke.removeClass("search-choice-focus"); + } + return this.pending_backstroke = null; + }; + + Chosen.prototype.keydown_checker = function(evt) { + var stroke, _ref1; + stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode; + this.search_field_scale(); + if (stroke !== 8 && this.pending_backstroke) { + this.clear_backstroke(); + } + switch (stroke) { + case 8: + this.backstroke_length = this.search_field.val().length; + break; + case 9: + if (this.results_showing && !this.is_multiple) { + this.result_select(evt); + } + this.mouse_on_container = false; + break; + case 13: + evt.preventDefault(); + break; + case 38: + evt.preventDefault(); + this.keyup_arrow(); + break; + case 40: + evt.preventDefault(); + this.keydown_arrow(); + break; + } + }; + + Chosen.prototype.search_field_scale = function() { + var div, f_width, h, style, style_block, styles, w, _i, _len; + if (this.is_multiple) { + h = 0; + w = 0; + style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"; + styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing']; + for (_i = 0, _len = styles.length; _i < _len; _i++) { + style = styles[_i]; + style_block += style + ":" + this.search_field.css(style) + ";"; + } + div = $('
        ', { + 'style': style_block + }); + div.text(this.search_field.val()); + $('body').append(div); + w = div.width() + 25; + div.remove(); + f_width = this.container.outerWidth(); + if (w > f_width - 10) { + w = f_width - 10; + } + return this.search_field.css({ + 'width': w + 'px' + }); + } + }; + + return Chosen; + + })(AbstractChosen); + +}).call(this); diff --git a/LiveChat/ClientComponents/chosen.jquery/chosen.js b/LiveChat/ClientComponents/chosen.jquery/chosen.js new file mode 100644 index 0000000..806f916 --- /dev/null +++ b/LiveChat/ClientComponents/chosen.jquery/chosen.js @@ -0,0 +1,116 @@ +// Generated by CoffeeScript 1.8.0 +(function() { + var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + angular.module('localytics.directives', []); + + angular.module('localytics.directives').directive('chosen', [ + '$timeout', function($timeout) { + var CHOSEN_OPTION_WHITELIST, NG_OPTIONS_REGEXP, isEmpty, snakeCase; + NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/; + CHOSEN_OPTION_WHITELIST = ['noResultsText', 'allowSingleDeselect', 'disableSearchThreshold', 'disableSearch', 'enableSplitWordSearch', 'inheritSelectClasses', 'maxSelectedOptions', 'placeholderTextMultiple', 'placeholderTextSingle', 'searchContains', 'singleBackstrokeDelete', 'displayDisabledOptions', 'displaySelectedOptions', 'width']; + snakeCase = function(input) { + return input.replace(/[A-Z]/g, function($1) { + return "_" + ($1.toLowerCase()); + }); + }; + isEmpty = function(value) { + var key; + if (angular.isArray(value)) { + return value.length === 0; + } else if (angular.isObject(value)) { + for (key in value) { + if (value.hasOwnProperty(key)) { + return false; + } + } + } + return true; + }; + return { + restrict: 'A', + require: '?ngModel', + terminal: true, + link: function(scope, element, attr, ngModel) { + var chosen, defaultText, disableWithMessage, empty, initOrUpdate, match, options, origRender, removeEmptyMessage, startLoading, stopLoading, valuesExpr, viewWatch; + element.addClass('localytics-chosen'); + options = scope.$eval(attr.chosen) || {}; + angular.forEach(attr, function(value, key) { + if (__indexOf.call(CHOSEN_OPTION_WHITELIST, key) >= 0) { + return options[snakeCase(key)] = scope.$eval(value); + } + }); + startLoading = function() { + return element.addClass('loading').attr('disabled', true).trigger('chosen:updated'); + }; + stopLoading = function() { + return element.removeClass('loading').attr('disabled', false).trigger('chosen:updated'); + }; + chosen = null; + defaultText = null; + empty = false; + initOrUpdate = function() { + if (chosen) { + return element.trigger('chosen:updated'); + } else { + chosen = element.chosen(options).data('chosen'); + return defaultText = chosen.default_text; + } + }; + removeEmptyMessage = function() { + empty = false; + return element.attr('data-placeholder', defaultText); + }; + disableWithMessage = function() { + empty = true; + return element.attr('data-placeholder', chosen.results_none_found).attr('disabled', true).trigger('chosen:updated'); + }; + if (ngModel) { + origRender = ngModel.$render; + ngModel.$render = function() { + origRender(); + return initOrUpdate(); + }; + if (attr.multiple) { + viewWatch = function() { + return ngModel.$viewValue; + }; + scope.$watch(viewWatch, ngModel.$render, true); + } + } else { + initOrUpdate(); + } + attr.$observe('disabled', function() { + return element.trigger('chosen:updated'); + }); + if (attr.ngOptions && ngModel) { + match = attr.ngOptions.match(NG_OPTIONS_REGEXP); + valuesExpr = match[7]; + scope.$watchCollection(valuesExpr, function(newVal, oldVal) { + var timer; + return timer = $timeout(function() { + if (angular.isUndefined(newVal)) { + return startLoading(); + } else { + if (empty) { + removeEmptyMessage(); + } + stopLoading(); + if (isEmpty(newVal)) { + return disableWithMessage(); + } + } + }); + }); + return scope.$on('$destroy', function(event) { + if (typeof timer !== "undefined" && timer !== null) { + return $timeout.cancel(timer); + } + }); + } + } + }; + } + ]); + +}).call(this); diff --git a/LiveChat/ClientComponents/chosen.jquery/chosen.min.css b/LiveChat/ClientComponents/chosen.jquery/chosen.min.css new file mode 100644 index 0000000..e69de29 diff --git a/LiveChat/ClientComponents/jquery.jscrollpane/jquery.jscrollpane.css b/LiveChat/ClientComponents/jquery.jscrollpane/jquery.jscrollpane.css new file mode 100644 index 0000000..e69de29 diff --git a/LiveChat/ClientComponents/jquery.jscrollpane/jquery.jscrollpane.min.js b/LiveChat/ClientComponents/jquery.jscrollpane/jquery.jscrollpane.min.js new file mode 100644 index 0000000..57d2945 --- /dev/null +++ b/LiveChat/ClientComponents/jquery.jscrollpane/jquery.jscrollpane.min.js @@ -0,0 +1,8 @@ +/*! + * jScrollPane - v2.0.22 - 2015-04-25 + * http://jscrollpane.kelvinluck.com/ + * + * Copyright (c) 2014 Kelvin Luck + * Dual licensed under the MIT or GPL licenses. + */ +!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.fn.jScrollPane=function(b){function c(b,c){function d(c){var f,h,j,k,l,o,p=!1,q=!1;if(N=c,void 0===O)l=b.scrollTop(),o=b.scrollLeft(),b.css({overflow:"hidden",padding:0}),P=b.innerWidth()+ra,Q=b.innerHeight(),b.width(P),O=a('
        ').css("padding",qa).append(b.children()),R=a('
        ').css({width:P+"px",height:Q+"px"}).append(O).appendTo(b);else{if(b.css("width",""),p=N.stickToBottom&&A(),q=N.stickToRight&&B(),k=b.innerWidth()+ra!=P||b.outerHeight()!=Q,k&&(P=b.innerWidth()+ra,Q=b.innerHeight(),R.css({width:P+"px",height:Q+"px"})),!k&&sa==S&&O.outerHeight()==T)return void b.width(P);sa=S,O.css("width",""),b.width(P),R.find(">.jspVerticalBar,>.jspHorizontalBar").remove().end()}O.css("overflow","auto"),S=c.contentWidth?c.contentWidth:O[0].scrollWidth,T=O[0].scrollHeight,O.css("overflow",""),U=S/P,V=T/Q,W=V>1,X=U>1,X||W?(b.addClass("jspScrollable"),f=N.maintainPosition&&($||ba),f&&(h=y(),j=z()),e(),g(),i(),f&&(w(q?S-P:h,!1),v(p?T-Q:j,!1)),F(),C(),L(),N.enableKeyboardNavigation&&H(),N.clickOnTrack&&m(),J(),N.hijackInternalLinks&&K()):(b.removeClass("jspScrollable"),O.css({top:0,left:0,width:R.width()-ra}),D(),G(),I(),n()),N.autoReinitialise&&!pa?pa=setInterval(function(){d(N)},N.autoReinitialiseDelay):!N.autoReinitialise&&pa&&clearInterval(pa),l&&b.scrollTop(0)&&v(l,!1),o&&b.scrollLeft(0)&&w(o,!1),b.trigger("jsp-initialised",[X||W])}function e(){W&&(R.append(a('
        ').append(a('
        '),a('
        ').append(a('
        ').append(a('
        '),a('
        '))),a('
        '))),ca=R.find(">.jspVerticalBar"),da=ca.find(">.jspTrack"),Y=da.find(">.jspDrag"),N.showArrows&&(ha=a('').bind("mousedown.jsp",k(0,-1)).bind("click.jsp",E),ia=a('').bind("mousedown.jsp",k(0,1)).bind("click.jsp",E),N.arrowScrollOnHover&&(ha.bind("mouseover.jsp",k(0,-1,ha)),ia.bind("mouseover.jsp",k(0,1,ia))),j(da,N.verticalArrowPositions,ha,ia)),fa=Q,R.find(">.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow").each(function(){fa-=a(this).outerHeight()}),Y.hover(function(){Y.addClass("jspHover")},function(){Y.removeClass("jspHover")}).bind("mousedown.jsp",function(b){a("html").bind("dragstart.jsp selectstart.jsp",E),Y.addClass("jspActive");var c=b.pageY-Y.position().top;return a("html").bind("mousemove.jsp",function(a){p(a.pageY-c,!1)}).bind("mouseup.jsp mouseleave.jsp",o),!1}),f())}function f(){da.height(fa+"px"),$=0,ea=N.verticalGutter+da.outerWidth(),O.width(P-ea-ra);try{0===ca.position().left&&O.css("margin-left",ea+"px")}catch(a){}}function g(){X&&(R.append(a('
        ').append(a('
        '),a('
        ').append(a('
        ').append(a('
        '),a('
        '))),a('
        '))),ja=R.find(">.jspHorizontalBar"),ka=ja.find(">.jspTrack"),_=ka.find(">.jspDrag"),N.showArrows&&(na=a('').bind("mousedown.jsp",k(-1,0)).bind("click.jsp",E),oa=a('').bind("mousedown.jsp",k(1,0)).bind("click.jsp",E),N.arrowScrollOnHover&&(na.bind("mouseover.jsp",k(-1,0,na)),oa.bind("mouseover.jsp",k(1,0,oa))),j(ka,N.horizontalArrowPositions,na,oa)),_.hover(function(){_.addClass("jspHover")},function(){_.removeClass("jspHover")}).bind("mousedown.jsp",function(b){a("html").bind("dragstart.jsp selectstart.jsp",E),_.addClass("jspActive");var c=b.pageX-_.position().left;return a("html").bind("mousemove.jsp",function(a){r(a.pageX-c,!1)}).bind("mouseup.jsp mouseleave.jsp",o),!1}),la=R.innerWidth(),h())}function h(){R.find(">.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow").each(function(){la-=a(this).outerWidth()}),ka.width(la+"px"),ba=0}function i(){if(X&&W){var b=ka.outerHeight(),c=da.outerWidth();fa-=b,a(ja).find(">.jspCap:visible,>.jspArrow").each(function(){la+=a(this).outerWidth()}),la-=c,Q-=c,P-=b,ka.parent().append(a('
        ').css("width",b+"px")),f(),h()}X&&O.width(R.outerWidth()-ra+"px"),T=O.outerHeight(),V=T/Q,X&&(ma=Math.ceil(1/U*la),ma>N.horizontalDragMaxWidth?ma=N.horizontalDragMaxWidth:maN.verticalDragMaxHeight?ga=N.verticalDragMaxHeight:gaf)$-k>e?ta.scrollByY(-j):p(e);else{if(!(f>0))return void i();e>$+k?ta.scrollByY(j):p(e)}c=setTimeout(h,g?N.initialDelay:N.trackClickRepeatFreq),g=!1},i=function(){c&&clearTimeout(c),c=null,a(document).unbind("mouseup.jsp",i)};return h(),a(document).bind("mouseup.jsp",i),!1}}),X&&ka.bind("mousedown.jsp",function(b){if(void 0===b.originalTarget||b.originalTarget==b.currentTarget){var c,d=a(this),e=d.offset(),f=b.pageX-e.left-ba,g=!0,h=function(){var a=d.offset(),e=b.pageX-a.left-ma/2,j=P*N.scrollPagePercent,k=aa*j/(S-P);if(0>f)ba-k>e?ta.scrollByX(-j):r(e);else{if(!(f>0))return void i();e>ba+k?ta.scrollByX(j):r(e)}c=setTimeout(h,g?N.initialDelay:N.trackClickRepeatFreq),g=!1},i=function(){c&&clearTimeout(c),c=null,a(document).unbind("mouseup.jsp",i)};return h(),a(document).bind("mouseup.jsp",i),!1}})}function n(){ka&&ka.unbind("mousedown.jsp"),da&&da.unbind("mousedown.jsp")}function o(){a("html").unbind("dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp"),Y&&Y.removeClass("jspActive"),_&&_.removeClass("jspActive")}function p(a,b){W&&(0>a?a=0:a>Z&&(a=Z),void 0===b&&(b=N.animateScroll),b?ta.animate(Y,"top",a,q):(Y.css("top",a),q(a)))}function q(a){void 0===a&&(a=Y.position().top),R.scrollTop(0),$=a||0;var c=0===$,d=$==Z,e=a/Z,f=-e*(T-Q);(ua!=c||wa!=d)&&(ua=c,wa=d,b.trigger("jsp-arrow-change",[ua,wa,va,xa])),t(c,d),O.css("top",f),b.trigger("jsp-scroll-y",[-f,c,d]).trigger("scroll")}function r(a,b){X&&(0>a?a=0:a>aa&&(a=aa),void 0===b&&(b=N.animateScroll),b?ta.animate(_,"left",a,s):(_.css("left",a),s(a)))}function s(a){void 0===a&&(a=_.position().left),R.scrollTop(0),ba=a||0;var c=0===ba,d=ba==aa,e=a/aa,f=-e*(S-P);(va!=c||xa!=d)&&(va=c,xa=d,b.trigger("jsp-arrow-change",[ua,wa,va,xa])),u(c,d),O.css("left",f),b.trigger("jsp-scroll-x",[-f,c,d]).trigger("scroll")}function t(a,b){N.showArrows&&(ha[a?"addClass":"removeClass"]("jspDisabled"),ia[b?"addClass":"removeClass"]("jspDisabled"))}function u(a,b){N.showArrows&&(na[a?"addClass":"removeClass"]("jspDisabled"),oa[b?"addClass":"removeClass"]("jspDisabled"))}function v(a,b){var c=a/(T-Q);p(c*Z,b)}function w(a,b){var c=a/(S-P);r(c*aa,b)}function x(b,c,d){var e,f,g,h,i,j,k,l,m,n=0,o=0;try{e=a(b)}catch(p){return}for(f=e.outerHeight(),g=e.outerWidth(),R.scrollTop(0),R.scrollLeft(0);!e.is(".jspPane");)if(n+=e.position().top,o+=e.position().left,e=e.offsetParent(),/^body|html$/i.test(e[0].nodeName))return;h=z(),j=h+Q,h>n||c?l=n-N.horizontalGutter:n+f>j&&(l=n-Q+f+N.horizontalGutter),isNaN(l)||v(l,d),i=y(),k=i+P,i>o||c?m=o-N.horizontalGutter:o+g>k&&(m=o-P+g+N.horizontalGutter),isNaN(m)||w(m,d)}function y(){return-O.position().left}function z(){return-O.position().top}function A(){var a=T-Q;return a>20&&a-z()<10}function B(){var a=S-P;return a>20&&a-y()<10}function C(){R.unbind(za).bind(za,function(a,b,c,d){ba||(ba=0),$||($=0);var e=ba,f=$,g=a.deltaFactor||N.mouseWheelSpeed;return ta.scrollBy(c*g,-d*g,!1),e==ba&&f==$})}function D(){R.unbind(za)}function E(){return!1}function F(){O.find(":input,a").unbind("focus.jsp").bind("focus.jsp",function(a){x(a.target,!1)})}function G(){O.find(":input,a").unbind("focus.jsp")}function H(){function c(){var a=ba,b=$;switch(d){case 40:ta.scrollByY(N.keyboardSpeed,!1);break;case 38:ta.scrollByY(-N.keyboardSpeed,!1);break;case 34:case 32:ta.scrollByY(Q*N.scrollPagePercent,!1);break;case 33:ta.scrollByY(-Q*N.scrollPagePercent,!1);break;case 39:ta.scrollByX(N.keyboardSpeed,!1);break;case 37:ta.scrollByX(-N.keyboardSpeed,!1)}return e=a!=ba||b!=$}var d,e,f=[];X&&f.push(ja[0]),W&&f.push(ca[0]),O.bind("focus.jsp",function(){b.focus()}),b.attr("tabindex",0).unbind("keydown.jsp keypress.jsp").bind("keydown.jsp",function(b){if(b.target===this||f.length&&a(b.target).closest(f).length){var g=ba,h=$;switch(b.keyCode){case 40:case 38:case 34:case 32:case 33:case 39:case 37:d=b.keyCode,c();break;case 35:v(T-Q),d=null;break;case 36:v(0),d=null}return e=b.keyCode==d&&g!=ba||h!=$,!e}}).bind("keypress.jsp",function(a){return a.keyCode==d&&c(),!e}),N.hideFocus?(b.css("outline","none"),"hideFocus"in R[0]&&b.attr("hideFocus",!0)):(b.css("outline",""),"hideFocus"in R[0]&&b.attr("hideFocus",!1))}function I(){b.attr("tabindex","-1").removeAttr("tabindex").unbind("keydown.jsp keypress.jsp"),O.unbind(".jsp")}function J(){if(location.hash&&location.hash.length>1){var b,c,d=escape(location.hash.substr(1));try{b=a("#"+d+', a[name="'+d+'"]')}catch(e){return}b.length&&O.find(d)&&(0===R.scrollTop()?c=setInterval(function(){R.scrollTop()>0&&(x(b,!0),a(document).scrollTop(R.position().top),clearInterval(c))},50):(x(b,!0),a(document).scrollTop(R.position().top)))}}function K(){a(document.body).data("jspHijack")||(a(document.body).data("jspHijack",!0),a(document.body).delegate("a[href*=#]","click",function(b){var c,d,e,f,g,h,i=this.href.substr(0,this.href.indexOf("#")),j=location.href;if(-1!==location.href.indexOf("#")&&(j=location.href.substr(0,location.href.indexOf("#"))),i===j){c=escape(this.href.substr(this.href.indexOf("#")+1));try{d=a("#"+c+', a[name="'+c+'"]')}catch(k){return}d.length&&(e=d.closest(".jspScrollable"),f=e.data("jsp"),f.scrollToElement(d,!0),e[0].scrollIntoView&&(g=a(window).scrollTop(),h=d.offset().top,(g>h||h>g+a(window).height())&&e[0].scrollIntoView()),b.preventDefault())}}))}function L(){var a,b,c,d,e,f=!1;R.unbind("touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick").bind("touchstart.jsp",function(g){var h=g.originalEvent.touches[0];a=y(),b=z(),c=h.pageX,d=h.pageY,e=!1,f=!0}).bind("touchmove.jsp",function(g){if(f){var h=g.originalEvent.touches[0],i=ba,j=$;return ta.scrollTo(a+c-h.pageX,b+d-h.pageY),e=e||Math.abs(c-h.pageX)>5||Math.abs(d-h.pageY)>5,i==ba&&j==$}}).bind("touchend.jsp",function(a){f=!1}).bind("click.jsp-touchclick",function(a){return e?(e=!1,!1):void 0})}function M(){var a=z(),c=y();b.removeClass("jspScrollable").unbind(".jsp"),O.unbind(".jsp"),b.replaceWith(ya.append(O.children())),ya.scrollTop(a),ya.scrollLeft(c),pa&&clearInterval(pa)}var N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,aa,ba,ca,da,ea,fa,ga,ha,ia,ja,ka,la,ma,na,oa,pa,qa,ra,sa,ta=this,ua=!0,va=!0,wa=!1,xa=!1,ya=b.clone(!1,!1).empty(),za=a.fn.mwheelIntent?"mwheelIntent.jsp":"mousewheel.jsp";"border-box"===b.css("box-sizing")?(qa=0,ra=0):(qa=b.css("paddingTop")+" "+b.css("paddingRight")+" "+b.css("paddingBottom")+" "+b.css("paddingLeft"),ra=(parseInt(b.css("paddingLeft"),10)||0)+(parseInt(b.css("paddingRight"),10)||0)),a.extend(ta,{reinitialise:function(b){b=a.extend({},N,b),d(b)},scrollToElement:function(a,b,c){x(a,b,c)},scrollTo:function(a,b,c){w(a,c),v(b,c)},scrollToX:function(a,b){w(a,b)},scrollToY:function(a,b){v(a,b)},scrollToPercentX:function(a,b){w(a*(S-P),b)},scrollToPercentY:function(a,b){v(a*(T-Q),b)},scrollBy:function(a,b,c){ta.scrollByX(a,c),ta.scrollByY(b,c)},scrollByX:function(a,b){var c=y()+Math[0>a?"floor":"ceil"](a),d=c/(S-P);r(d*aa,b)},scrollByY:function(a,b){var c=z()+Math[0>a?"floor":"ceil"](a),d=c/(T-Q);p(d*Z,b)},positionDragX:function(a,b){r(a,b)},positionDragY:function(a,b){p(a,b)},animate:function(a,b,c,d){var e={};e[b]=c,a.animate(e,{duration:N.animateDuration,easing:N.animateEase,queue:!1,step:d})},getContentPositionX:function(){return y()},getContentPositionY:function(){return z()},getContentWidth:function(){return S},getContentHeight:function(){return T},getPercentScrolledX:function(){return y()/(S-P)},getPercentScrolledY:function(){return z()/(T-Q)},getIsScrollableH:function(){return X},getIsScrollableV:function(){return W},getContentPane:function(){return O},scrollToBottom:function(a){p(Z,a)},hijackInternalLinks:a.noop,destroy:function(){M()}}),d(c)}return b=a.extend({},a.fn.jScrollPane.defaults,b),a.each(["arrowButtonSpeed","trackClickSpeed","keyboardSpeed"],function(){b[this]=b[this]||b.speed}),this.each(function(){var d=a(this),e=d.data("jsp");e?e.reinitialise(b):(a("script",d).filter('[type="text/javascript"],:not([type])').remove(),e=new c(d,b),d.data("jsp",e))})},a.fn.jScrollPane.defaults={showArrows:!1,maintainPosition:!0,stickToBottom:!1,stickToRight:!1,clickOnTrack:!0,autoReinitialise:!1,autoReinitialiseDelay:500,verticalDragMinHeight:0,verticalDragMaxHeight:99999,horizontalDragMinWidth:0,horizontalDragMaxWidth:99999,contentWidth:void 0,animateScroll:!1,animateDuration:300,animateEase:"linear",hijackInternalLinks:!1,verticalGutter:4,horizontalGutter:4,mouseWheelSpeed:3,arrowButtonSpeed:0,arrowRepeatFreq:50,arrowScrollOnHover:!1,trackClickSpeed:0,trackClickRepeatFreq:70,verticalArrowPositions:"split",horizontalArrowPositions:"split",enableKeyboardNavigation:!0,hideFocus:!1,keyboardSpeed:0,initialDelay:300,speed:30,scrollPagePercent:.8}}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/jquery.jscrollpane/jquery.mousewheel.js b/LiveChat/ClientComponents/jquery.jscrollpane/jquery.mousewheel.js new file mode 100644 index 0000000..bf61ad0 --- /dev/null +++ b/LiveChat/ClientComponents/jquery.jscrollpane/jquery.mousewheel.js @@ -0,0 +1,221 @@ +/*! + * jQuery Mousewheel 3.1.12 + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +(function (factory) { + if ( typeof define === 'function' && define.amd ) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS style for Browserify + module.exports = factory; + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], + toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? + ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], + slice = Array.prototype.slice, + nullLowestDeltaTimeout, lowestDelta; + + if ( $.event.fixHooks ) { + for ( var i = toFix.length; i; ) { + $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; + } + } + + var special = $.event.special.mousewheel = { + version: '3.1.12', + + setup: function() { + if ( this.addEventListener ) { + for ( var i = toBind.length; i; ) { + this.addEventListener( toBind[--i], handler, false ); + } + } else { + this.onmousewheel = handler; + } + // Store the line height and page height for this particular element + $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); + $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); + }, + + teardown: function() { + if ( this.removeEventListener ) { + for ( var i = toBind.length; i; ) { + this.removeEventListener( toBind[--i], handler, false ); + } + } else { + this.onmousewheel = null; + } + // Clean up the data we added to the element + $.removeData(this, 'mousewheel-line-height'); + $.removeData(this, 'mousewheel-page-height'); + }, + + getLineHeight: function(elem) { + var $elem = $(elem), + $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); + if (!$parent.length) { + $parent = $('body'); + } + return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16; + }, + + getPageHeight: function(elem) { + return $(elem).height(); + }, + + settings: { + adjustOldDeltas: true, // see shouldAdjustOldDeltas() below + normalizeOffset: true // calls getBoundingClientRect for each event + } + }; + + $.fn.extend({ + mousewheel: function(fn) { + return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); + }, + + unmousewheel: function(fn) { + return this.unbind('mousewheel', fn); + } + }); + + + function handler(event) { + var orgEvent = event || window.event, + args = slice.call(arguments, 1), + delta = 0, + deltaX = 0, + deltaY = 0, + absDelta = 0, + offsetX = 0, + offsetY = 0; + event = $.event.fix(orgEvent); + event.type = 'mousewheel'; + + // Old school scrollwheel delta + if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } + if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } + if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } + if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } + + // Firefox < 17 horizontal scrolling related to DOMMouseScroll event + if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { + deltaX = deltaY * -1; + deltaY = 0; + } + + // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy + delta = deltaY === 0 ? deltaX : deltaY; + + // New school wheel delta (wheel event) + if ( 'deltaY' in orgEvent ) { + deltaY = orgEvent.deltaY * -1; + delta = deltaY; + } + if ( 'deltaX' in orgEvent ) { + deltaX = orgEvent.deltaX; + if ( deltaY === 0 ) { delta = deltaX * -1; } + } + + // No change actually happened, no reason to go any further + if ( deltaY === 0 && deltaX === 0 ) { return; } + + // Need to convert lines and pages to pixels if we aren't already in pixels + // There are three delta modes: + // * deltaMode 0 is by pixels, nothing to do + // * deltaMode 1 is by lines + // * deltaMode 2 is by pages + if ( orgEvent.deltaMode === 1 ) { + var lineHeight = $.data(this, 'mousewheel-line-height'); + delta *= lineHeight; + deltaY *= lineHeight; + deltaX *= lineHeight; + } else if ( orgEvent.deltaMode === 2 ) { + var pageHeight = $.data(this, 'mousewheel-page-height'); + delta *= pageHeight; + deltaY *= pageHeight; + deltaX *= pageHeight; + } + + // Store lowest absolute delta to normalize the delta values + absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); + + if ( !lowestDelta || absDelta < lowestDelta ) { + lowestDelta = absDelta; + + // Adjust older deltas if necessary + if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { + lowestDelta /= 40; + } + } + + // Adjust older deltas if necessary + if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { + // Divide all the things by 40! + delta /= 40; + deltaX /= 40; + deltaY /= 40; + } + + // Get a whole, normalized value for the deltas + delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); + deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); + deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); + + // Normalise offsetX and offsetY properties + if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { + var boundingRect = this.getBoundingClientRect(); + offsetX = event.clientX - boundingRect.left; + offsetY = event.clientY - boundingRect.top; + } + + // Add information to the event object + event.deltaX = deltaX; + event.deltaY = deltaY; + event.deltaFactor = lowestDelta; + event.offsetX = offsetX; + event.offsetY = offsetY; + // Go ahead and set deltaMode to 0 since we converted to pixels + // Although this is a little odd since we overwrite the deltaX/Y + // properties with normalized deltas. + event.deltaMode = 0; + + // Add event and delta to the front of the arguments + args.unshift(event, delta, deltaX, deltaY); + + // Clearout lowestDelta after sometime to better + // handle multiple device types that give different + // a different lowestDelta + // Ex: trackpad = 3 and mouse wheel = 120 + if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } + nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); + + return ($.event.dispatch || $.event.handle).apply(this, args); + } + + function nullLowestDelta() { + lowestDelta = null; + } + + function shouldAdjustOldDeltas(orgEvent, absDelta) { + // If this is an older event and the delta is divisable by 120, + // then we are assuming that the browser is treating this as an + // older mouse wheel event and that we should divide the deltas + // by 40 to try and get a more usable deltaFactor. + // Side note, this actually impacts the reported scroll distance + // in older browsers and can cause scrolling to be slower than native. + // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. + return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; + } + +})); diff --git a/LiveChat/ClientComponents/jquery.nicescroll/jquery.nicescroll.min.js b/LiveChat/ClientComponents/jquery.nicescroll/jquery.nicescroll.min.js new file mode 100644 index 0000000..5440b6a --- /dev/null +++ b/LiveChat/ClientComponents/jquery.nicescroll/jquery.nicescroll.min.js @@ -0,0 +1,118 @@ +/* jquery.nicescroll 3.6.0 InuYaksa*2014 MIT http://nicescroll.areaaperta.com */(function(f){"function"===typeof define&&define.amd?define(["jquery"],f):f(jQuery)})(function(f){var y=!1,D=!1,N=0,O=2E3,x=0,H=["webkit","ms","moz","o"],s=window.requestAnimationFrame||!1,t=window.cancelAnimationFrame||!1;if(!s)for(var P in H){var E=H[P];s||(s=window[E+"RequestAnimationFrame"]);t||(t=window[E+"CancelAnimationFrame"]||window[E+"CancelRequestAnimationFrame"])}var v=window.MutationObserver||window.WebKitMutationObserver||!1,I={zindex:"auto",cursoropacitymin:0,cursoropacitymax:1,cursorcolor:"#424242", +cursorwidth:"5px",cursorborder:"1px solid #fff",cursorborderradius:"5px",scrollspeed:60,mousescrollstep:24,touchbehavior:!1,hwacceleration:!0,usetransition:!0,boxzoom:!1,dblclickzoom:!0,gesturezoom:!0,grabcursorenabled:!0,autohidemode:!0,background:"",iframeautoresize:!0,cursorminheight:32,preservenativescrolling:!0,railoffset:!1,railhoffset:!1,bouncescroll:!0,spacebarenabled:!0,railpadding:{top:0,right:0,left:0,bottom:0},disableoutline:!0,horizrailenabled:!0,railalign:"right",railvalign:"bottom", +enabletranslate3d:!0,enablemousewheel:!0,enablekeyboard:!0,smoothscroll:!0,sensitiverail:!0,enablemouselockapi:!0,cursorfixedheight:!1,directionlockdeadzone:6,hidecursordelay:400,nativeparentscrolling:!0,enablescrollonselection:!0,overflowx:!0,overflowy:!0,cursordragspeed:.3,rtlmode:"auto",cursordragontouch:!1,oneaxismousemode:"auto",scriptpath:function(){var f=document.getElementsByTagName("script"),f=f[f.length-1].src.split("?")[0];return 0d?a.getScrollLeft()>=a.page.maxw:0>=a.getScrollLeft())&&(e=d,d=0));d&&(a.scrollmom&&a.scrollmom.stop(),a.lastdeltax+=d,a.debounced("mousewheelx",function(){var b=a.lastdeltax;a.lastdeltax=0;a.rail.drag||a.doScrollLeftBy(b)},15));if(e){if(a.opt.nativeparentscrolling&&c&&!a.ispage&&!a.zoomactive)if(0>e){if(a.getScrollTop()>=a.page.maxh)return!0}else if(0>=a.getScrollTop())return!0;a.scrollmom&&a.scrollmom.stop();a.lastdeltay+=e;a.debounced("mousewheely", +function(){var b=a.lastdeltay;a.lastdeltay=0;a.rail.drag||a.doScrollBy(b)},15)}b.stopImmediatePropagation();return b.preventDefault()}var a=this;this.version="3.6.0";this.name="nicescroll";this.me=c;this.opt={doc:f("body"),win:!1};f.extend(this.opt,I);this.opt.snapbackspeed=80;if(k)for(var G in a.opt)"undefined"!=typeof k[G]&&(a.opt[G]=k[G]);this.iddoc=(this.doc=a.opt.doc)&&this.doc[0]?this.doc[0].id||"":"";this.ispage=/^BODY|HTML/.test(a.opt.win?a.opt.win[0].nodeName:this.doc[0].nodeName);this.haswrapper= +!1!==a.opt.win;this.win=a.opt.win||(this.ispage?f(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?f(window):this.win;this.body=f("body");this.iframe=this.isfixed=this.viewport=!1;this.isiframe="IFRAME"==this.doc[0].nodeName&&"IFRAME"==this.win[0].nodeName;this.istextarea="TEXTAREA"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent="scroll"!=a.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin=this.onscrollcancel=this.onscrollend=this.onscrollstart=this.onclick= +this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.isrtlmode="auto"==this.opt.rtlmode?"rtl"==(this.win[0]==window?this.body:this.win).css("direction"):!0===this.opt.rtlmode;this.observerbody=this.observerremover=this.observer=this.scrollmom=this.scrollrunning=!1;do this.id="ascrail"+O++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus= +this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed=this.cursor=this.rail=!1;this.visibility=!0;this.hidden=this.locked=this.railslocked=!1;this.cursoractive=!0;this.wheelprevented=!1;this.overflowx=a.opt.overflowx;this.overflowy=a.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;this.detected=Q();var e=f.extend({},this.detected);this.ishwscroll=(this.canhwscroll=e.hastransform&& +a.opt.hwacceleration)&&a.haswrapper;this.hasreversehr=this.isrtlmode&&!e.iswebkit;this.istouchcapable=!1;!e.cantouch||e.isios||e.isandroid||!e.iswebkit&&!e.ismozilla||(this.istouchcapable=!0,e.cantouch=!1);a.opt.enablemouselockapi||(e.hasmousecapture=!1,e.haspointerlock=!1);this.debounced=function(b,g,c){var d=a.delaylist[b];a.delaylist[b]=g;d||setTimeout(function(){var g=a.delaylist[b];a.delaylist[b]=!1;g.call(a)},c)};var r=!1;this.synched=function(b,g){a.synclist[b]=g;(function(){r||(s(function(){r= +!1;for(var b in a.synclist){var g=a.synclist[b];g&&g.call(a);a.synclist[b]=!1}}),r=!0)})();return b};this.unsynched=function(b){a.synclist[b]&&(a.synclist[b]=!1)};this.css=function(b,g){for(var c in g)a.saved.css.push([b,c,b.css(c)]),b.css(c,g[c])};this.scrollTop=function(b){return"undefined"==typeof b?a.getScrollTop():a.setScrollTop(b)};this.scrollLeft=function(b){return"undefined"==typeof b?a.getScrollLeft():a.setScrollLeft(b)};var A=function(a,g,c,d,e,f,h){this.st=a;this.ed=g;this.spd=c;this.p1= +d||0;this.p2=e||1;this.p3=f||0;this.p4=h||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};A.prototype={B2:function(a){return 3*a*a*(1-a)},B3:function(a){return 3*a*(1-a)*(1-a)},B4:function(a){return(1-a)*(1-a)*(1-a)},getNow:function(){var a=1-((new Date).getTime()-this.ts)/this.spd,g=this.B2(a)+this.B3(a)+this.B4(a);return 0>a?this.ed:this.st+Math.round(this.df*g)},update:function(a,g){this.st=this.getNow();this.ed=a;this.spd=g;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}}; +if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:"0px",ty:"0px"};e.hastranslate3d&&e.isios&&this.doc.css("-webkit-backface-visibility","hidden");this.getScrollTop=function(b){if(!b){if(b=h())return 16==b.length?-b[13]:-b[5];if(a.timerscroll&&a.timerscroll.bz)return a.timerscroll.bz.getNow()}return a.doc.translate.y};this.getScrollLeft=function(b){if(!b){if(b=h())return 16==b.length?-b[12]:-b[4];if(a.timerscroll&&a.timerscroll.bh)return a.timerscroll.bh.getNow()}return a.doc.translate.x};this.notifyScrollEvent= +function(a){var g=document.createEvent("UIEvents");g.initUIEvent("scroll",!1,!0,window,1);g.niceevent=!0;a.dispatchEvent(g)};var K=this.isrtlmode?1:-1;e.hastranslate3d&&a.opt.enabletranslate3d?(this.setScrollTop=function(b,g){a.doc.translate.y=b;a.doc.translate.ty=-1*b+"px";a.doc.css(e.trstyle,"translate3d("+a.doc.translate.tx+","+a.doc.translate.ty+",0px)");g||a.notifyScrollEvent(a.win[0])},this.setScrollLeft=function(b,g){a.doc.translate.x=b;a.doc.translate.tx=b*K+"px";a.doc.css(e.trstyle,"translate3d("+ +a.doc.translate.tx+","+a.doc.translate.ty+",0px)");g||a.notifyScrollEvent(a.win[0])}):(this.setScrollTop=function(b,g){a.doc.translate.y=b;a.doc.translate.ty=-1*b+"px";a.doc.css(e.trstyle,"translate("+a.doc.translate.tx+","+a.doc.translate.ty+")");g||a.notifyScrollEvent(a.win[0])},this.setScrollLeft=function(b,g){a.doc.translate.x=b;a.doc.translate.tx=b*K+"px";a.doc.css(e.trstyle,"translate("+a.doc.translate.tx+","+a.doc.translate.ty+")");g||a.notifyScrollEvent(a.win[0])})}else this.getScrollTop= +function(){return a.docscroll.scrollTop()},this.setScrollTop=function(b){return a.docscroll.scrollTop(b)},this.getScrollLeft=function(){return a.detected.ismozilla&&a.isrtlmode?Math.abs(a.docscroll.scrollLeft()):a.docscroll.scrollLeft()},this.setScrollLeft=function(b){return a.docscroll.scrollLeft(a.detected.ismozilla&&a.isrtlmode?-b:b)};this.getTarget=function(a){return a?a.target?a.target:a.srcElement?a.srcElement:!1:!1};this.hasParent=function(a,g){if(!a)return!1;for(var c=a.target||a.srcElement|| +a||!1;c&&c.id!=g;)c=c.parentNode||!1;return!1!==c};var w={thin:1,medium:3,thick:5};this.getDocumentScrollOffset=function(){return{top:window.pageYOffset||document.documentElement.scrollTop,left:window.pageXOffset||document.documentElement.scrollLeft}};this.getOffset=function(){if(a.isfixed){var b=a.win.offset(),g=a.getDocumentScrollOffset();b.top-=g.top;b.left-=g.left;return b}b=a.win.offset();if(!a.viewport)return b;g=a.viewport.offset();return{top:b.top-g.top,left:b.left-g.left}};this.updateScrollBar= +function(b){if(a.ishwscroll)a.rail.css({height:a.win.innerHeight()-(a.opt.railpadding.top+a.opt.railpadding.bottom)}),a.railh&&a.railh.css({width:a.win.innerWidth()-(a.opt.railpadding.left+a.opt.railpadding.right)});else{var g=a.getOffset(),c=g.top,e=g.left-(a.opt.railpadding.left+a.opt.railpadding.right),c=c+d(a.win,"border-top-width",!0),e=e+(a.rail.align?a.win.outerWidth()-d(a.win,"border-right-width")-a.rail.width:d(a.win,"border-left-width")),f=a.opt.railoffset;f&&(f.top&&(c+=f.top),a.rail.align&& +f.left&&(e+=f.left));a.railslocked||a.rail.css({top:c,left:e,height:(b?b.h:a.win.innerHeight())-(a.opt.railpadding.top+a.opt.railpadding.bottom)});a.zoom&&a.zoom.css({top:c+1,left:1==a.rail.align?e-20:e+a.rail.width+4});if(a.railh&&!a.railslocked){c=g.top;e=g.left;if(f=a.opt.railhoffset)f.top&&(c+=f.top),f.left&&(e+=f.left);b=a.railh.align?c+d(a.win,"border-top-width",!0)+a.win.innerHeight()-a.railh.height:c+d(a.win,"border-top-width",!0);e+=d(a.win,"border-left-width");a.railh.css({top:b-(a.opt.railpadding.top+ +a.opt.railpadding.bottom),left:e,width:a.railh.width})}}};this.doRailClick=function(b,g,c){var e;a.railslocked||(a.cancelEvent(b),g?(g=c?a.doScrollLeft:a.doScrollTop,e=c?(b.pageX-a.railh.offset().left-a.cursorwidth/2)*a.scrollratio.x:(b.pageY-a.rail.offset().top-a.cursorheight/2)*a.scrollratio.y,g(e)):(g=c?a.doScrollLeftBy:a.doScrollBy,e=c?a.scroll.x:a.scroll.y,b=c?b.pageX-a.railh.offset().left:b.pageY-a.rail.offset().top,c=c?a.view.w:a.view.h,g(e>=b?c:-c)))};a.hasanimationframe=s;a.hascancelanimationframe= +t;a.hasanimationframe?a.hascancelanimationframe||(t=function(){a.cancelAnimationFrame=!0}):(s=function(a){return setTimeout(a,15-Math.floor(+new Date/1E3)%16)},t=clearInterval);this.init=function(){a.saved.css=[];if(e.isie7mobile||e.isoperamini)return!0;e.hasmstouch&&a.css(a.ispage?f("html"):a.win,{"-ms-touch-action":"none"});a.zindex="auto";a.zindex=a.ispage||"auto"!=a.opt.zindex?a.opt.zindex:m()||"auto";!a.ispage&&"auto"!=a.zindex&&a.zindex>x&&(x=a.zindex);a.isie&&0==a.zindex&&"auto"==a.opt.zindex&& +(a.zindex="auto");if(!a.ispage||!e.cantouch&&!e.isieold&&!e.isie9mobile){var b=a.docscroll;a.ispage&&(b=a.haswrapper?a.win:a.doc);e.isie9mobile||a.css(b,{"overflow-y":"hidden"});a.ispage&&e.isie7&&("BODY"==a.doc[0].nodeName?a.css(f("html"),{"overflow-y":"hidden"}):"HTML"==a.doc[0].nodeName&&a.css(f("body"),{"overflow-y":"hidden"}));!e.isios||a.ispage||a.haswrapper||a.css(f("body"),{"-webkit-overflow-scrolling":"touch"});var g=f(document.createElement("div"));g.css({position:"relative",top:0,"float":"right", +width:a.opt.cursorwidth,height:"0px","background-color":a.opt.cursorcolor,border:a.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":a.opt.cursorborderradius,"-moz-border-radius":a.opt.cursorborderradius,"border-radius":a.opt.cursorborderradius});g.hborder=parseFloat(g.outerHeight()-g.innerHeight());g.addClass("nicescroll-cursors");a.cursor=g;var c=f(document.createElement("div"));c.attr("id",a.id);c.addClass("nicescroll-rails nicescroll-rails-vr");var d,h,k=["left","right", +"top","bottom"],J;for(J in k)h=k[J],(d=a.opt.railpadding[h])?c.css("padding-"+h,d+"px"):a.opt.railpadding[h]=0;c.append(g);c.width=Math.max(parseFloat(a.opt.cursorwidth),g.outerWidth());c.css({width:c.width+"px",zIndex:a.zindex,background:a.opt.background,cursor:"default"});c.visibility=!0;c.scrollable=!0;c.align="left"==a.opt.railalign?0:1;a.rail=c;g=a.rail.drag=!1;!a.opt.boxzoom||a.ispage||e.isieold||(g=document.createElement("div"),a.bind(g,"click",a.doZoom),a.bind(g,"mouseenter",function(){a.zoom.css("opacity", +a.opt.cursoropacitymax)}),a.bind(g,"mouseleave",function(){a.zoom.css("opacity",a.opt.cursoropacitymin)}),a.zoom=f(g),a.zoom.css({cursor:"pointer","z-index":a.zindex,backgroundImage:"url("+a.opt.scriptpath+"zoomico.png)",height:18,width:18,backgroundPosition:"0px 0px"}),a.opt.dblclickzoom&&a.bind(a.win,"dblclick",a.doZoom),e.cantouch&&a.opt.gesturezoom&&(a.ongesturezoom=function(b){1.5b.scale&&a.doZoomOut(b);return a.cancelEvent(b)},a.bind(a.win,"gestureend",a.ongesturezoom))); +a.railh=!1;var l;a.opt.horizrailenabled&&(a.css(b,{"overflow-x":"hidden"}),g=f(document.createElement("div")),g.css({position:"absolute",top:0,height:a.opt.cursorwidth,width:"0px","background-color":a.opt.cursorcolor,border:a.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":a.opt.cursorborderradius,"-moz-border-radius":a.opt.cursorborderradius,"border-radius":a.opt.cursorborderradius}),e.isieold&&g.css({overflow:"hidden"}),g.wborder=parseFloat(g.outerWidth()-g.innerWidth()), +g.addClass("nicescroll-cursors"),a.cursorh=g,l=f(document.createElement("div")),l.attr("id",a.id+"-hr"),l.addClass("nicescroll-rails nicescroll-rails-hr"),l.height=Math.max(parseFloat(a.opt.cursorwidth),g.outerHeight()),l.css({height:l.height+"px",zIndex:a.zindex,background:a.opt.background}),l.append(g),l.visibility=!0,l.scrollable=!0,l.align="top"==a.opt.railvalign?0:1,a.railh=l,a.railh.drag=!1);a.ispage?(c.css({position:"fixed",top:"0px",height:"100%"}),c.align?c.css({right:"0px"}):c.css({left:"0px"}), +a.body.append(c),a.railh&&(l.css({position:"fixed",left:"0px",width:"100%"}),l.align?l.css({bottom:"0px"}):l.css({top:"0px"}),a.body.append(l))):(a.ishwscroll?("static"==a.win.css("position")&&a.css(a.win,{position:"relative"}),b="HTML"==a.win[0].nodeName?a.body:a.win,f(b).scrollTop(0).scrollLeft(0),a.zoom&&(a.zoom.css({position:"absolute",top:1,right:0,"margin-right":c.width+4}),b.append(a.zoom)),c.css({position:"absolute",top:0}),c.align?c.css({right:0}):c.css({left:0}),b.append(c),l&&(l.css({position:"absolute", +left:0,bottom:0}),l.align?l.css({bottom:0}):l.css({top:0}),b.append(l))):(a.isfixed="fixed"==a.win.css("position"),b=a.isfixed?"fixed":"absolute",a.isfixed||(a.viewport=a.getViewport(a.win[0])),a.viewport&&(a.body=a.viewport,0==/fixed|absolute/.test(a.viewport.css("position"))&&a.css(a.viewport,{position:"relative"})),c.css({position:b}),a.zoom&&a.zoom.css({position:b}),a.updateScrollBar(),a.body.append(c),a.zoom&&a.body.append(a.zoom),a.railh&&(l.css({position:b}),a.body.append(l))),e.isios&&a.css(a.win, +{"-webkit-tap-highlight-color":"rgba(0,0,0,0)","-webkit-touch-callout":"none"}),e.isie&&a.opt.disableoutline&&a.win.attr("hideFocus","true"),e.iswebkit&&a.opt.disableoutline&&a.win.css({outline:"none"}));!1===a.opt.autohidemode?(a.autohidedom=!1,a.rail.css({opacity:a.opt.cursoropacitymax}),a.railh&&a.railh.css({opacity:a.opt.cursoropacitymax})):!0===a.opt.autohidemode||"leave"===a.opt.autohidemode?(a.autohidedom=f().add(a.rail),e.isie8&&(a.autohidedom=a.autohidedom.add(a.cursor)),a.railh&&(a.autohidedom= +a.autohidedom.add(a.railh)),a.railh&&e.isie8&&(a.autohidedom=a.autohidedom.add(a.cursorh))):"scroll"==a.opt.autohidemode?(a.autohidedom=f().add(a.rail),a.railh&&(a.autohidedom=a.autohidedom.add(a.railh))):"cursor"==a.opt.autohidemode?(a.autohidedom=f().add(a.cursor),a.railh&&(a.autohidedom=a.autohidedom.add(a.cursorh))):"hidden"==a.opt.autohidemode&&(a.autohidedom=!1,a.hide(),a.railslocked=!1);if(e.isie9mobile)a.scrollmom=new L(a),a.onmangotouch=function(){var b=a.getScrollTop(),c=a.getScrollLeft(); +if(b==a.scrollmom.lastscrolly&&c==a.scrollmom.lastscrollx)return!0;var g=b-a.mangotouch.sy,e=c-a.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(e,2)+Math.pow(g,2)))){var d=0>g?-1:1,f=0>e?-1:1,q=+new Date;a.mangotouch.lazy&&clearTimeout(a.mangotouch.lazy);80k?k=Math.round(k/2):k>a.page.maxh&&(k=a.page.maxh+Math.round((k-a.page.maxh)/2)):(0>k&&(q=k=0),k>a.page.maxh&&(k=a.page.maxh,q=0));var l;a.railh&&a.railh.scrollable&&(l=a.isrtlmode?u-a.rail.drag.sl:a.rail.drag.sl-u,a.ishwscroll&&a.opt.bouncescroll?0>l?l=Math.round(l/2):l>a.page.maxw&&(l=a.page.maxw+Math.round((l-a.page.maxw)/2)):(0>l&&(h=l=0),l>a.page.maxw&&(l=a.page.maxw,h=0)));g=!1;if(a.rail.drag.dl)g= +!0,"v"==a.rail.drag.dl?l=a.rail.drag.sl:"h"==a.rail.drag.dl&&(k=a.rail.drag.st);else{d=Math.abs(d);var u=Math.abs(u),z=a.opt.directionlockdeadzone;if("v"==a.rail.drag.ck){if(d>z&&u<=.3*d)return a.rail.drag=!1,!0;u>z&&(a.rail.drag.dl="f",f("body").scrollTop(f("body").scrollTop()))}else if("h"==a.rail.drag.ck){if(u>z&&d<=.3*u)return a.rail.drag=!1,!0;d>z&&(a.rail.drag.dl="f",f("body").scrollLeft(f("body").scrollLeft()))}}a.synched("touchmove",function(){a.rail.drag&&2==a.rail.drag.pt&&(a.prepareTransition&& +a.prepareTransition(0),a.rail.scrollable&&a.setScrollTop(k),a.scrollmom.update(h,q),a.railh&&a.railh.scrollable?(a.setScrollLeft(l),a.showCursor(k,l)):a.showCursor(k),e.isie10&&document.selection.clear())});e.ischrome&&a.istouchcapable&&(g=!1);if(g)return a.cancelEvent(b)}else if(1==a.rail.drag.pt)return a.onmousemove(b)}}a.onmousedown=function(b,c){if(!a.rail.drag||1==a.rail.drag.pt){if(a.railslocked)return a.cancelEvent(b);a.cancelScroll();a.rail.drag={x:b.clientX,y:b.clientY,sx:a.scroll.x,sy:a.scroll.y, +pt:1,hr:!!c};var g=a.getTarget(b);!a.ispage&&e.hasmousecapture&&g.setCapture();a.isiframe&&!e.hasmousecapture&&(a.saved.csspointerevents=a.doc.css("pointer-events"),a.css(a.doc,{"pointer-events":"none"}));a.hasmoving=!1;return a.cancelEvent(b)}};a.onmouseup=function(b){if(a.rail.drag){if(1!=a.rail.drag.pt)return!0;e.hasmousecapture&&document.releaseCapture();a.isiframe&&!e.hasmousecapture&&a.doc.css("pointer-events",a.saved.csspointerevents);a.rail.drag=!1;a.hasmoving&&a.triggerScrollEnd();return a.cancelEvent(b)}}; +a.onmousemove=function(b){if(a.rail.drag&&1==a.rail.drag.pt){if(e.ischrome&&0==b.which)return a.onmouseup(b);a.cursorfreezed=!0;a.hasmoving=!0;if(a.rail.drag.hr){a.scroll.x=a.rail.drag.sx+(b.clientX-a.rail.drag.x);0>a.scroll.x&&(a.scroll.x=0);var c=a.scrollvaluemaxw;a.scroll.x>c&&(a.scroll.x=c)}else a.scroll.y=a.rail.drag.sy+(b.clientY-a.rail.drag.y),0>a.scroll.y&&(a.scroll.y=0),c=a.scrollvaluemax,a.scroll.y>c&&(a.scroll.y=c);a.synched("mousemove",function(){a.rail.drag&&1==a.rail.drag.pt&&(a.showCursor(), +a.rail.drag.hr?a.hasreversehr?a.doScrollLeft(a.scrollvaluemaxw-Math.round(a.scroll.x*a.scrollratio.x),a.opt.cursordragspeed):a.doScrollLeft(Math.round(a.scroll.x*a.scrollratio.x),a.opt.cursordragspeed):a.doScrollTop(Math.round(a.scroll.y*a.scrollratio.y),a.opt.cursordragspeed))});return a.cancelEvent(b)}};if(e.cantouch||a.opt.touchbehavior)a.onpreventclick=function(b){if(a.preventclick)return a.preventclick.tg.onclick=a.preventclick.click,a.preventclick=!1,a.cancelEvent(b)},a.bind(a.win,"mousedown", +a.ontouchstart),a.onclick=e.isios?!1:function(b){return a.lastmouseup?(a.lastmouseup=!1,a.cancelEvent(b)):!0},a.opt.grabcursorenabled&&e.cursorgrabvalue&&(a.css(a.ispage?a.doc:a.win,{cursor:e.cursorgrabvalue}),a.css(a.rail,{cursor:e.cursorgrabvalue}));else{var p=function(b){if(a.selectiondrag){if(b){var c=a.win.outerHeight();b=b.pageY-a.selectiondrag.top;0=c&&(b-=c);a.selectiondrag.df=b}0!=a.selectiondrag.df&&(a.doScrollBy(2*-Math.floor(a.selectiondrag.df/6)),a.debounced("doselectionscroll", +function(){p()},50))}};a.hasTextSelected="getSelection"in document?function(){return 0a.page.maxh?a.doScrollTop(a.page.maxh):(a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y)),a.scroll.x=Math.round(a.getScrollLeft()*(1/a.scrollratio.x)),a.cursoractive&&a.noticeCursor());a.scroll.y&&0==a.getScrollTop()&&a.doScrollTo(Math.floor(a.scroll.y*a.scrollratio.y));return a};this.resize=a.onResize;this.lazyResize=function(b){b=isNaN(b)?30:b;a.debounced("resize",a.resize,b);return a};this.jqbind=function(b, +c,d){a.events.push({e:b,n:c,f:d,q:!0});f(b).bind(c,d)};this.bind=function(b,c,d,f){var h="jquery"in b?b[0]:b;"mousewheel"==c?window.addEventListener||"onwheel"in document?a._bind(h,"wheel",d,f||!1):(b="undefined"!=typeof document.onmousewheel?"mousewheel":"DOMMouseScroll",n(h,b,d,f||!1),"DOMMouseScroll"==b&&n(h,"MozMousePixelScroll",d,f||!1)):h.addEventListener?(e.cantouch&&/mouseup|mousedown|mousemove/.test(c)&&a._bind(h,"mousedown"==c?"touchstart":"mouseup"==c?"touchend":"touchmove",function(a){if(a.touches){if(2> +a.touches.length){var b=a.touches.length?a.touches[0]:a;b.original=a;d.call(this,b)}}else a.changedTouches&&(b=a.changedTouches[0],b.original=a,d.call(this,b))},f||!1),a._bind(h,c,d,f||!1),e.cantouch&&"mouseup"==c&&a._bind(h,"touchcancel",d,f||!1)):a._bind(h,c,function(b){(b=b||window.event||!1)&&b.srcElement&&(b.target=b.srcElement);"pageY"in b||(b.pageX=b.clientX+document.documentElement.scrollLeft,b.pageY=b.clientY+document.documentElement.scrollTop);return!1===d.call(h,b)||!1===f?a.cancelEvent(b): +!0})};e.haseventlistener?(this._bind=function(b,c,d,e){a.events.push({e:b,n:c,f:d,b:e,q:!1});b.addEventListener(c,d,e||!1)},this.cancelEvent=function(a){if(!a)return!1;a=a.original?a.original:a;a.preventDefault();a.stopPropagation();a.preventManipulation&&a.preventManipulation();return!1},this.stopPropagation=function(a){if(!a)return!1;a=a.original?a.original:a;a.stopPropagation();return!1},this._unbind=function(a,c,d,e){a.removeEventListener(c,d,e)}):(this._bind=function(b,c,d,e){a.events.push({e:b, +n:c,f:d,b:e,q:!1});b.attachEvent?b.attachEvent("on"+c,d):b["on"+c]=d},this.cancelEvent=function(a){a=window.event||!1;if(!a)return!1;a.cancelBubble=!0;a.cancel=!0;return a.returnValue=!1},this.stopPropagation=function(a){a=window.event||!1;if(!a)return!1;a.cancelBubble=!0;return!1},this._unbind=function(a,c,d,e){a.detachEvent?a.detachEvent("on"+c,d):a["on"+c]=!1});this.unbindAll=function(){for(var b=0;b(a.newscrolly- +f)*(c-f)||0>(a.newscrollx-h)*(b-h))&&a.cancelScroll();0==a.opt.bouncescroll&&(0>c?c=0:c>a.page.maxh&&(c=a.page.maxh),0>b?b=0:b>a.page.maxw&&(b=a.page.maxw));if(a.scrollrunning&&b==a.newscrollx&&c==a.newscrolly)return!1;a.newscrolly=c;a.newscrollx=b;a.newscrollspeed=d||!1;if(a.timer)return!1;a.timer=setTimeout(function(){var d=a.getScrollTop(),f=a.getScrollLeft(),h,k;h=b-f;k=c-d;h=Math.round(Math.sqrt(Math.pow(h,2)+Math.pow(k,2)));h=a.newscrollspeed&&1=a.newscrollspeed&&(h*=a.newscrollspeed);a.prepareTransition(h,!0);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);0b?b=0:b>a.page.maxh&&(b=a.page.maxh);0>c?c=0:c>a.page.maxw&&(c=a.page.maxw);if(b!=a.newscrolly||c!=a.newscrollx)return a.doScrollPos(c,b,a.opt.snapbackspeed);a.onscrollend&&a.scrollrunning&&a.triggerScrollEnd();a.scrollrunning=!1}):(this.doScrollLeft= +function(b,c){var d=a.scrollrunning?a.newscrolly:a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,c){var d=a.scrollrunning?a.newscrollx:a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){function e(){if(a.cancelAnimationFrame)return!0;a.scrollrunning=!0;if(n=1-n)return a.timer=s(e)||1;var b=0,c,d,g=d=a.getScrollTop();if(a.dst.ay){g=a.bzscroll?a.dst.py+a.bzscroll.getNow()*a.dst.ay:a.newscrolly;c=g-d;if(0>c&&ga.newscrolly)g=a.newscrolly; +a.setScrollTop(g);g==a.newscrolly&&(b=1)}else b=1;d=c=a.getScrollLeft();if(a.dst.ax){d=a.bzscroll?a.dst.px+a.bzscroll.getNow()*a.dst.ax:a.newscrollx;c=d-c;if(0>c&&da.newscrollx)d=a.newscrollx;a.setScrollLeft(d);d==a.newscrollx&&(b+=1)}else b+=1;2==b?(a.timer=0,a.cursorfreezed=!1,a.bzscroll=!1,a.scrollrunning=!1,0>g?g=0:g>a.page.maxh&&(g=a.page.maxh),0>d?d=0:d>a.page.maxw&&(d=a.page.maxw),d!=a.newscrollx||g!=a.newscrolly?a.doScrollPos(d,g):a.onscrollend&&a.triggerScrollEnd()): +a.timer=s(e)||1}c="undefined"==typeof c||!1===c?a.getScrollTop(!0):c;if(a.timer&&a.newscrolly==c&&a.newscrollx==b)return!0;a.timer&&t(a.timer);a.timer=0;var f=a.getScrollTop(),h=a.getScrollLeft();(0>(a.newscrolly-f)*(c-f)||0>(a.newscrollx-h)*(b-h))&&a.cancelScroll();a.newscrolly=c;a.newscrollx=b;a.bouncescroll&&a.rail.visibility||(0>a.newscrolly?a.newscrolly=0:a.newscrolly>a.page.maxh&&(a.newscrolly=a.page.maxh));a.bouncescroll&&a.railh.visibility||(0>a.newscrollx?a.newscrollx=0:a.newscrollx>a.page.maxw&& +(a.newscrollx=a.page.maxw));a.dst={};a.dst.x=b-h;a.dst.y=c-f;a.dst.px=h;a.dst.py=f;var k=Math.round(Math.sqrt(Math.pow(a.dst.x,2)+Math.pow(a.dst.y,2)));a.dst.ax=a.dst.x/k;a.dst.ay=a.dst.y/k;var l=0,m=k;0==a.dst.x?(l=f,m=c,a.dst.ay=1,a.dst.py=0):0==a.dst.y&&(l=h,m=b,a.dst.ax=1,a.dst.px=0);k=a.getTransitionSpeed(k);d&&1>=d&&(k*=d);a.bzscroll=0=a.page.maxh||h==a.page.maxw&&b>=a.page.maxw)&&a.checkContentSize(); +var n=1;a.cancelAnimationFrame=!1;a.timer=1;a.onscrollstart&&!a.scrollrunning&&a.onscrollstart.call(a,{type:"scrollstart",current:{x:h,y:f},request:{x:b,y:c},end:{x:a.newscrollx,y:a.newscrolly},speed:k});e();(f==a.page.maxh&&c>=f||h==a.page.maxw&&b>=h)&&a.checkContentSize();a.noticeCursor()}},this.cancelScroll=function(){a.timer&&t(a.timer);a.timer=0;a.bzscroll=!1;a.scrollrunning=!1;return a}):(this.doScrollLeft=function(b,c){var d=a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b, +c){var d=a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){var e=b>a.page.maxw?a.page.maxw:b;0>e&&(e=0);var f=c>a.page.maxh?a.page.maxh:c;0>f&&(f=0);a.synched("scroll",function(){a.setScrollTop(f);a.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(b,c){var d=0,d=c?Math.floor((a.scroll.y-b)*a.scrollratio.y):(a.timer?a.newscrolly:a.getScrollTop(!0))-b;if(a.bouncescroll){var e=Math.round(a.view.h/2);d<-e?d=-e:d>a.page.maxh+e&&(d=a.page.maxh+e)}a.cursorfreezed= +!1;e=a.getScrollTop(!0);if(0>d&&0>=e)return a.noticeCursor();if(d>a.page.maxh&&e>=a.page.maxh)return a.checkContentSize(),a.noticeCursor();a.doScrollTop(d)};this.doScrollLeftBy=function(b,c){var d=0,d=c?Math.floor((a.scroll.x-b)*a.scrollratio.x):(a.timer?a.newscrollx:a.getScrollLeft(!0))-b;if(a.bouncescroll){var e=Math.round(a.view.w/2);d<-e?d=-e:d>a.page.maxw+e&&(d=a.page.maxw+e)}a.cursorfreezed=!1;e=a.getScrollLeft(!0);if(0>d&&0>=e||d>a.page.maxw&&e>=a.page.maxw)return a.noticeCursor();a.doScrollLeft(d)}; +this.doScrollTo=function(b,c){c&&Math.round(b*a.scrollratio.y);a.cursorfreezed=!1;a.doScrollTop(b)};this.checkContentSize=function(){var b=a.getContentSize();b.h==a.page.h&&b.w==a.page.w||a.resize(!1,b)};a.onscroll=function(b){a.rail.drag||a.cursorfreezed||a.synched("scroll",function(){a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y));a.railh&&(a.scroll.x=Math.round(a.getScrollLeft()*(1/a.scrollratio.x)));a.noticeCursor()})};a.bind(a.docscroll,"scroll",a.onscroll);this.doZoomIn=function(b){if(!a.zoomactive){a.zoomactive= +!0;a.zoomrestore={style:{}};var c="position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight".split(" "),d=a.win[0].style,h;for(h in c){var k=c[h];a.zoomrestore.style[k]="undefined"!=typeof d[k]?d[k]:""}a.zoomrestore.style.width=a.win.css("width");a.zoomrestore.style.height=a.win.css("height");a.zoomrestore.padding={w:a.win.outerWidth()-a.win.width(),h:a.win.outerHeight()-a.win.height()};e.isios4&&(a.zoomrestore.scrollTop=f(window).scrollTop(),f(window).scrollTop(0)); +a.win.css({position:e.isios4?"absolute":"fixed",top:0,left:0,"z-index":x+100,margin:"0px"});c=a.win.css("backgroundColor");(""==c||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(c))&&a.win.css("backgroundColor","#fff");a.rail.css({"z-index":x+101});a.zoom.css({"z-index":x+102});a.zoom.css("backgroundPosition","0px -18px");a.resizeZoom();a.onzoomin&&a.onzoomin.call(a);return a.cancelEvent(b)}};this.doZoomOut=function(b){if(a.zoomactive)return a.zoomactive=!1,a.win.css("margin",""),a.win.css(a.zoomrestore.style), +e.isios4&&f(window).scrollTop(a.zoomrestore.scrollTop),a.rail.css({"z-index":a.zindex}),a.zoom.css({"z-index":a.zindex}),a.zoomrestore=!1,a.zoom.css("backgroundPosition","0px 0px"),a.onResize(),a.onzoomout&&a.onzoomout.call(a),a.cancelEvent(b)};this.doZoom=function(b){return a.zoomactive?a.doZoomOut(b):a.doZoomIn(b)};this.resizeZoom=function(){if(a.zoomactive){var b=a.getScrollTop();a.win.css({width:f(window).width()-a.zoomrestore.padding.w+"px",height:f(window).height()-a.zoomrestore.padding.h+"px"}); +a.onResize();a.setScrollTop(Math.min(a.page.maxh,b))}};this.init();f.nicescroll.push(this)},L=function(f){var c=this;this.nc=f;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(f,k){c.stop();var d=c.time();c.steptime=0;c.lasttime=d;c.speedx=0;c.speedy=0;c.lastx=f;c.lasty=k;c.lastscrollx=-1;c.lastscrolly= +-1};this.update=function(f,k){var d=c.time();c.steptime=d-c.lasttime;c.lasttime=d;var d=k-c.lasty,n=f-c.lastx,p=c.nc.getScrollTop(),a=c.nc.getScrollLeft(),p=p+d,a=a+n;c.snapx=0>a||a>c.nc.page.maxw;c.snapy=0>p||p>c.nc.page.maxh;c.speedx=n;c.speedy=d;c.lastx=f;c.lasty=k};this.stop=function(){c.nc.unsynched("domomentum2d");c.timer&&clearTimeout(c.timer);c.timer=0;c.lastscrollx=-1;c.lastscrolly=-1};this.doSnapy=function(f,k){var d=!1;0>k?(k=0,d=!0):k>c.nc.page.maxh&&(k=c.nc.page.maxh,d=!0);0>f?(f=0,d= +!0):f>c.nc.page.maxw&&(f=c.nc.page.maxw,d=!0);d?c.nc.doScrollPos(f,k,c.nc.opt.snapbackspeed):c.nc.triggerScrollEnd()};this.doMomentum=function(f){var k=c.time(),d=f?k+f:c.lasttime;f=c.nc.getScrollLeft();var n=c.nc.getScrollTop(),p=c.nc.page.maxh,a=c.nc.page.maxw;c.speedx=0=k-d;if(0>n||n>p||0>f||f>a)d=!1;f=c.speedx&&d?c.speedx:!1;if(c.speedy&&d&&c.speedy||f){var s=Math.max(16,c.steptime);50e||e>a)&&(d=.1);c.speedy&&(r=Math.floor(c.lastscrolly-c.speedy*(1-c.demulxy)),c.lastscrolly=r,0>r||r>p)&&(d=.1);c.demulxy=Math.min(1,c.demulxy+d);c.nc.synched("domomentum2d",function(){c.speedx&&(c.nc.getScrollLeft()!= +c.chkx&&c.stop(),c.chkx=e,c.nc.setScrollLeft(e));c.speedy&&(c.nc.getScrollTop()!=c.chky&&c.stop(),c.chky=r,c.nc.setScrollTop(r));c.timer||(c.nc.hideCursor(),c.doSnapy(e,r))});1>c.demulxy?c.timer=setTimeout(t,s):(c.stop(),c.nc.hideCursor(),c.doSnapy(e,r))};t()}else c.doSnapy(c.nc.getScrollLeft(),c.nc.getScrollTop())}},w=f.fn.scrollTop;f.cssHooks.pageYOffset={get:function(k,c,h){return(c=f.data(k,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollTop():w.call(k)},set:function(k,c){var h=f.data(k,"__nicescroll")|| +!1;h&&h.ishwscroll?h.setScrollTop(parseInt(c)):w.call(k,c);return this}};f.fn.scrollTop=function(k){if("undefined"==typeof k){var c=this[0]?f.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollTop():w.call(this)}return this.each(function(){var c=f.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollTop(parseInt(k)):w.call(f(this),k)})};var B=f.fn.scrollLeft;f.cssHooks.pageXOffset={get:function(k,c,h){return(c=f.data(k,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollLeft():B.call(k)}, +set:function(k,c){var h=f.data(k,"__nicescroll")||!1;h&&h.ishwscroll?h.setScrollLeft(parseInt(c)):B.call(k,c);return this}};f.fn.scrollLeft=function(k){if("undefined"==typeof k){var c=this[0]?f.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollLeft():B.call(this)}return this.each(function(){var c=f.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollLeft(parseInt(k)):B.call(f(this),k)})};var C=function(k){var c=this;this.length=0;this.name="nicescrollarray";this.each=function(d){for(var f= +0,h=0;f 57) + { + var value = $(this).val(); + /* '-' only allowed at start and if negative numbers allowed */ + if($.inArray('-', value.split('')) !== 0 && negative && key == 45 && (value.length === 0 || parseInt($.fn.getSelectionStart(this), 10) === 0)) { return true; } + /* only one decimal separator allowed */ + if(decimal && key == decimal.charCodeAt(0) && $.inArray(decimal, value.split('')) != -1) + { + allow = false; + } + // check for other keys that have special purposes + if( + key != 8 /* backspace */ && + key != 9 /* tab */ && + key != 13 /* enter */ && + key != 35 /* end */ && + key != 36 /* home */ && + key != 37 /* left */ && + key != 39 /* right */ && + key != 46 /* del */ + ) + { + allow = false; + } + else + { + // for detecting special keys (listed above) + // IE does not support 'charCode' and ignores them in keypress anyway + if(typeof e.charCode != "undefined") + { + // special keys have 'keyCode' and 'which' the same (e.g. backspace) + if(e.keyCode == e.which && e.which !== 0) + { + allow = true; + // . and delete share the same code, don't allow . (will be set to true later if it is the decimal point) + if(e.which == 46) { allow = false; } + } + // or keyCode != 0 and 'charCode'/'which' = 0 + else if(e.keyCode !== 0 && e.charCode === 0 && e.which === 0) + { + allow = true; + } + } + } + // if key pressed is the decimal and it is not already in the field + if(decimal && key == decimal.charCodeAt(0)) + { + if($.inArray(decimal, value.split('')) == -1) + { + allow = true; + } + else + { + allow = false; + } + } + } + else + { + allow = true; + // remove extra decimal places + if(decimal && decimalPlaces > 0) + { + var selectionStart = $.fn.getSelectionStart(this); + var selectionEnd = $.fn.getSelectionEnd(this); + var dot = $.inArray(decimal, $(this).val().split('')); + if (selectionStart === selectionEnd && dot >= 0 && selectionStart > dot && $(this).val().length > dot + decimalPlaces) { + allow = false; + } + } + + } + return allow; +}; + +$.fn.numeric.keyup = function(e) +{ + var val = $(this).val(); + if(val && val.length > 0) + { + // get carat (cursor) position + var carat = $.fn.getSelectionStart(this); + var selectionEnd = $.fn.getSelectionEnd(this); + // get decimal character and determine if negatives are allowed + var decimal = $.data(this, "numeric.decimal"); + var negative = $.data(this, "numeric.negative"); + var decimalPlaces = $.data(this, "numeric.decimalPlaces"); + + // prepend a 0 if necessary + if(decimal !== "" && decimal !== null) + { + // find decimal point + var dot = $.inArray(decimal, val.split('')); + // if dot at start, add 0 before + if(dot === 0) + { + this.value = "0" + val; + carat++; + selectionEnd++; + } + // if dot at position 1, check if there is a - symbol before it + if(dot == 1 && val.charAt(0) == "-") + { + this.value = "-0" + val.substring(1); + carat++; + selectionEnd++; + } + val = this.value; + } + + // if pasted in, only allow the following characters + var validChars = [0,1,2,3,4,5,6,7,8,9,'-',decimal]; + // get length of the value (to loop through) + var length = val.length; + // loop backwards (to prevent going out of bounds) + for(var i = length - 1; i >= 0; i--) + { + var ch = val.charAt(i); + // remove '-' if it is in the wrong place + if(i !== 0 && ch == "-") + { + val = val.substring(0, i) + val.substring(i + 1); + } + // remove character if it is at the start, a '-' and negatives aren't allowed + else if(i === 0 && !negative && ch == "-") + { + val = val.substring(1); + } + var validChar = false; + // loop through validChars + for(var j = 0; j < validChars.length; j++) + { + // if it is valid, break out the loop + if(ch == validChars[j]) + { + validChar = true; + break; + } + } + // if not a valid character, or a space, remove + if(!validChar || ch == " ") + { + val = val.substring(0, i) + val.substring(i + 1); + } + } + // remove extra decimal characters + var firstDecimal = $.inArray(decimal, val.split('')); + if(firstDecimal > 0) + { + for(var k = length - 1; k > firstDecimal; k--) + { + var chch = val.charAt(k); + // remove decimal character + if(chch == decimal) + { + val = val.substring(0, k) + val.substring(k + 1); + } + } + } + + // remove extra decimal places + if(decimal && decimalPlaces > 0) + { + var dot = $.inArray(decimal, val.split('')); + if (dot >= 0) + { + val = val.substring(0, dot + decimalPlaces + 1); + selectionEnd = Math.min(val.length, selectionEnd); + } + } + // set the value and prevent the cursor moving to the end + this.value = val; + $.fn.setSelection(this, [carat, selectionEnd]); + } +}; + +$.fn.numeric.blur = function() +{ + var decimal = $.data(this, "numeric.decimal"); + var callback = $.data(this, "numeric.callback"); + var negative = $.data(this, "numeric.negative"); + var val = this.value; + if(val !== "") + { + var re = new RegExp("^" + (negative?"-?":"") + "\\d+$|^" + (negative?"-?":"") + "\\d*" + decimal + "\\d+$"); + if(!re.exec(val)) + { + callback.apply(this); + } + } +}; + +$.fn.removeNumeric = function() +{ + return this.data("numeric.decimal", null).data("numeric.negative", null).data("numeric.callback", null).data("numeric.decimalPlaces", null).unbind("keypress", $.fn.numeric.keypress).unbind("keyup", $.fn.numeric.keyup).unbind("blur", $.fn.numeric.blur); +}; + +// Based on code from http://javascript.nwbox.com/cursor_position/ (Diego Perini ) +$.fn.getSelectionStart = function(o) +{ + if(o.type === "number"){ + return undefined; + } + else if (o.createTextRange && document.selection) + { + var r = document.selection.createRange().duplicate(); + r.moveEnd('character', o.value.length); + if (r.text == '') return o.value.length; + + return Math.max(0, o.value.lastIndexOf(r.text)); + } else { + try { return o.selectionStart; } + catch(e) { return 0; } + } +}; + +// Based on code from http://javascript.nwbox.com/cursor_position/ (Diego Perini ) +$.fn.getSelectionEnd = function(o) +{ + if(o.type === "number"){ + return undefined; + } + else if (o.createTextRange && document.selection) { + var r = document.selection.createRange().duplicate() + r.moveStart('character', -o.value.length) + return r.text.length + } else return o.selectionEnd +} + +// set the selection, o is the object (input), p is the position ([start, end] or just start) +$.fn.setSelection = function(o, p) +{ + // if p is number, start and end are the same + if(typeof p == "number") { p = [p, p]; } + // only set if p is an array of length 2 + if(p && p.constructor == Array && p.length == 2) + { + if(o.type === "number") { + o.focus(); + } + else if (o.createTextRange) + { + var r = o.createTextRange(); + r.collapse(true); + r.moveStart('character', p[0]); + r.moveEnd('character', p[1] - p[0]); + r.select(); + } + else { + o.focus(); + try{ + if(o.setSelectionRange) + { + o.setSelectionRange(p[0], p[1]); + } + } catch(e) { + } + } + } +}; + +})); diff --git a/LiveChat/ClientComponents/moment.js/moment.min.js b/LiveChat/ClientComponents/moment.js/moment.min.js new file mode 100644 index 0000000..8e6866a --- /dev/null +++ b/LiveChat/ClientComponents/moment.js/moment.min.js @@ -0,0 +1,7 @@ +//! moment.js +//! version : 2.10.6 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Hc.apply(null,arguments)}function b(a){Hc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c0)for(c in Jc)d=Jc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),Kc===!1&&(Kc=!0,a.updateOffset(this),Kc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){return 0>a?Math.ceil(a):Math.floor(a)}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=p(b)),c}function r(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function s(){}function t(a){return a?a.toLowerCase().replace("_","-"):a}function u(a){for(var b,c,d,e,f=0;f0;){if(d=v(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&r(e,c,!0)>=b-1)break;b--}f++}return null}function v(a){var b=null;if(!Lc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ic._abbr,require("./locale/"+a),w(b)}catch(c){}return Lc[a]}function w(a,b){var c;return a&&(c="undefined"==typeof b?y(a):x(a,b),c&&(Ic=c)),Ic._abbr}function x(a,b){return null!==b?(b.abbr=a,Lc[a]=Lc[a]||new s,Lc[a].set(b),w(a),Lc[a]):(delete Lc[a],null)}function y(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ic;if(!c(a)){if(b=v(a))return b;a=[a]}return u(a)}function z(a,b){var c=a.toLowerCase();Mc[c]=Mc[c+"s"]=Mc[b]=a}function A(a){return"string"==typeof a?Mc[a]||Mc[a.toLowerCase()]:void 0}function B(a){var b,c,d={};for(c in a)f(a,c)&&(b=A(c),b&&(d[b]=a[c]));return d}function C(b,c){return function(d){return null!=d?(E(this,b,d),a.updateOffset(this,c),this):D(this,b)}}function D(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function E(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function F(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=A(a),"function"==typeof this[a])return this[a](b);return this}function G(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function H(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Qc[a]=e),b&&(Qc[b[0]]=function(){return G(e.apply(this,arguments),b[1],b[2])}),c&&(Qc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function I(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function J(a){var b,c,d=a.match(Nc);for(b=0,c=d.length;c>b;b++)Qc[d[b]]?d[b]=Qc[d[b]]:d[b]=I(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function K(a,b){return a.isValid()?(b=L(b,a.localeData()),Pc[b]=Pc[b]||J(b),Pc[b](a)):a.localeData().invalidDate()}function L(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Oc.lastIndex=0;d>=0&&Oc.test(a);)a=a.replace(Oc,c),Oc.lastIndex=0,d-=1;return a}function M(a){return"function"==typeof a&&"[object Function]"===Object.prototype.toString.call(a)}function N(a,b,c){dd[a]=M(b)?b:function(a){return a&&c?c:b}}function O(a,b){return f(dd,a)?dd[a](b._strict,b._locale):new RegExp(P(a))}function P(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=q(a)}),c=0;cd;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function X(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),T(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function Y(b){return null!=b?(X(this,b),a.updateOffset(this,!0),this):D(this,"Month")}function Z(){return T(this.year(),this.month())}function $(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[gd]<0||c[gd]>11?gd:c[hd]<1||c[hd]>T(c[fd],c[gd])?hd:c[id]<0||c[id]>24||24===c[id]&&(0!==c[jd]||0!==c[kd]||0!==c[ld])?id:c[jd]<0||c[jd]>59?jd:c[kd]<0||c[kd]>59?kd:c[ld]<0||c[ld]>999?ld:-1,j(a)._overflowDayOfYear&&(fd>b||b>hd)&&(b=hd),j(a).overflow=b),a}function _(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function aa(a,b){var c=!0;return g(function(){return c&&(_(a+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function ba(a,b){od[a]||(_(b),od[a]=!0)}function ca(a){var b,c,d=a._i,e=pd.exec(d);if(e){for(j(a).iso=!0,b=0,c=qd.length;c>b;b++)if(qd[b][1].exec(d)){a._f=qd[b][0];break}for(b=0,c=rd.length;c>b;b++)if(rd[b][1].exec(d)){a._f+=(e[6]||" ")+rd[b][0];break}d.match(ad)&&(a._f+="Z"),va(a)}else a._isValid=!1}function da(b){var c=sd.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ca(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ea(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fa(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ga(a){return ha(a)?366:365}function ha(a){return a%4===0&&a%100!==0||a%400===0}function ia(){return ha(this.year())}function ja(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Da(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ka(a){return ja(a,this._week.dow,this._week.doy).week}function la(){return this._week.dow}function ma(){return this._week.doy}function na(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function oa(a){var b=ja(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function pa(a,b,c,d,e){var f,g=6+e-d,h=fa(a,0,1+g),i=h.getUTCDay();return e>i&&(i+=7),c=null!=c?1*c:e,f=1+g+7*(b-1)-i+c,{year:f>0?a:a-1,dayOfYear:f>0?f:ga(a-1)+f}}function qa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ra(a,b,c){return null!=a?a:null!=b?b:c}function sa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ta(a){var b,c,d,e,f=[];if(!a._d){for(d=sa(a),a._w&&null==a._a[hd]&&null==a._a[gd]&&ua(a),a._dayOfYear&&(e=ra(a._a[fd],d[fd]),a._dayOfYear>ga(e)&&(j(a)._overflowDayOfYear=!0),c=fa(e,0,a._dayOfYear),a._a[gd]=c.getUTCMonth(),a._a[hd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[id]&&0===a._a[jd]&&0===a._a[kd]&&0===a._a[ld]&&(a._nextDay=!0,a._a[id]=0),a._d=(a._useUTC?fa:ea).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[id]=24)}}function ua(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ra(b.GG,a._a[fd],ja(Da(),1,4).year),d=ra(b.W,1),e=ra(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ra(b.gg,a._a[fd],ja(Da(),f,g).year),d=ra(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=pa(c,d,e,g,f),a._a[fd]=h.year,a._dayOfYear=h.dayOfYear}function va(b){if(b._f===a.ISO_8601)return void ca(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=L(b._f,b._locale).match(Nc)||[],c=0;c0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Qc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),S(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[id]<=12&&b._a[id]>0&&(j(b).bigHour=void 0),b._a[id]=wa(b._locale,b._a[id],b._meridiem),ta(b),$(b)}function wa(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function xa(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;ef)&&(d=f,c=b));g(a,c||b)}function ya(a){if(!a._d){var b=B(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ta(a)}}function za(a){var b=new n($(Aa(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Aa(a){var b=a._i,e=a._f;return a._locale=a._locale||y(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),o(b)?new n($(b)):(c(e)?xa(a):e?va(a):d(b)?a._d=b:Ba(a),a))}function Ba(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?da(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ta(b)):"object"==typeof f?ya(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ca(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,za(f)}function Da(a,b,c,d){return Ca(a,b,c,d,!1)}function Ea(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Da();for(d=b[0],e=1;ea&&(a=-a,c="-"),c+G(~~(a/60),2)+b+G(~~a%60,2)})}function Ka(a){var b=(a||"").match(ad)||[],c=b[b.length-1]||[],d=(c+"").match(xd)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?e:-e}function La(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Da(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Da(b).local()}function Ma(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Na(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ka(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ma(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?bb(this,Ya(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ma(this)}function Oa(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Pa(a){return this.utcOffset(0,a)}function Qa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ma(this),"m")),this}function Ra(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ka(this._i)),this}function Sa(a){return a=a?Da(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Ta(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ua(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var a={};if(m(a,this),a=Aa(a),a._a){var b=a._isUTC?h(a._a):Da(a._a);this._isDSTShifted=this.isValid()&&r(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Va(){return!this._isUTC}function Wa(){return this._isUTC}function Xa(){return this._isUTC&&0===this._offset}function Ya(a,b){var c,d,e,g=a,h=null;return Ia(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=yd.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[hd])*c,h:q(h[id])*c,m:q(h[jd])*c,s:q(h[kd])*c,ms:q(h[ld])*c}):(h=zd.exec(a))?(c="-"===h[1]?-1:1,g={y:Za(h[2],c),M:Za(h[3],c),d:Za(h[4],c),h:Za(h[5],c),m:Za(h[6],c),s:Za(h[7],c),w:Za(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=_a(Da(g.from),Da(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ha(g),Ia(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Za(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function $a(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function _a(a,b){var c;return b=La(b,a),a.isBefore(b)?c=$a(a,b):(c=$a(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function ab(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(ba(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ya(c,d),bb(this,e,a),this}}function bb(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&E(b,"Date",D(b,"Date")+g*d),h&&X(b,D(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function cb(a,b){var c=a||Da(),d=La(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(b&&b[f]||this.localeData().calendar(f,this,Da(c)))}function db(){return new n(this)}function eb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this>+a):(c=o(a)?+a:+Da(a),c<+this.clone().startOf(b))}function fb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+a>+this):(c=o(a)?+a:+Da(a),+this.clone().endOf(b)b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function kb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function lb(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=Da([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Pb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Kb(a,this.localeData()),this.add(a-b,"d")):b}function Qb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Rb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Sb(a,b){H(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Tb(a,b){return b._meridiemParse}function Ub(a){return"p"===(a+"").toLowerCase().charAt(0)}function Vb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wb(a,b){b[ld]=q(1e3*("0."+a))}function Xb(){return this._isUTC?"UTC":""}function Yb(){return this._isUTC?"Coordinated Universal Time":""}function Zb(a){return Da(1e3*a)}function $b(){return Da.apply(null,arguments).parseZone()}function _b(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function bc(){return this._invalidDate}function cc(a){return this._ordinal.replace("%d",a)}function dc(a){return a}function ec(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function gc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function hc(a,b,c,d){var e=y(),f=h().set(d,b);return e[c](f,a)}function ic(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return hc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=hc(a,f,c,e);return g}function jc(a,b){return ic(a,b,"months",12,"month")}function kc(a,b){return ic(a,b,"monthsShort",12,"month")}function lc(a,b){return ic(a,b,"weekdays",7,"day")}function mc(a,b){return ic(a,b,"weekdaysShort",7,"day")}function nc(a,b){return ic(a,b,"weekdaysMin",7,"day")}function oc(){var a=this._data;return this._milliseconds=Wd(this._milliseconds),this._days=Wd(this._days),this._months=Wd(this._months),a.milliseconds=Wd(a.milliseconds),a.seconds=Wd(a.seconds),a.minutes=Wd(a.minutes),a.hours=Wd(a.hours),a.months=Wd(a.months),a.years=Wd(a.years),this}function pc(a,b,c,d){var e=Ya(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function qc(a,b){return pc(this,a,b,1)}function rc(a,b){return pc(this,a,b,-1)}function sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*sc(vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=p(f/1e3),i.seconds=a%60,b=p(a/60),i.minutes=b%60,c=p(b/60),i.hours=c%24,g+=p(c/24),e=p(uc(g)),h+=e,g-=sc(vc(e)),d=p(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function uc(a){return 4800*a/146097}function vc(a){return 146097*a/4800}function wc(a){var b,c,d=this._milliseconds;if(a=A(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)}function yc(a){return function(){return this.as(a)}}function zc(a){return a=A(a),this[a+"s"]()}function Ac(a){return function(){return this._data[a]}}function Bc(){return p(this.days()/7)}function Cc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Dc(a,b,c){var d=Ya(a).abs(),e=ke(d.as("s")),f=ke(d.as("m")),g=ke(d.as("h")),h=ke(d.as("d")),i=ke(d.as("M")),j=ke(d.as("y")),k=e0,k[4]=c,Cc.apply(null,k)}function Ec(a,b){return void 0===le[a]?!1:void 0===b?le[a]:(le[a]=b,!0)}function Fc(a){var b=this.localeData(),c=Dc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Gc(){var a,b,c,d=me(this._milliseconds)/1e3,e=me(this._days),f=me(this._months);a=p(d/60),b=p(a/60),d%=60,a%=60,c=p(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Hc,Ic,Jc=a.momentProperties=[],Kc=!1,Lc={},Mc={},Nc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Oc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pc={},Qc={},Rc=/\d/,Sc=/\d\d/,Tc=/\d{3}/,Uc=/\d{4}/,Vc=/[+-]?\d{6}/,Wc=/\d\d?/,Xc=/\d{1,3}/,Yc=/\d{1,4}/,Zc=/[+-]?\d{1,6}/,$c=/\d+/,_c=/[+-]?\d+/,ad=/Z|[+-]\d\d:?\d\d/gi,bd=/[+-]?\d+(\.\d{1,3})?/,cd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,dd={},ed={},fd=0,gd=1,hd=2,id=3,jd=4,kd=5,ld=6;H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),H("MMMM",0,0,function(a){return this.localeData().months(this,a)}),z("month","M"),N("M",Wc),N("MM",Wc,Sc),N("MMM",cd),N("MMMM",cd),Q(["M","MM"],function(a,b){b[gd]=q(a)-1}),Q(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[gd]=e:j(c).invalidMonth=a});var md="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),nd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),od={};a.suppressDeprecationWarnings=!1;var pd=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,qd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],rd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],sd=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),z("year","y"),N("Y",_c),N("YY",Wc,Sc),N("YYYY",Yc,Uc),N("YYYYY",Zc,Vc),N("YYYYYY",Zc,Vc),Q(["YYYYY","YYYYYY"],fd),Q("YYYY",function(b,c){c[fd]=2===b.length?a.parseTwoDigitYear(b):q(b)}),Q("YY",function(b,c){c[fd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return q(a)+(q(a)>68?1900:2e3)};var td=C("FullYear",!1);H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),z("week","w"),z("isoWeek","W"),N("w",Wc),N("ww",Wc,Sc),N("W",Wc),N("WW",Wc,Sc),R(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=q(a)});var ud={dow:0,doy:6};H("DDD",["DDDD",3],"DDDo","dayOfYear"),z("dayOfYear","DDD"),N("DDD",Xc),N("DDDD",Tc),Q(["DDD","DDDD"],function(a,b,c){c._dayOfYear=q(a)}),a.ISO_8601=function(){};var vd=aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return this>a?this:a}),wd=aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return a>this?this:a});Ja("Z",":"),Ja("ZZ",""),N("Z",ad),N("ZZ",ad),Q(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ka(a)});var xd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var yd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,zd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ya.fn=Ha.prototype;var Ad=ab(1,"add"),Bd=ab(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var Cd=aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Db("gggg","weekYear"),Db("ggggg","weekYear"),Db("GGGG","isoWeekYear"),Db("GGGGG","isoWeekYear"),z("weekYear","gg"),z("isoWeekYear","GG"),N("G",_c),N("g",_c),N("GG",Wc,Sc),N("gg",Wc,Sc),N("GGGG",Yc,Uc),N("gggg",Yc,Uc),N("GGGGG",Zc,Vc),N("ggggg",Zc,Vc),R(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=q(a)}),R(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),H("Q",0,0,"quarter"),z("quarter","Q"),N("Q",Rc),Q("Q",function(a,b){b[gd]=3*(q(a)-1)}),H("D",["DD",2],"Do","date"),z("date","D"),N("D",Wc),N("DD",Wc,Sc),N("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),Q(["D","DD"],hd),Q("Do",function(a,b){b[hd]=q(a.match(Wc)[0],10)});var Dd=C("Date",!0);H("d",0,"do","day"),H("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),H("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),H("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),z("day","d"),z("weekday","e"),z("isoWeekday","E"),N("d",Wc),N("e",Wc),N("E",Wc),N("dd",cd),N("ddd",cd),N("dddd",cd),R(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),R(["d","e","E"],function(a,b,c,d){b[d]=q(a)});var Ed="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Fd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");H("H",["HH",2],0,"hour"),H("h",["hh",2],0,function(){return this.hours()%12||12}),Sb("a",!0),Sb("A",!1),z("hour","h"),N("a",Tb),N("A",Tb),N("H",Wc),N("h",Wc),N("HH",Wc,Sc),N("hh",Wc,Sc),Q(["H","HH"],id),Q(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),Q(["h","hh"],function(a,b,c){b[id]=q(a),j(c).bigHour=!0});var Hd=/[ap]\.?m?\.?/i,Id=C("Hours",!0);H("m",["mm",2],0,"minute"),z("minute","m"),N("m",Wc),N("mm",Wc,Sc),Q(["m","mm"],jd);var Jd=C("Minutes",!1);H("s",["ss",2],0,"second"),z("second","s"),N("s",Wc),N("ss",Wc,Sc),Q(["s","ss"],kd);var Kd=C("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),z("millisecond","ms"),N("S",Xc,Rc),N("SS",Xc,Sc),N("SSS",Xc,Tc);var Ld;for(Ld="SSSS";Ld.length<=9;Ld+="S")N(Ld,$c);for(Ld="S";Ld.length<=9;Ld+="S")Q(Ld,Wb);var Md=C("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var Nd=n.prototype;Nd.add=Ad,Nd.calendar=cb,Nd.clone=db,Nd.diff=ib,Nd.endOf=ub,Nd.format=mb,Nd.from=nb,Nd.fromNow=ob,Nd.to=pb,Nd.toNow=qb,Nd.get=F,Nd.invalidAt=Cb,Nd.isAfter=eb,Nd.isBefore=fb,Nd.isBetween=gb,Nd.isSame=hb,Nd.isValid=Ab,Nd.lang=Cd,Nd.locale=rb,Nd.localeData=sb,Nd.max=wd,Nd.min=vd,Nd.parsingFlags=Bb,Nd.set=F,Nd.startOf=tb,Nd.subtract=Bd,Nd.toArray=yb,Nd.toObject=zb,Nd.toDate=xb,Nd.toISOString=lb,Nd.toJSON=lb,Nd.toString=kb,Nd.unix=wb,Nd.valueOf=vb,Nd.year=td,Nd.isLeapYear=ia,Nd.weekYear=Fb,Nd.isoWeekYear=Gb,Nd.quarter=Nd.quarters=Jb,Nd.month=Y,Nd.daysInMonth=Z,Nd.week=Nd.weeks=na,Nd.isoWeek=Nd.isoWeeks=oa,Nd.weeksInYear=Ib,Nd.isoWeeksInYear=Hb,Nd.date=Dd,Nd.day=Nd.days=Pb,Nd.weekday=Qb,Nd.isoWeekday=Rb,Nd.dayOfYear=qa,Nd.hour=Nd.hours=Id,Nd.minute=Nd.minutes=Jd,Nd.second=Nd.seconds=Kd, +Nd.millisecond=Nd.milliseconds=Md,Nd.utcOffset=Na,Nd.utc=Pa,Nd.local=Qa,Nd.parseZone=Ra,Nd.hasAlignedHourOffset=Sa,Nd.isDST=Ta,Nd.isDSTShifted=Ua,Nd.isLocal=Va,Nd.isUtcOffset=Wa,Nd.isUtc=Xa,Nd.isUTC=Xa,Nd.zoneAbbr=Xb,Nd.zoneName=Yb,Nd.dates=aa("dates accessor is deprecated. Use date instead.",Dd),Nd.months=aa("months accessor is deprecated. Use month instead",Y),Nd.years=aa("years accessor is deprecated. Use year instead",td),Nd.zone=aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Oa);var Od=Nd,Pd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Qd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Rd="Invalid date",Sd="%d",Td=/\d{1,2}/,Ud={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Vd=s.prototype;Vd._calendar=Pd,Vd.calendar=_b,Vd._longDateFormat=Qd,Vd.longDateFormat=ac,Vd._invalidDate=Rd,Vd.invalidDate=bc,Vd._ordinal=Sd,Vd.ordinal=cc,Vd._ordinalParse=Td,Vd.preparse=dc,Vd.postformat=dc,Vd._relativeTime=Ud,Vd.relativeTime=ec,Vd.pastFuture=fc,Vd.set=gc,Vd.months=U,Vd._months=md,Vd.monthsShort=V,Vd._monthsShort=nd,Vd.monthsParse=W,Vd.week=ka,Vd._week=ud,Vd.firstDayOfYear=ma,Vd.firstDayOfWeek=la,Vd.weekdays=Lb,Vd._weekdays=Ed,Vd.weekdaysMin=Nb,Vd._weekdaysMin=Gd,Vd.weekdaysShort=Mb,Vd._weekdaysShort=Fd,Vd.weekdaysParse=Ob,Vd.isPM=Ub,Vd._meridiemParse=Hd,Vd.meridiem=Vb,w("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=aa("moment.lang is deprecated. Use moment.locale instead.",w),a.langData=aa("moment.langData is deprecated. Use moment.localeData instead.",y);var Wd=Math.abs,Xd=yc("ms"),Yd=yc("s"),Zd=yc("m"),$d=yc("h"),_d=yc("d"),ae=yc("w"),be=yc("M"),ce=yc("y"),de=Ac("milliseconds"),ee=Ac("seconds"),fe=Ac("minutes"),ge=Ac("hours"),he=Ac("days"),ie=Ac("months"),je=Ac("years"),ke=Math.round,le={s:45,m:45,h:22,d:26,M:11},me=Math.abs,ne=Ha.prototype;ne.abs=oc,ne.add=qc,ne.subtract=rc,ne.as=wc,ne.asMilliseconds=Xd,ne.asSeconds=Yd,ne.asMinutes=Zd,ne.asHours=$d,ne.asDays=_d,ne.asWeeks=ae,ne.asMonths=be,ne.asYears=ce,ne.valueOf=xc,ne._bubble=tc,ne.get=zc,ne.milliseconds=de,ne.seconds=ee,ne.minutes=fe,ne.hours=ge,ne.days=he,ne.weeks=Bc,ne.months=ie,ne.years=je,ne.humanize=Fc,ne.toISOString=Gc,ne.toString=Gc,ne.toJSON=Gc,ne.locale=rb,ne.localeData=sb,ne.toIsoString=aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Gc),ne.lang=Cd,H("X",0,0,"unix"),H("x",0,0,"valueOf"),N("x",_c),N("X",bd),Q("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),Q("x",function(a,b,c){c._d=new Date(q(a))}),a.version="2.10.6",b(Da),a.fn=Od,a.min=Fa,a.max=Ga,a.utc=h,a.unix=Zb,a.months=jc,a.isDate=d,a.locale=w,a.invalid=l,a.duration=Ya,a.isMoment=o,a.weekdays=lc,a.parseZone=$b,a.localeData=y,a.isDuration=Ia,a.monthsShort=kc,a.weekdaysMin=nc,a.defineLocale=x,a.weekdaysShort=mc,a.normalizeUnits=A,a.relativeTimeThreshold=Ec;var oe=a;return oe}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/ng-table/ng-table.min.js b/LiveChat/ClientComponents/ng-table/ng-table.min.js new file mode 100644 index 0000000..d816a92 --- /dev/null +++ b/LiveChat/ClientComponents/ng-table/ng-table.min.js @@ -0,0 +1,4 @@ +/*! ngTable v0.8.3 by Vitalii Savchuk(esvit666@gmail.com) - https://github.com/esvit/ng-table - New BSD License */ + +!function(a,b){"use strict";return"function"==typeof define&&define.amd?void define(["angular"],function(a){return b(a)}):b(a)}(window.angular||null,function(a){"use strict";var b=a.module("ngTable",[]);return function(){function b(b){function c(b,c){var f=b.charAt(0).toUpperCase()+b.substring(1),g={};return g["on"+f]=d(b),g["publish"+f]=e(b),a.extend(c,g)}function d(c){return function(d){var e=a.identity,g=b;if(2===arguments.length?a.isFunction(arguments[1].$new)?g=arguments[1]:e=arguments[1]:arguments.length>2&&(g=arguments[1],e=arguments[2]),a.isObject(e)){var h=e;e=function(a){return a===h}}return g.$on("ngTable:"+c,function(a,b){if(!b.isNullInstance){var c=f(arguments,2),g=[b].concat(c);e.apply(this,g)&&d.apply(this,g)}})}}function e(a){return function(){var c=["ngTable:"+a].concat(Array.prototype.slice.call(arguments));b.$broadcast.apply(b,c)}}function f(a,b){return Array.prototype.slice.call(a,null==b?1:b)}var g={};return g=c("afterCreated",g),g=c("afterReloadData",g),g=c("datasetChanged",g),g=c("pagesChanged",g)}a.module("ngTable").factory("ngTableEventsChannel",b),b.$inject=["$rootScope"]}(),function(){function b(){function b(){c()}function c(){f=g}function d(b){var c=a.extend({},f,b);c.aliasUrls=a.extend({},f.aliasUrls,b.aliasUrls),f=c}function e(){function b(a,b){return-1!==a.indexOf("/")?a:e.getUrlForAlias(a,b)}function c(a){return f.aliasUrls[a]||f.defaultBaseUrl+a+f.defaultExt}var d,e={config:d,getTemplateUrl:b,getUrlForAlias:c};return Object.defineProperty(e,"config",{get:function(){return d=d||a.copy(f)},enumerable:!0}),e}var f,g={defaultBaseUrl:"ng-table/filters/",defaultExt:".html",aliasUrls:{}};this.$get=e,this.resetConfigs=c,this.setConfig=d,b(),e.$inject=[]}a.module("ngTable").provider("ngTableFilterConfig",b),b.$inject=[]}(),function(){function b(){function a(a){function c(c,d){if(null==c)return[];var e=d.hasFilter()?a(b.filterFilterName)(c,d.filter(!0)):c,f=d.orderBy(),g=f.length?a(b.sortingFilterName)(e,f):e,h=g.slice((d.page()-1)*d.count(),d.page()*d.count());return d.total(g.length),h}return c}var b=this;b.$get=a,b.filterFilterName="filter",b.sortingFilterName="orderBy",a.$inject=["$filter"]}a.module("ngTable").provider("ngTableDefaultGetData",b),b.$inject=[]}(),function(){function b(a){function b(b){return function(){var c=a.defer(),d=b.apply(this,[c].concat(Array.prototype.slice.call(arguments)));return d||(d=c.promise),d}}return b}a.module("ngTable").factory("ngTableGetDataBcShim",b),b.$inject=["$q"]}(),b.value("ngTableDefaults",{params:{},settings:{}}),b.factory("NgTableParams",["$q","$log","ngTableDefaults","ngTableGetDataBcShim","ngTableDefaultGetData","ngTableEventsChannel",function(b,c,d,e,f,g){var h=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},i=function(i,j){function k(){var a=s.getDataFnAdaptor(s.getData);return b.when(a.call(s,o))}function l(){var a=s.getGroupsFnAdaptor(s.getGroups);return b.when(a.call(s,s.groupBy,o))}function m(a){var c=s.interceptors||[];return c.reduce(function(a,c){var d=c.response&&c.response.bind(c)||b.when,e=c.responseError&&c.responseError.bind(c)||b.reject;return a.then(function(a){return d(a,o)},function(a){return e(a,o)})},a())}"boolean"==typeof i&&(this.isNullInstance=!0);var n,o=this,p=!1,q=function(){s.debugMode&&c.debug&&c.debug.apply(this,arguments)};this.data=[],this.parameters=function(b,c){if(c=c||!1,a.isDefined(b)){for(var d in b){var e=b[d];if(c&&d.indexOf("[")>=0){for(var f=d.split(/\[(.*)\]/).reverse(),g="",i=0,j=f.length;j>i;i++){var k=f[i];if(""!==k){var l=e;e={},e[g=k]=h(l)?parseFloat(l):l}}"sorting"===g&&(r[g]={}),r[g]=a.extend(r[g]||{},e[g])}else r[d]=h(b[d])?parseFloat(b[d]):b[d]}return q("ngTable: set parameters",r),this}return r},this.settings=function(b){if(a.isDefined(b)){a.isArray(b.data)&&(b.total=b.data.length),b.getData&&b.getData.length>1&&(b.getDataFnAdaptor=e),b.getGroups&&b.getGroups.length>2&&(b.getGroupsFnAdaptor=e);var c=s.data;s=a.extend(s,b);var d=b.hasOwnProperty("data")&&b.data!=c;return d&&(p&&this.page(1),p=!1,g.publishDatasetChanged(this,b.data,c)),q("ngTable: set settings",s),this}return s},this.page=function(b){return a.isDefined(b)?this.parameters({page:b}):r.page},this.total=function(b){return a.isDefined(b)?this.settings({total:b}):s.total},this.count=function(b){return a.isDefined(b)?this.parameters({count:b,page:1}):r.count},this.filter=function(b){if(a.isDefined(b)&&a.isObject(b))return this.parameters({filter:b,page:1});if(b===!0){for(var c=Object.keys(r.filter),d={},e=0;ed?6:d,i=[],h=Math.ceil(b/c),h>1){i.push({type:"prev",number:Math.max(1,a-1),active:a>1}),i.push({type:"first",number:1,active:a>1,current:1===a}),f=Math.round((s.paginationMaxBlocks-s.paginationMinBlocks)/2),g=Math.max(2,a-f),e=Math.min(h-1,a+2*f-(a-g)),g=Math.max(2,g-(2*f-(e-g)));for(var j=g;e>=j;)i.push(j===g&&2!==j||j===e&&j!==h-1?{type:"more",active:!1}:{type:"page",number:j,active:a!==j,current:a===j}),j++;i.push({type:"last",number:h,active:a!==h,current:a===h}),i.push({type:"next",number:Math.min(h,a+1),active:h>a})}return i},this.isDataReloadRequired=function(){return!p||!a.equals(r,n)},this.hasFilter=function(){return Object.keys(this.filter(!0)).length>0},this.hasFilterChanges=function(){return!a.equals(r&&r.filter,n&&n.filter)},this.url=function(b){b=b||!1;var c=b?[]:{};for(var d in r)if(r.hasOwnProperty(d)){var e=r[d],f=encodeURIComponent(d);if("object"==typeof e){for(var g in e)if(!a.isUndefined(e[g])&&""!==e[g]){var h=f+"["+encodeURIComponent(g)+"]";b?c.push(h+"="+e[g]):c[h]=e[g]}}else a.isFunction(e)||a.isUndefined(e)||""===e||(b?c.push(f+"="+encodeURIComponent(e)):c[f]=encodeURIComponent(e))}return c},this.reload=function(){var c=this,d=null;s.$loading=!0,n=a.copy(r),p=!0,d=m(s.groupBy?l:k),q("ngTable: reload data");var e=c.data;return d.then(function(a){return s.$loading=!1,c.data=a,g.publishAfterReloadData(c,a,e),c.reloadPages(),s.$scope&&s.$scope.$emit("ngTableAfterReloadData"),a})["catch"](function(a){return n=null,p=!1,b.reject(a)})},this.reloadPages=function(){var b;return function(){var c=b,d=o.generatePagesArray(o.page(),o.total(),o.count());a.equals(c,d)||(b=d,g.publishPagesChanged(this,d,c))}}();var r={page:1,count:1,filter:{},sorting:{},group:{},groupBy:null};a.extend(r,d.params);var s={$scope:null,$loading:!1,data:null,total:0,defaultSort:"desc",filterDelay:750,counts:[10,25,50,100],interceptors:[],paginationMaxBlocks:11,paginationMinBlocks:5,sortingIndicator:"span",getDataFnAdaptor:a.identity,getGroupsFnAdaptor:a.identity,getGroups:this.getGroups,getData:this.getData};return this.settings(d.settings),this.settings(j),this.parameters(i,!0),g.publishAfterCreated(this),this};return i}]),b.factory("ngTableParams",["NgTableParams",function(a){return a}]),function(){function b(a,b){a.config=b}a.module("ngTable").controller("ngTableFilterRowController",b),b.$inject=["$scope","ngTableFilterConfig"]}(),function(){function b(a){function b(b,c){var d=b.sortable&&b.sortable();if(d){var e=a.params.settings().defaultSort,f="asc"===e?"desc":"asc",g=a.params.sorting()&&a.params.sorting()[d]&&a.params.sorting()[d]===e,h=c.ctrlKey||c.metaKey?a.params.sorting():{};h[d]=g?f:e,a.params.parameters({sorting:h})}}a.sortBy=b}a.module("ngTable").controller("ngTableSorterRowController",b),b.$inject=["$scope"]}(),b.controller("ngTableController",["$scope","NgTableParams","$timeout","$parse","$compile","$attrs","$element","ngTableColumn","ngTableEventsChannel",function(b,c,d,e,f,g,h,i,j){function k(a){if(a){b.params.settings().$scope=b;var c=b.params;if(c.hasFilterChanges()){var d=function(){c.page(1),c.reload()};c.settings().filterDelay?m(d,c.settings().filterDelay):d()}else c.reload()}}function l(){function a(a,c){a.settings().groupBy?b.$groups=c:b.$data=c}function c(a,c){b.pages=c}function d(a){return b.params===a}j.onAfterReloadData(a,b,d),j.onPagesChanged(c,b,d)}b.$filterRow={},b.$loading=!1,b.hasOwnProperty("params")||(b.params=new c(!0)),b.params.settings().$scope=b;var m=function(){var a=0;return function(b,c){d.cancel(a),a=d(b,c)}}();b.$watch("params",function(a,b){a!==b&&a&&a.reload()},!1),b.$watch("params.isDataReloadRequired()",k),this.compileDirectiveTemplates=function(){if(!h.hasClass("ng-table")){b.templates={header:g.templateHeader?g.templateHeader:"ng-table/header.html",pagination:g.templatePagination?g.templatePagination:"ng-table/pager.html"},h.addClass("ng-table");var c=null,d=!1;a.forEach(h.children(),function(a){"THEAD"===a.tagName&&(d=!0)}),d||(c=a.element(document.createElement("thead")).attr("ng-include","templates.header"),h.prepend(c));var e=a.element(document.createElement("div")).attr({"ng-table-pagination":"params","template-url":"templates.pagination"});h.after(e),c&&f(c)(b),f(e)(b)}},this.loadFilterData=function(c){a.forEach(c,function(c){var d;return d=c.filterData(b,{$column:c}),d?a.isObject(d)&&a.isObject(d.promise)?(delete c.filterData,d.promise.then(function(b){a.isArray(b)||a.isFunction(b)||a.isObject(b)?a.isArray(b)&&b.unshift({title:"",id:""}):b=[],c.data=b})):c.data=d:void delete c.filterData})},this.buildColumns=function(a){return a.map(function(a){return i.buildColumn(a,b)})},this.parseNgTableDynamicExpr=function(a){if(!a||a.indexOf(" with ")>-1){var b=a.split(/\s+with\s+/);return{tableParams:b[0],columns:b[1]}}throw new Error("Parse error (expected example: ng-table-dynamic='tableParams with cols')")},this.setupBindingsToInternalScope=function(c){var d=e(c);b.$watch(d,function(c){a.isUndefined(c)||(b.paramsModel=d,b.params=c)},!1),g.showFilter&&b.$parent.$watch(g.showFilter,function(a){b.show_filter=a}),g.disableFilter&&b.$parent.$watch(g.disableFilter,function(a){b.$filterRow.disabled=a})},l()}]),b.factory("ngTableColumn",[function(){function b(b,d){var e=Object.create(b);for(var f in c)void 0===e[f]&&(e[f]=c[f]),a.isFunction(e[f])||!function(a){e[a]=function(){return b[a]}}(f),function(a){var c=e[a];e[a]=function(){return 0===arguments.length?c.call(b,d):c.apply(b,arguments)}}(f);return e}var c={"class":function(){return""},filter:function(){return!1},filterData:a.noop,headerTemplateURL:function(){return!1},headerTitle:function(){return""},sortable:function(){return!1},show:function(){return!0},title:function(){return""},titleAlt:function(){return""}};return{buildColumn:b}}]),b.directive("ngTable",["$q","$parse",function(b,c){return{restrict:"A",priority:1001,scope:!0,controller:"ngTableController",compile:function(b){var d=[],e=0,f=null;return a.forEach(a.element(b.find("tr")),function(b){b=a.element(b),b.hasClass("ng-table-group")||f||(f=b)}),f?(a.forEach(f.find("td"),function(b){var f=a.element(b);if(!f.attr("ignore-cell")||"true"!==f.attr("ignore-cell")){var g=function(a){return f.attr("x-data-"+a)||f.attr("data-"+a)||f.attr(a)},h=function(b){var e=g(b);return e?function(b,f){return c(e)(b,a.extend(f||{},{$columns:d}))}:void 0},i=g("title-alt")||g("title");i&&f.attr("data-title-text","{{"+i+"}}"),d.push({id:e++,title:h("title"),titleAlt:h("title-alt"),headerTitle:h("header-title"),sortable:h("sortable"),"class":h("header-class"),filter:h("filter"),headerTemplateURL:h("header"),filterData:h("filter-data"),show:f.attr("ng-if")?function(a){return c(f.attr("ng-if"))(a)}:void 0})}}),function(a,b,c,e){a.$columns=d=e.buildColumns(d),e.setupBindingsToInternalScope(c.ngTable),e.loadFilterData(d),e.compileDirectiveTemplates()}):void 0}}}]),b.directive("ngTableDynamic",["$parse",function(){return{restrict:"A",priority:1001,scope:!0,controller:"ngTableController",compile:function(b){var c;return a.forEach(a.element(b.find("tr")),function(b){b=a.element(b),b.hasClass("ng-table-group")||c||(c=b)}),c?(a.forEach(c.find("td"),function(b){var c=a.element(b),d=function(a){return c.attr("x-data-"+a)||c.attr("data-"+a)||c.attr(a)},e=d("title");e||c.attr("data-title-text","{{$columns[$index].titleAlt(this) || $columns[$index].title(this)}}");var f=c.attr("ng-if");f||c.attr("ng-if","$columns[$index].show(this)")}),function(a,b,c,d){var e=d.parseNgTableDynamicExpr(c.ngTableDynamic);d.setupBindingsToInternalScope(e.tableParams),d.compileDirectiveTemplates(),a.$watchCollection(e.columns,function(b){a.$columns=d.buildColumns(b),d.loadFilterData(a.$columns)})}):void 0}}}]),function(){function b(){var a={restrict:"E",replace:!0,templateUrl:"ng-table/filterRow.html",scope:!0,controller:"ngTableFilterRowController"};return a}a.module("ngTable").directive("ngTableFilterRow",b),b.$inject=[]}(),function(){function b(){var a={restrict:"E",replace:!0,templateUrl:"ng-table/sorterRow.html",scope:!0,controller:"ngTableSorterRowController"};return a}a.module("ngTable").directive("ngTableSorterRow",b),b.$inject=[]}(),b.directive("ngTablePagination",["$compile","ngTableEventsChannel",function(b,c){return{restrict:"A",scope:{params:"=ngTablePagination",templateUrl:"="},replace:!1,link:function(d,e){c.onAfterReloadData(function(a){d.pages=a.generatePagesArray()},d,function(a){return a===d.params}),d.$watch("templateUrl",function(c){if(!a.isUndefined(c)){var f=a.element(document.createElement("div"));f.attr({"ng-include":"templateUrl"}),e.append(f),b(f)(d)}})}}}]),a.module("ngTable").run(["$templateCache",function(a){a.put("ng-table/filterRow.html",'
        '),a.put("ng-table/filters/number.html",' '),a.put("ng-table/filters/select-multiple.html",' '),a.put("ng-table/filters/select.html",' '),a.put("ng-table/filters/text.html",' '),a.put("ng-table/header.html"," "),a.put("ng-table/pager.html",' '),a.put("ng-table/sorterRow.html",' ')}]),b}); +//# sourceMappingURL=ng-table.min.js.map \ No newline at end of file diff --git a/LiveChat/ClientComponents/signalr/jquery.signalR-2.1.0.min.js b/LiveChat/ClientComponents/signalr/jquery.signalR-2.1.0.min.js new file mode 100644 index 0000000..dc3cf2d --- /dev/null +++ b/LiveChat/ClientComponents/signalr/jquery.signalR-2.1.0.min.js @@ -0,0 +1,8 @@ +/*! + * ASP.NET SignalR JavaScript Library v2.1.0 + * http://signalr.net/ + * + * Copyright (C) Microsoft Corporation. All rights reserved. + * + */ +(function(n,t,i){function w(t,i){var u,f;if(n.isArray(t)){for(u=t.length-1;u>=0;u--)f=t[u],n.type(f)==="string"&&r.transports[f]||(i.log("Invalid transport: "+f+", removing it from the transports list."),t.splice(u,1));t.length===0&&(i.log("No transports remain within the specified transport array."),t=null)}else if(r.transports[t]||t==="auto"){if(t==="auto"&&r._.ieVersion<=8)return["longPolling"]}else i.log("Invalid transport: "+t.toString()+"."),t=null;return t}function b(n){return n==="http:"?80:n==="https:"?443:void 0}function a(n,t){return t.match(/:\d+$/)?t:t+":"+b(n)}function k(t,i){var u=this,r=[];u.tryBuffer=function(i){return t.state===n.signalR.connectionState.connecting?(r.push(i),!0):!1};u.drain=function(){if(t.state===n.signalR.connectionState.connected)while(r.length>0)i(r.shift())};u.clear=function(){r=[]}}var f={nojQuery:"jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.",noTransportOnInit:"No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.",errorOnNegotiate:"Error during negotiation request.",stoppedWhileLoading:"The connection was stopped during page load.",stoppedWhileNegotiating:"The connection was stopped during the negotiate request.",errorParsingNegotiateResponse:"Error parsing negotiate response.",errorDuringStartRequest:"Error during start request. Stopping the connection.",stoppedDuringStartRequest:"The connection was stopped during the start request.",errorParsingStartResponse:"Error parsing start response: '{0}'. Stopping the connection.",invalidStartResponse:"Invalid start response: '{0}'. Stopping the connection.",protocolIncompatible:"You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.",sendFailed:"Send failed.",parseFailed:"Failed at parsing response: {0}",longPollFailed:"Long polling request failed.",eventSourceFailedToConnect:"EventSource failed to connect.",eventSourceError:"Error raised by EventSource",webSocketClosed:"WebSocket closed.",pingServerFailedInvalidResponse:"Invalid ping response when pinging server: '{0}'.",pingServerFailed:"Failed to ping server.",pingServerFailedStatusCode:"Failed to ping server. Server responded with status code {0}, stopping the connection.",pingServerFailedParse:"Failed to parse ping server response, stopping the connection.",noConnectionTransport:"Connection is in an invalid state, there is no transport active.",webSocketsInvalidState:"The Web Socket transport is in an invalid state, transitioning into reconnecting.",reconnectTimeout:"Couldn't reconnect within the configured timeout of {0} ms, disconnecting.",reconnectWindowTimeout:"The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection."};if(typeof n!="function")throw new Error(f.nojQuery);var r,h,s=t.document.readyState==="complete",e=n(t),c="__Negotiate Aborted__",u={onStart:"onStart",onStarting:"onStarting",onReceived:"onReceived",onError:"onError",onConnectionSlow:"onConnectionSlow",onReconnecting:"onReconnecting",onReconnect:"onReconnect",onStateChanged:"onStateChanged",onDisconnect:"onDisconnect"},v=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},o=function(t,i,r){return i===t.state?(t.state=r,n(t).triggerHandler(u.onStateChanged,[{oldState:i,newState:r}]),!0):!1},y=function(n){return n.state===r.connectionState.disconnected},l=function(n){return n._.keepAliveData.activated&&n.transport.supportsKeepAlive(n)},p=function(i){var f,e;i._.configuredStopReconnectingTimeout||(e=function(t){var i=r._.format(r.resources.reconnectTimeout,t.disconnectTimeout);t.log(i);n(t).triggerHandler(u.onError,[r._.error(i,"TimeoutException")]);t.stop(!1,!1)},i.reconnecting(function(){var n=this;n.state===r.connectionState.reconnecting&&(f=t.setTimeout(function(){e(n)},n.disconnectTimeout))}),i.stateChanged(function(n){n.oldState===r.connectionState.reconnecting&&t.clearTimeout(f)}),i._.configuredStopReconnectingTimeout=!0)};r=function(n,t,i){return new r.fn.init(n,t,i)};r._={defaultContentType:"application/x-www-form-urlencoded; charset=UTF-8",ieVersion:function(){var i,n;return t.navigator.appName==="Microsoft Internet Explorer"&&(n=/MSIE ([0-9]+\.[0-9]+)/.exec(t.navigator.userAgent),n&&(i=t.parseFloat(n[1]))),i}(),error:function(n,t,i){var r=new Error(n);return r.source=t,typeof i!="undefined"&&(r.context=i),r},transportError:function(n,t,r,u){var f=this.error(n,r,u);return f.transport=t?t.name:i,f},format:function(){for(var t=arguments[0],n=0;n<\/script>.");}};e.load(function(){s=!0});r.fn=r.prototype={init:function(t,i,r){var f=n(this);this.url=t;this.qs=i;this.lastError=null;this._={keepAliveData:{},connectingMessageBuffer:new k(this,function(n){f.triggerHandler(u.onReceived,[n])}),onFailedTimeoutHandle:null,lastMessageAt:(new Date).getTime(),lastActiveAt:(new Date).getTime(),beatInterval:5e3,beatHandle:null,totalTransportConnectTimeout:0};typeof r=="boolean"&&(this.logging=r)},_parseResponse:function(n){var t=this;return n?typeof n=="string"?t.json.parse(n):n:n},_originalJson:t.JSON,json:t.JSON,isCrossDomain:function(i,r){var u;return(i=n.trim(i),r=r||t.location,i.indexOf("http")!==0)?!1:(u=t.document.createElement("a"),u.href=i,u.protocol+a(u.protocol,u.host)!==r.protocol+a(r.protocol,r.host))},ajaxDataType:"text",contentType:"application/json; charset=UTF-8",logging:!1,state:r.connectionState.disconnected,clientProtocol:"1.4",reconnectDelay:2e3,transportConnectTimeout:0,disconnectTimeout:3e4,reconnectWindow:3e4,keepAliveWarnAt:2/3,start:function(i,h){var a=this,v={pingInterval:3e5,waitForPageLoad:!0,transport:"auto",jsonp:!1},d,y=a._deferral||n.Deferred(),b=t.document.createElement("a"),k,g;if(a.lastError=null,a._deferral=y,!a.json)throw new Error("SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.");if(n.type(i)==="function"?h=i:n.type(i)==="object"&&(n.extend(v,i),n.type(v.callback)==="function"&&(h=v.callback)),v.transport=w(v.transport,a),!v.transport)throw new Error("SignalR: Invalid transport(s) specified, aborting start.");return(a._.config=v,!s&&v.waitForPageLoad===!0)?(a._.deferredStartHandler=function(){a.start(i,h)},e.bind("load",a._.deferredStartHandler),y.promise()):a.state===r.connectionState.connecting?y.promise():o(a,r.connectionState.disconnected,r.connectionState.connecting)===!1?(y.resolve(a),y.promise()):(p(a),b.href=a.url,b.protocol&&b.protocol!==":"?(a.protocol=b.protocol,a.host=b.host):(a.protocol=t.document.location.protocol,a.host=b.host||t.document.location.host),a.baseUrl=a.protocol+"//"+a.host,a.wsProtocol=a.protocol==="https:"?"wss://":"ws://",v.transport==="auto"&&v.jsonp===!0&&(v.transport="longPolling"),a.url.indexOf("//")===0&&(a.url=t.location.protocol+a.url,a.log("Protocol relative URL detected, normalizing it to '"+a.url+"'.")),this.isCrossDomain(a.url)&&(a.log("Auto detected cross domain url."),v.transport==="auto"&&(v.transport=["webSockets","serverSentEvents","longPolling"]),typeof v.withCredentials=="undefined"&&(v.withCredentials=!0),v.jsonp||(v.jsonp=!n.support.cors,v.jsonp&&a.log("Using jsonp because this browser doesn't support CORS.")),a.contentType=r._.defaultContentType),a.withCredentials=v.withCredentials,a.ajaxDataType=v.jsonp?"jsonp":"text",n(a).bind(u.onStart,function(){n.type(h)==="function"&&h.call(a);y.resolve(a)}),d=function(i,s){var p=r._.error(f.noTransportOnInit);if(s=s||0,s>=i.length){n(a).triggerHandler(u.onError,[p]);y.reject(p);a.stop();return}if(a.state!==r.connectionState.disconnected){var w=i[s],h=r.transports[w],c=!1,v=function(){c||(c=!0,t.clearTimeout(a._.onFailedTimeoutHandle),h.stop(a),d(i,s+1))};a.transport=h;try{a._.onFailedTimeoutHandle=t.setTimeout(function(){a.log(h.name+" timed out when trying to connect.");v()},a._.totalTransportConnectTimeout);h.start(a,function(){var i=r._.firefoxMajorVersion(t.navigator.userAgent)>=11,f=!!a.withCredentials&&i;a.state!==r.connectionState.disconnected&&(c||(c=!0,t.clearTimeout(a._.onFailedTimeoutHandle),l(a)&&r.transports._logic.monitorKeepAlive(a),r.transports._logic.startHeartbeat(a),r._.configurePingInterval(a),o(a,r.connectionState.connecting,r.connectionState.connected),a._.connectingMessageBuffer.drain(),n(a).triggerHandler(u.onStart),e.bind("unload",function(){a.log("Window unloading, stopping the connection.");a.stop(f)}),i&&e.bind("beforeunload",function(){t.setTimeout(function(){a.stop(f)},0)})))},v)}catch(b){a.log(h.name+" transport threw '"+b.message+"' when attempting to start.");v()}}},k=a.url+"/negotiate",g=function(t,i){var e=r._.error(f.errorOnNegotiate,t,i._.negotiateRequest);n(i).triggerHandler(u.onError,e);y.reject(e);i.stop()},n(a).triggerHandler(u.onStarting),k=r.transports._logic.prepareQueryString(a,k),a.log("Negotiating with '"+k+"'."),a._.negotiateRequest=r.transports._logic.ajax(a,{url:k,error:function(n,t){t!==c?g(n,a):y.reject(r._.error(f.stoppedWhileNegotiating,null,a._.negotiateRequest))},success:function(t){var i,e,h,o=[],s=[];try{i=a._parseResponse(t)}catch(c){g(r._.error(f.errorParsingNegotiateResponse,c),a);return}if(e=a._.keepAliveData,a.appRelativeUrl=i.Url,a.id=i.ConnectionId,a.token=i.ConnectionToken,a.webSocketServerUrl=i.WebSocketServerUrl,a._.longPollDelay=i.LongPollDelay*1e3,a.disconnectTimeout=i.DisconnectTimeout*1e3,a._.totalTransportConnectTimeout=a.transportConnectTimeout+i.TransportConnectTimeout*1e3,i.KeepAliveTimeout?(e.activated=!0,e.timeout=i.KeepAliveTimeout*1e3,e.timeoutWarning=e.timeout*a.keepAliveWarnAt,a._.beatInterval=(e.timeout-e.timeoutWarning)/3):e.activated=!1,a.reconnectWindow=a.disconnectTimeout+(e.timeout||0),!i.ProtocolVersion||i.ProtocolVersion!==a.clientProtocol){h=r._.error(r._.format(f.protocolIncompatible,a.clientProtocol,i.ProtocolVersion));n(a).triggerHandler(u.onError,[h]);y.reject(h);return}n.each(r.transports,function(n){if(n.indexOf("_")===0||n==="webSockets"&&!i.TryWebSockets)return!0;s.push(n)});n.isArray(v.transport)?n.each(v.transport,function(t,i){n.inArray(i,s)>=0&&o.push(i)}):v.transport==="auto"?o=s:n.inArray(v.transport,s)>=0&&o.push(v.transport);d(o)}}),y.promise())},starting:function(t){var i=this;return n(i).bind(u.onStarting,function(){t.call(i)}),i},send:function(n){var t=this;if(t.state===r.connectionState.disconnected)throw new Error("SignalR: Connection must be started before data can be sent. Call .start() before .send()");if(t.state===r.connectionState.connecting)throw new Error("SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.");return t.transport.send(t,n),t},received:function(t){var i=this;return n(i).bind(u.onReceived,function(n,r){t.call(i,r)}),i},stateChanged:function(t){var i=this;return n(i).bind(u.onStateChanged,function(n,r){t.call(i,r)}),i},error:function(t){var i=this;return n(i).bind(u.onError,function(n,r,u){i.lastError=r;t.call(i,r,u)}),i},disconnected:function(t){var i=this;return n(i).bind(u.onDisconnect,function(){t.call(i)}),i},connectionSlow:function(t){var i=this;return n(i).bind(u.onConnectionSlow,function(){t.call(i)}),i},reconnecting:function(t){var i=this;return n(i).bind(u.onReconnecting,function(){t.call(i)}),i},reconnected:function(t){var i=this;return n(i).bind(u.onReconnect,function(){t.call(i)}),i},stop:function(i,h){var a=this,v=a._deferral;if(a._.deferredStartHandler&&e.unbind("load",a._.deferredStartHandler),delete a._.config,delete a._.deferredStartHandler,!s&&(!a._.config||a._.config.waitForPageLoad===!0)){a.log("Stopping connection prior to negotiate.");v&&v.reject(r._.error(f.stoppedWhileLoading));return}if(a.state!==r.connectionState.disconnected)return a.log("Stopping connection."),o(a,a.state,r.connectionState.disconnected),t.clearTimeout(a._.beatHandle),t.clearTimeout(a._.onFailedTimeoutHandle),t.clearInterval(a._.pingIntervalId),a.transport&&(a.transport.stop(a),h!==!1&&a.transport.abort(a,i),l(a)&&r.transports._logic.stopMonitoringKeepAlive(a),a.transport=null),a._.negotiateRequest&&(a._.negotiateRequest.abort(c),delete a._.negotiateRequest),r.transports._logic.tryAbortStartRequest(a),n(a).triggerHandler(u.onDisconnect),delete a._deferral,delete a.messageId,delete a.groupsToken,delete a.id,delete a._.pingIntervalId,delete a._.lastMessageAt,delete a._.lastActiveAt,delete a._.longPollDelay,a._.connectingMessageBuffer.clear(),a},log:function(n){v(n,this.logging)}};r.fn.init.prototype=r.fn;r.noConflict=function(){return n.connection===r&&(n.connection=h),r};n.connection&&(h=n.connection);n.connection=n.signalR=r})(window.jQuery,window),function(n,t){function o(n){n._.keepAliveData.monitoring&&h(n);r.markActive(n)&&(n._.beatHandle=t.setTimeout(function(){o(n)},n._.beatInterval))}function h(t){var r=t._.keepAliveData,f;t.state===i.connectionState.connected&&(f=(new Date).getTime()-t._.lastMessageAt,f>=r.timeout?(t.log("Keep alive timed out. Notifying transport that connection has been lost."),t.transport.lostConnection(t)):f>=r.timeoutWarning?r.userNotified||(t.log("Keep alive has been missed, connection may be dead/slow."),n(t).triggerHandler(u.onConnectionSlow),r.userNotified=!0):r.userNotified=!1)}function f(n,t){var i=n.url+t;return n.transport&&(i+="?transport="+n.transport.name),r.prepareQueryString(n,i)}var i=n.signalR,u=n.signalR.events,s=n.signalR.changeState,e="__Start Aborted__",r;i.transports={};r=i.transports._logic={ajax:function(t,i){return n.ajax(n.extend(!0,{},n.signalR.ajaxDefaults,{type:"GET",data:{},xhrFields:{withCredentials:t.withCredentials},contentType:t.contentType,dataType:t.ajaxDataType},i))},pingServer:function(t){var e,f,u=n.Deferred();return t.transport?(e=t.url+"/ping",e=r.addQs(e,t.qs),f=r.ajax(t,{url:e,success:function(n){var r;try{r=t._parseResponse(n)}catch(e){u.reject(i._.transportError(i.resources.pingServerFailedParse,t.transport,e,f));t.stop();return}r.Response==="pong"?u.resolve():u.reject(i._.transportError(i._.format(i.resources.pingServerFailedInvalidResponse,n),t.transport,null,f))},error:function(n){n.status===401||n.status===403?(u.reject(i._.transportError(i._.format(i.resources.pingServerFailedStatusCode,n.status),t.transport,n,f)),t.stop()):u.reject(i._.transportError(i.resources.pingServerFailed,t.transport,n,f))}})):u.reject(i._.transportError(i.resources.noConnectionTransport,t.transport)),u.promise()},prepareQueryString:function(n,i){var u;return u=r.addQs(i,"clientProtocol="+n.clientProtocol),u=r.addQs(u,n.qs),n.token&&(u+="&connectionToken="+t.encodeURIComponent(n.token)),n.data&&(u+="&connectionData="+t.encodeURIComponent(n.data)),u},addQs:function(t,i){var r=t.indexOf("?")!==-1?"&":"?",u;if(!i)return t;if(typeof i=="object")return t+r+n.param(i);if(typeof i=="string")return u=i.charAt(0),(u==="?"||u==="&")&&(r=""),t+r+i;throw new Error("Query string property must be either a string or object.");},getUrl:function(n,i,u,f){var s=i==="webSockets"?"":n.baseUrl,e=s+n.appRelativeUrl,o="transport="+i;return n.groupsToken&&(o+="&groupsToken="+t.encodeURIComponent(n.groupsToken)),u?(e+=f?"/poll":"/reconnect",n.messageId&&(o+="&messageId="+t.encodeURIComponent(n.messageId))):e+="/connect",e+="?"+o,e=r.prepareQueryString(n,e),e+("&tid="+Math.floor(Math.random()*11))},maximizePersistentResponse:function(n){return{MessageId:n.C,Messages:n.M,Initialized:typeof n.S!="undefined"?!0:!1,Disconnect:typeof n.D!="undefined"?!0:!1,ShouldReconnect:typeof n.T!="undefined"?!0:!1,LongPollDelay:n.L,GroupsToken:n.G}},updateGroups:function(n,t){t&&(n.groupsToken=t)},stringifySend:function(n,t){return typeof t=="string"||typeof t=="undefined"||t===null?t:n.json.stringify(t)},ajaxSend:function(t,e){var h=r.stringifySend(t,e),c=f(t,"/send"),o,s=function(t,r){n(r).triggerHandler(u.onError,[i._.transportError(i.resources.sendFailed,r.transport,t,o),e])};return o=r.ajax(t,{url:c,type:t.ajaxDataType==="jsonp"?"GET":"POST",contentType:i._.defaultContentType,data:{data:h},success:function(n){var i;if(n){try{i=t._parseResponse(n)}catch(u){s(u,t);t.stop();return}r.triggerReceived(t,i)}},error:function(n,i){i!=="abort"&&i!=="parsererror"&&s(n,t)}})},ajaxAbort:function(n,t){if(typeof n.transport!="undefined"){t=typeof t=="undefined"?!0:t;var i=f(n,"/abort");r.ajax(n,{url:i,async:t,timeout:1e3,type:"POST"});n.log("Fired ajax abort async = "+t+".")}},tryInitialize:function(t,o,s){var l,h,a=function(n){var i=t._deferral;i&&i.reject(n)},c=function(i){n(t).triggerHandler(u.onError,[i]);a(i);t.stop()};o.Initialized&&(l=f(t,"/start"),h=r.ajax(t,{url:l,success:function(n){var r;try{r=t._parseResponse(n)}catch(u){c(i._.error(i._.format(i.resources.errorParsingStartResponse,n),u,h));return}r.Response==="started"?s():c(i._.error(i._.format(i.resources.invalidStartResponse,n),null,h))},error:function(n,t){t!==e?c(i._.error(i.resources.errorDuringStartRequest,n,h)):a(i._.error(i.resources.stoppedDuringStartRequest,null,h))}}),t._.startRequest=h)},tryAbortStartRequest:function(n){n._.startRequest&&(n._.startRequest.abort(e),delete n._.startRequest)},triggerReceived:function(t,i){t._.connectingMessageBuffer.tryBuffer(i)||n(t).triggerHandler(u.onReceived,[i])},processMessages:function(t,i,u){var f;r.markLastMessage(t);i&&(f=r.maximizePersistentResponse(i),r.updateGroups(t,f.GroupsToken),f.MessageId&&(t.messageId=f.MessageId),f.Messages&&(n.each(f.Messages,function(n,i){r.triggerReceived(t,i)}),r.tryInitialize(t,f,u)))},monitorKeepAlive:function(t){var i=t._.keepAliveData;i.monitoring?t.log("Tried to monitor keep alive but it's already being monitored."):(i.monitoring=!0,r.markLastMessage(t),t._.keepAliveData.reconnectKeepAliveUpdate=function(){r.markLastMessage(t)},n(t).bind(u.onReconnect,t._.keepAliveData.reconnectKeepAliveUpdate),t.log("Now monitoring keep alive with a warning timeout of "+i.timeoutWarning+" and a connection lost timeout of "+i.timeout+"."))},stopMonitoringKeepAlive:function(t){var i=t._.keepAliveData;i.monitoring&&(i.monitoring=!1,n(t).unbind(u.onReconnect,t._.keepAliveData.reconnectKeepAliveUpdate),t._.keepAliveData={},t.log("Stopping the monitoring of the keep alive."))},startHeartbeat:function(n){n._.lastActiveAt=(new Date).getTime();o(n)},markLastMessage:function(n){n._.lastMessageAt=(new Date).getTime()},markActive:function(n){return r.verifyLastActive(n)?(n._.lastActiveAt=(new Date).getTime(),!0):!1},isConnectedOrReconnecting:function(n){return n.state===i.connectionState.connected||n.state===i.connectionState.reconnecting},ensureReconnectingState:function(t){return s(t,i.connectionState.connected,i.connectionState.reconnecting)===!0&&n(t).triggerHandler(u.onReconnecting),t.state===i.connectionState.reconnecting},clearReconnectTimeout:function(n){n&&n._.reconnectTimeout&&(t.clearTimeout(n._.reconnectTimeout),delete n._.reconnectTimeout)},verifyLastActive:function(t){if((new Date).getTime()-t._.lastActiveAt>=t.reconnectWindow){var r=i._.format(i.resources.reconnectWindowTimeout,new Date(t._.lastActiveAt),t.reconnectWindow);return t.log(r),n(t).triggerHandler(u.onError,[i._.error(r,"TimeoutException")]),t.stop(!1,!1),!1}return!0},reconnect:function(n,u){var f=i.transports[u];if(r.isConnectedOrReconnecting(n)&&!n._.reconnectTimeout){if(!r.verifyLastActive(n))return;n._.reconnectTimeout=t.setTimeout(function(){r.verifyLastActive(n)&&(f.stop(n),r.ensureReconnectingState(n)&&(n.log(u+" reconnecting."),f.start(n)))},n.reconnectDelay)}},handleParseFailure:function(t,r,f,e,o){t.state===i.connectionState.connecting?(t.log("Failed to parse server response while attempting to connect."),e()):(n(t).triggerHandler(u.onError,[i._.transportError(i._.format(i.resources.parseFailed,r),t.transport,f,o)]),t.stop())},foreverFrame:{count:0,connections:{}}}}(window.jQuery,window),function(n,t){var r=n.signalR,u=n.signalR.events,f=n.signalR.changeState,i=r.transports._logic;r.transports.webSockets={name:"webSockets",supportsKeepAlive:function(){return!0},send:function(t,f){var e=i.stringifySend(t,f);try{t.socket.send(e)}catch(o){n(t).triggerHandler(u.onError,[r._.transportError(r.resources.webSocketsInvalidState,t.transport,o,t.socket),f])}},start:function(e,o,s){var h,c=!1,l=this,a=!o,v=n(e);if(!t.WebSocket){s();return}e.socket||(h=e.webSocketServerUrl?e.webSocketServerUrl:e.wsProtocol+e.host,h+=i.getUrl(e,this.name,a),e.log("Connecting to websocket endpoint '"+h+"'."),e.socket=new t.WebSocket(h),e.socket.onopen=function(){c=!0;e.log("Websocket opened.");i.clearReconnectTimeout(e);f(e,r.connectionState.reconnecting,r.connectionState.connected)===!0&&v.triggerHandler(u.onReconnect)},e.socket.onclose=function(t){if(this===e.socket){if(c)typeof t.wasClean!="undefined"&&t.wasClean===!1?(n(e).triggerHandler(u.onError,[r._.transportError(r.resources.webSocketClosed,e.transport,t)]),e.log("Unclean disconnect from websocket: "+t.reason||"[no reason given].")):e.log("Websocket closed.");else{s?s():a&&l.reconnect(e);return}l.reconnect(e)}},e.socket.onmessage=function(t){var r;try{r=e._parseResponse(t.data)}catch(u){i.handleParseFailure(e,t.data,u,s,t);return}r&&(n.isEmptyObject(r)||r.M?i.processMessages(e,r,o):i.triggerReceived(e,r))})},reconnect:function(n){i.reconnect(n,this.name)},lostConnection:function(n){this.reconnect(n)},stop:function(n){i.clearReconnectTimeout(n);n.socket&&(n.log("Closing the Websocket."),n.socket.close(),n.socket=null)},abort:function(n,t){i.ajaxAbort(n,t)}}}(window.jQuery,window),function(n,t){var i=n.signalR,u=n.signalR.events,e=n.signalR.changeState,r=i.transports._logic,f=function(n){t.clearTimeout(n._.reconnectAttemptTimeoutHandle);delete n._.reconnectAttemptTimeoutHandle};i.transports.serverSentEvents={name:"serverSentEvents",supportsKeepAlive:function(){return!0},timeOut:3e3,start:function(o,s,h){var c=this,l=!1,a=n(o),v=!s,y;if(o.eventSource&&(o.log("The connection already has an event source. Stopping it."),o.stop()),!t.EventSource){h&&(o.log("This browser doesn't support SSE."),h());return}y=r.getUrl(o,this.name,v);try{o.log("Attempting to connect to SSE endpoint '"+y+"'.");o.eventSource=new t.EventSource(y,{withCredentials:o.withCredentials})}catch(p){o.log("EventSource failed trying to connect with error "+p.Message+".");h?h():(a.triggerHandler(u.onError,[i._.transportError(i.resources.eventSourceFailedToConnect,o.transport,p)]),v&&c.reconnect(o));return}v&&(o._.reconnectAttemptTimeoutHandle=t.setTimeout(function(){l===!1&&o.eventSource.readyState!==t.EventSource.OPEN&&c.reconnect(o)},c.timeOut));o.eventSource.addEventListener("open",function(){o.log("EventSource connected.");f(o);r.clearReconnectTimeout(o);l===!1&&(l=!0,e(o,i.connectionState.reconnecting,i.connectionState.connected)===!0&&a.triggerHandler(u.onReconnect))},!1);o.eventSource.addEventListener("message",function(n){var t;if(n.data!=="initialized"){try{t=o._parseResponse(n.data)}catch(i){r.handleParseFailure(o,n.data,i,h,n);return}r.processMessages(o,t,s)}},!1);o.eventSource.addEventListener("error",function(n){if(this===o.eventSource){if(!l){h&&h();return}o.log("EventSource readyState: "+o.eventSource.readyState+".");n.eventPhase===t.EventSource.CLOSED?(o.log("EventSource reconnecting due to the server connection ending."),c.reconnect(o)):(o.log("EventSource error."),a.triggerHandler(u.onError,[i._.transportError(i.resources.eventSourceError,o.transport,n)]))}},!1)},reconnect:function(n){r.reconnect(n,this.name)},lostConnection:function(n){this.reconnect(n)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){f(n);r.clearReconnectTimeout(n);n&&n.eventSource&&(n.log("EventSource calling close()."),n.eventSource.close(),n.eventSource=null,delete n.eventSource)},abort:function(n,t){r.ajaxAbort(n,t)}}}(window.jQuery,window),function(n,t){var r=n.signalR,e=n.signalR.events,o=n.signalR.changeState,i=r.transports._logic,u=function(){var n=t.document.createElement("iframe");return n.setAttribute("style","position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;"),n},f=function(){var i=null,f=1e3,n=0;return{prevent:function(){r._.ieVersion<=8&&(n===0&&(i=t.setInterval(function(){var n=u();t.document.body.appendChild(n);t.document.body.removeChild(n);n=null},f)),n++)},cancel:function(){n===1&&t.clearInterval(i);n>0&&n--}}}();r.transports.foreverFrame={name:"foreverFrame",supportsKeepAlive:function(){return!0},iframeClearThreshold:50,start:function(n,r,e){var l=this,s=i.foreverFrame.count+=1,h,o=u(),c=function(){n.log("Forever frame iframe finished loading and is no longer receiving messages.");l.reconnect(n)};if(t.EventSource){e&&(n.log("This browser supports SSE, skipping Forever Frame."),e());return}o.setAttribute("data-signalr-connection-id",n.id);f.prevent();h=i.getUrl(n,this.name);h+="&frameId="+s;t.document.body.appendChild(o);n.log("Binding to iframe's load event.");o.addEventListener?o.addEventListener("load",c,!1):o.attachEvent&&o.attachEvent("onload",c);o.src=h;i.foreverFrame.connections[s]=n;n.frame=o;n.frameId=s;r&&(n.onSuccess=function(){n.log("Iframe transport started.");r()})},reconnect:function(n){var r=this;i.isConnectedOrReconnecting(n)&&i.verifyLastActive(n)&&t.setTimeout(function(){if(i.verifyLastActive(n)&&n.frame&&i.ensureReconnectingState(n)){var u=n.frame,t=i.getUrl(n,r.name,!0)+"&frameId="+n.frameId;n.log("Updating iframe src to '"+t+"'.");u.src=t}},n.reconnectDelay)},lostConnection:function(n){this.reconnect(n)},send:function(n,t){i.ajaxSend(n,t)},receive:function(t,u){var f,e,o;if(t.json!==t._originalJson&&(u=t._originalJson.stringify(u)),o=t._parseResponse(u),i.processMessages(t,o,t.onSuccess),t.state===n.signalR.connectionState.connected&&(t.frameMessageCount=(t.frameMessageCount||0)+1,t.frameMessageCount>r.transports.foreverFrame.iframeClearThreshold&&(t.frameMessageCount=0,f=t.frame.contentWindow||t.frame.contentDocument,f&&f.document&&f.document.body)))for(e=f.document.body;e.firstChild;)e.removeChild(e.firstChild)},stop:function(n){var r=null;if(f.cancel(),n.frame){if(n.frame.stop)n.frame.stop();else try{r=n.frame.contentWindow||n.frame.contentDocument;r.document&&r.document.execCommand&&r.document.execCommand("Stop")}catch(u){n.log("Error occured when stopping foreverFrame transport. Message = "+u.message+".")}n.frame.parentNode===t.document.body&&t.document.body.removeChild(n.frame);delete i.foreverFrame.connections[n.frameId];n.frame=null;n.frameId=null;delete n.frame;delete n.frameId;delete n.onSuccess;delete n.frameMessageCount;n.log("Stopping forever frame.")}},abort:function(n,t){i.ajaxAbort(n,t)},getConnection:function(n){return i.foreverFrame.connections[n]},started:function(t){o(t,r.connectionState.reconnecting,r.connectionState.connected)===!0&&n(t).triggerHandler(e.onReconnect)}}}(window.jQuery,window),function(n,t){var r=n.signalR,u=n.signalR.events,e=n.signalR.changeState,f=n.signalR.isDisconnecting,i=r.transports._logic,o=function(){try{return"onprogress"in new t.XMLHttpRequest}catch(n){return!1}}();r.transports.longPolling={name:"longPolling",supportsKeepAlive:function(n){return o&&n.ajaxDataType!=="jsonp"&&n._.longPollDelay===0},reconnectDelay:3e3,start:function(o,s,h){var a=this,v=function(){v=n.noop;h=null;o.log("LongPolling connected.");s()},y=function(){return h?(h(),h=null,o.log("LongPolling failed to connect."),!0):!1},c=o._,l=0,p=function(i){t.clearTimeout(c.reconnectTimeoutId);c.reconnectTimeoutId=null;e(i,r.connectionState.reconnecting,r.connectionState.connected)===!0&&(i.log("Raising the reconnect event"),n(i).triggerHandler(u.onReconnect))},w=36e5;o.pollXhr&&(o.log("Polling xhr requests already exists, aborting."),o.stop());o.messageId=null;c.reconnectTimeoutId=null;c.pollTimeoutId=t.setTimeout(function(){(function e(s,h){var d=s.messageId,g=d===null,b=!g,nt=!h,k=i.getUrl(s,a.name,b,nt);f(s)!==!0&&(o.log("Opening long polling request to '"+k+"'."),s.pollXhr=i.ajax(o,{xhrFields:{onprogress:function(){i.markLastMessage(o)}},url:k,success:function(r){var h,w=0,u,a;o.log("Long poll complete.");l=0;try{h=o._parseResponse(r)}catch(b){i.handleParseFailure(s,r,b,y,s.pollXhr);return}(c.reconnectTimeoutId!==null&&p(s),h&&(u=i.maximizePersistentResponse(h)),i.processMessages(s,h,v),u&&n.type(u.LongPollDelay)==="number"&&(w=u.LongPollDelay),u&&u.Disconnect)||f(s)!==!0&&(a=u&&u.ShouldReconnect,!a||i.ensureReconnectingState(s))&&(w>0?c.pollTimeoutId=t.setTimeout(function(){e(s,a)},w):e(s,a))},error:function(f,h){if(t.clearTimeout(c.reconnectTimeoutId),c.reconnectTimeoutId=null,h==="abort"){o.log("Aborted xhr request.");return}if(!y()){if(l++,o.state!==r.connectionState.reconnecting&&(o.log("An error occurred using longPolling. Status = "+h+". Response = "+f.responseText+"."),n(s).triggerHandler(u.onError,[r._.transportError(r.resources.longPollFailed,o.transport,f,s.pollXhr)])),(o.state===r.connectionState.connected||o.state===r.connectionState.reconnecting)&&!i.verifyLastActive(o))return;if(!i.ensureReconnectingState(s))return;c.pollTimeoutId=t.setTimeout(function(){e(s,!0)},a.reconnectDelay)}}}),b&&h===!0&&(c.reconnectTimeoutId=t.setTimeout(function(){p(s)},Math.min(1e3*(Math.pow(2,l)-1),w))))})(o)},250)},lostConnection:function(n){n.pollXhr&&n.pollXhr.abort("lostConnection")},send:function(n,t){i.ajaxSend(n,t)},stop:function(n){t.clearTimeout(n._.pollTimeoutId);t.clearTimeout(n._.reconnectTimeoutId);delete n._.pollTimeoutId;delete n._.reconnectTimeoutId;n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr)},abort:function(n,t){i.ajaxAbort(n,t)}}}(window.jQuery,window),function(n){function r(n){return n+e}function s(n,t,i){for(var f=n.length,u=[],r=0;r=0;)n=n.replace(" "+t+" "," ");e.className=n.replace(/^\s+|\s+$/g,"")}},i=function(e){var n=t.createElement("div");return n.appendChild(t.createTextNode(e)),n.innerHTML},u=function(e){e.style.opacity="",e.style.display="block"},c=function(e){if(e&&!e.length)return u(e);for(var t=0;t0?setTimeout(o,t):e.style.display="none"});o()},h=function(n){if("function"==typeof MouseEvent){var o=new MouseEvent("click",{view:e,bubbles:!1,cancelable:!0});n.dispatchEvent(o)}else if(t.createEvent){var a=t.createEvent("MouseEvents");a.initEvent("click",!1,!1),n.dispatchEvent(a)}else t.createEventObject?n.fireEvent("onclick"):"function"==typeof n.onclick&&n.onclick()},g=function(t){"function"==typeof t.stopPropagation?(t.stopPropagation(),t.preventDefault()):e.event&&e.event.hasOwnProperty("cancelBubble")&&(e.event.cancelBubble=!0)};a.hasClass=r,a.addClass=s,a.removeClass=l,a.escapeHtml=i,a._show=u,a.show=c,a._hide=d,a.hide=f,a.isDescendant=p,a.getTopMargin=m,a.fadeIn=v,a.fadeOut=y,a.fireClick=h,a.stopEventPropagation=g},{}],5:[function(t,o,a){Object.defineProperty(a,"__esModule",{value:!0});var r=t("./handle-dom"),s=t("./handle-swal-dom"),l=function(t,o,a){var l=t||e.event,i=l.keyCode||l.which,u=a.querySelector("button.confirm"),c=a.querySelector("button.cancel"),d=a.querySelectorAll("button[tabindex]");if(-1!==[9,13,32,27].indexOf(i)){for(var f=l.target||l.srcElement,p=-1,m=0;m"),i.innerHTML=e.html?e.text:s.escapeHtml(e.text||"").split("\n").join("
        "),e.text&&s.show(i),e.customClass)s.addClass(t,e.customClass),t.setAttribute("data-custom-class",e.customClass);else{var d=t.getAttribute("data-custom-class");s.removeClass(t,d),t.setAttribute("data-custom-class","")}if(s.hide(t.querySelectorAll(".sa-icon")),e.type&&!a.isIE8()){var f=function(){for(var o=!1,a=0;ao;o++)n=parseInt(e.substr(2*o,2),16),n=Math.round(Math.min(Math.max(0,n+n*t),255)).toString(16),a+=("00"+n).substr(n.length);return a};o.extend=a,o.hexToRgb=r,o.isIE8=s,o.logStr=l,o.colorLuminance=i},{}]},{},[1]),"function"==typeof define&&define.amd?define(function(){return sweetAlert}):"undefined"!=typeof module&&module.exports&&(module.exports=sweetAlert)}(window,document); \ No newline at end of file diff --git a/LiveChat/ClientComponents/ua-parser/ua-parser.min.js b/LiveChat/ClientComponents/ua-parser/ua-parser.min.js new file mode 100644 index 0000000..f9607b8 --- /dev/null +++ b/LiveChat/ClientComponents/ua-parser/ua-parser.min.js @@ -0,0 +1,8 @@ +/** + * UAParser.js v0.7.9 + * Lightweight JavaScript-based User-Agent string parser + * https://github.com/faisalman/ua-parser-js + * + * Copyright © 2012-2015 Faisal Salman + * Dual licensed under GPLv2 & MIT + */(function(e,t){"use strict";var n="0.7.9",r="",i="?",s="function",o="undefined",u="object",a="string",f="major",l="model",c="name",h="type",p="vendor",d="version",v="architecture",m="console",g="mobile",y="tablet",b="smarttv",w="wearable",E="embedded",S={extend:function(e,t){for(var n in t)"browser cpu device engine os".indexOf(n)!==-1&&t[n].length%2===0&&(e[n]=t[n].concat(e[n]));return e},has:function(e,t){return typeof e=="string"?t.toLowerCase().indexOf(e.toLowerCase())!==-1:!1},lowerize:function(e){return e.toLowerCase()},major:function(e){return typeof e===a?e.split(".")[0]:t}},x={rgx:function(){var e,n=0,r,i,a,f,l,c,h=arguments;while(n0?f.length==2?typeof f[1]==s?e[f[0]]=f[1].call(this,c):e[f[0]]=f[1]:f.length==3?typeof f[1]===s&&(!f[1].exec||!f[1].test)?e[f[0]]=c?f[1].call(this,c,f[2]):t:e[f[0]]=c?c.replace(f[1],f[2]):t:f.length==4&&(e[f[0]]=c?f[3].call(this,c.replace(f[1],f[2])):t):e[f]=c?c:t}n+=2}return e},str:function(e,n){for(var r in n)if(typeof n[r]===u&&n[r].length>0){for(var s=0;s"),H.css("position","relative"),t.after(H),W=t.clone(),W.attr("placeholder",""),W.val(""),W.css({position:"absolute",top:"0px",left:"0px","border-color":"transparent","box-shadow":"none",opacity:1,background:"none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)",color:"#999"}),t.css({position:"relative","vertical-align":"top","background-color":"transparent"}),H.append(W),W.after(t));var j=angular.element("
        ");j.attr({id:L,matches:"matches",active:"activeIdx",select:"select(activeIdx, evt)","move-in-progress":"moveInProgress",query:"query",position:"position","assign-is-open":"assignIsOpen(isOpen)",debounce:"debounceUpdate"}),angular.isDefined(a.typeaheadTemplateUrl)&&j.attr("template-url",a.typeaheadTemplateUrl),angular.isDefined(a.typeaheadPopupTemplateUrl)&&j.attr("popup-template-url",a.typeaheadPopupTemplateUrl);var _=function(){R&&W.val("")},z=function(){D.matches=[],D.activeIdx=-1,t.attr("aria-expanded",!1),_()},X=function(e){return L+"-option-"+e};D.$watch("activeIdx",function(e){0>e?t.removeAttr("aria-activedescendant"):t.attr("aria-activedescendant",X(e))});var Y=function(e,t){return D.matches.length>t&&e?e.toUpperCase()===D.matches[t].label.toUpperCase():!1},G=function(a,n){var i={$viewValue:a};T(e,!0),M(e,!1),o.when(V.source(e,i)).then(function(o){var r=a===g.$viewValue;if(r&&x)if(o&&o.length>0){D.activeIdx=E?0:-1,M(e,!1),D.matches.length=0;for(var l=0;l0&&s.slice(0,a.length).toUpperCase()===a.toUpperCase()?a+s.slice(a.length):"")}}else z(),M(e,!0);r&&T(e,!1)},function(){z(),T(e,!1),M(e,!0)})};I&&(angular.element(s).on("resize",h),l.find("body").on("scroll",h));var J=c(function(){D.matches.length&&f(),D.moveInProgress=!1},v);D.moveInProgress=!1,D.query=void 0;var K,Q=function(e){K=r(function(){G(e)},y)},Z=function(){K&&r.cancel(K)};z(),D.assignIsOpen=function(t){P(e,t)},D.select=function(n,i){var o,l,s={};C=!0,s[V.itemName]=l=D.matches[n].model,o=V.modelMapper(e,s),A(e,o),g.$setValidity("editable",!0),g.$setValidity("parse",!0),U(e,{$item:l,$model:o,$label:V.viewMapper(e,s),$event:i}),z(),D.$eval(a.typeaheadFocusOnSelect)!==!1&&r(function(){t[0].focus()},0,!1)},t.on("keydown",function(e){if(0!==D.matches.length&&-1!==m.indexOf(e.which)){if(-1===D.activeIdx&&(9===e.which||13===e.which))return z(),void D.$digest();e.preventDefault();var t;switch(e.which){case 9:case 13:D.$apply(function(){angular.isNumber(D.debounceUpdate)||angular.isObject(D.debounceUpdate)?c(function(){D.select(D.activeIdx,e)},angular.isNumber(D.debounceUpdate)?D.debounceUpdate:D.debounceUpdate["default"]):D.select(D.activeIdx,e)});break;case 27:e.stopPropagation(),z(),D.$digest();break;case 38:D.activeIdx=(D.activeIdx>0?D.activeIdx:D.matches.length)-1,D.$digest(),t=j.find("li")[D.activeIdx],t.parentNode.scrollTop=t.offsetTop;break;case 40:D.activeIdx=(D.activeIdx+1)%D.matches.length,D.$digest(),t=j.find("li")[D.activeIdx],t.parentNode.scrollTop=t.offsetTop}}}),t.bind("focus",function(e){x=!0,0!==$||g.$viewValue||r(function(){G(g.$viewValue,e)},0)}),t.bind("blur",function(e){k&&D.matches.length&&-1!==D.activeIdx&&!C&&(C=!0,D.$apply(function(){angular.isObject(D.debounceUpdate)&&angular.isNumber(D.debounceUpdate.blur)?c(function(){D.select(D.activeIdx,e)},D.debounceUpdate.blur):D.select(D.activeIdx,e)})),!w&&g.$error.editable&&(g.$viewValue="",t.val("")),x=!1,C=!1});var et=function(e){t[0]!==e.target&&3!==e.which&&0!==D.matches.length&&(z(),u.$$phase||D.$digest())};l.on("click",et),e.$on("$destroy",function(){l.off("click",et),(I||N)&&tt.remove(),I&&(angular.element(s).off("resize",h),l.find("body").off("scroll",h)),j.remove(),R&&H.remove()});var tt=n(j)(D);I?l.find("body").append(tt):N?angular.element(N).eq(0).append(tt):t.after(tt),this.init=function(t,a){g=t,b=a,D.debounceUpdate=g.$options&&i(g.$options.debounce)(e),g.$parsers.unshift(function(t){return x=!0,0===$||t&&t.length>=$?y>0?(Z(),Q(t)):G(t):(T(e,!1),Z(),z()),w?t:t?void g.$setValidity("editable",!1):(g.$setValidity("editable",!0),null)}),g.$formatters.push(function(t){var a,n,i={};return w||g.$setValidity("editable",!0),S?(i.$model=t,S(e,i)):(i[V.itemName]=t,a=V.viewMapper(e,i),i[V.itemName]=void 0,n=V.viewMapper(e,i),a!==n?a:t)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","^?ngModelOptions","uibTypeahead"],link:function(e,t,a,n){n[2].init(n[0],n[1])}}}).directive("uibTypeaheadPopup",["$$debounce",function(e){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&",assignIsOpen:"&",debounce:"&"},replace:!0,templateUrl:function(e,t){return t.popupTemplateUrl||"uib/template/typeahead/typeahead-popup.html"},link:function(t,a,n){t.templateUrl=n.templateUrl,t.isOpen=function(){var e=t.matches.length>0;return t.assignIsOpen({isOpen:e}),e},t.isActive=function(e){return t.active===e},t.selectActive=function(e){t.active=e},t.selectMatch=function(a,n){var i=t.debounce();angular.isNumber(i)||angular.isObject(i)?e(function(){t.select({activeIdx:a,evt:n})},angular.isNumber(i)?i:i["default"]):t.select({activeIdx:a,evt:n})}}}}]).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(e,t,a){return{scope:{index:"=",match:"=",query:"="},link:function(n,i,o){var r=a(o.templateUrl)(n.$parent)||"uib/template/typeahead/typeahead-match.html";e(r).then(function(e){var a=angular.element(e.trim());i.replaceWith(a),t(a)(n)})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(e,t,a){function n(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function i(e){return/<.*>/g.test(e)}var o;return o=t.has("$sanitize"),function(t,r){return!o&&i(t)&&a.warn("Unsafe use of typeahead please use ngSanitize"),t=r?(""+t).replace(new RegExp(n(r),"gi"),"$&"):t,o||(t=e.trustAsHtml(t)),t}}]),angular.module("ui.bootstrap.debounce",[]).factory("$$debounce",["$timeout",function(e){return function(t,a){var n;return function(){var i=this,o=Array.prototype.slice.call(arguments);n&&e.cancel(n),n=e(function(){t.apply(i,o)},a)}}}]),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(e,t){var a,n={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},i={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/};return{getRawNode:function(e){return e[0]||e},parseStyle:function(e){return e=parseFloat(e),isFinite(e)?e:0},offsetParent:function(a){function n(e){return"static"===(t.getComputedStyle(e).position||"static")}a=this.getRawNode(a);for(var i=a.offsetParent||e[0].documentElement;i&&i!==e[0].documentElement&&n(i);)i=i.offsetParent;return i||e[0].documentElement},scrollbarWidth:function(){if(angular.isUndefined(a)){var t=angular.element('
        ');e.find("body").append(t),a=t[0].offsetWidth-t[0].clientWidth,a=isFinite(a)?a:0,t.remove()}return a},scrollParent:function(a,i){a=this.getRawNode(a);var o=i?n.hidden:n.normal,r=e[0].documentElement,l=t.getComputedStyle(a),s="absolute"===l.position,u=a.parentElement||r;if(u===r||"fixed"===l.position)return r;for(;u.parentElement&&u!==r;){var c=t.getComputedStyle(u);if(s&&"static"!==c.position&&(s=!1),!s&&o.test(c.overflow+c.overflowY+c.overflowX))break;u=u.parentElement}return u},position:function(a,n){a=this.getRawNode(a);var i=this.offset(a);if(n){var o=t.getComputedStyle(a);i.top-=this.parseStyle(o.marginTop),i.left-=this.parseStyle(o.marginLeft)}var r=this.offsetParent(a),l={top:0,left:0};return r!==e[0].documentElement&&(l=this.offset(r),l.top+=r.clientTop-r.scrollTop,l.left+=r.clientLeft-r.scrollLeft),{width:Math.round(angular.isNumber(i.width)?i.width:a.offsetWidth),height:Math.round(angular.isNumber(i.height)?i.height:a.offsetHeight),top:Math.round(i.top-l.top),left:Math.round(i.left-l.left)}},offset:function(a){a=this.getRawNode(a);var n=a.getBoundingClientRect();return{width:Math.round(angular.isNumber(n.width)?n.width:a.offsetWidth),height:Math.round(angular.isNumber(n.height)?n.height:a.offsetHeight),top:Math.round(n.top+(t.pageYOffset||e[0].documentElement.scrollTop)),left:Math.round(n.left+(t.pageXOffset||e[0].documentElement.scrollLeft))}},viewportOffset:function(a,n,i){a=this.getRawNode(a),i=i!==!1?!0:!1;var o=a.getBoundingClientRect(),r={top:0,left:0,bottom:0,right:0},l=n?e[0].documentElement:this.scrollParent(a),s=l.getBoundingClientRect();if(r.top=s.top+l.clientTop,r.left=s.left+l.clientLeft,l===e[0].documentElement&&(r.top+=t.pageYOffset,r.left+=t.pageXOffset),r.bottom=r.top+l.clientHeight,r.right=r.left+l.clientWidth,i){var u=t.getComputedStyle(l);r.top+=this.parseStyle(u.paddingTop),r.bottom-=this.parseStyle(u.paddingBottom),r.left+=this.parseStyle(u.paddingLeft),r.right-=this.parseStyle(u.paddingRight)}return{top:Math.round(o.top-r.top),bottom:Math.round(r.bottom-o.bottom),left:Math.round(o.left-r.left),right:Math.round(r.right-o.right)}},parsePlacement:function(e){var t=i.auto.test(e);return t&&(e=e.replace(i.auto,"")),e=e.split("-"),e[0]=e[0]||"top",i.primary.test(e[0])||(e[0]="top"),e[1]=e[1]||"center",i.secondary.test(e[1])||(e[1]="center"),e[2]=t?!0:!1,e},positionElements:function(e,a,n,o){e=this.getRawNode(e),a=this.getRawNode(a);var r=angular.isDefined(a.offsetWidth)?a.offsetWidth:a.prop("offsetWidth"),l=angular.isDefined(a.offsetHeight)?a.offsetHeight:a.prop("offsetHeight");n=this.parsePlacement(n);var s=o?this.offset(e):this.position(e),u={top:0,left:0,placement:""};if(n[2]){var c=this.viewportOffset(e),d=t.getComputedStyle(a),p={width:r+Math.round(Math.abs(this.parseStyle(d.marginLeft)+this.parseStyle(d.marginRight))),height:l+Math.round(Math.abs(this.parseStyle(d.marginTop)+this.parseStyle(d.marginBottom)))};if(n[0]="top"===n[0]&&p.height>c.top&&p.height<=c.bottom?"bottom":"bottom"===n[0]&&p.height>c.bottom&&p.height<=c.top?"top":"left"===n[0]&&p.width>c.left&&p.width<=c.right?"right":"right"===n[0]&&p.width>c.right&&p.width<=c.left?"left":n[0],n[1]="top"===n[1]&&p.height-s.height>c.bottom&&p.height-s.height<=c.top?"bottom":"bottom"===n[1]&&p.height-s.height>c.top&&p.height-s.height<=c.bottom?"top":"left"===n[1]&&p.width-s.width>c.right&&p.width-s.width<=c.left?"right":"right"===n[1]&&p.width-s.width>c.left&&p.width-s.width<=c.right?"left":n[1],"center"===n[1])if(i.vertical.test(n[0])){var h=s.width/2-r/2;c.left+h<0&&p.width-s.width<=c.right?n[1]="left":c.right+h<0&&p.width-s.width<=c.left&&(n[1]="right")}else{var f=s.height/2-p.height/2;c.top+f<0&&p.height-s.height<=c.bottom?n[1]="top":c.bottom+f<0&&p.height-s.height<=c.top&&(n[1]="bottom")}}switch(n[0]){case"top":u.top=s.top-l;break;case"bottom":u.top=s.top+s.height;break;case"left":u.left=s.left-r;break;case"right":u.left=s.left+s.width}switch(n[1]){case"top":u.top=s.top;break;case"bottom":u.top=s.top+s.height-l;break;case"left":u.left=s.left;break;case"right":u.left=s.left+s.width-r;break;case"center":i.vertical.test(n[0])?u.left=s.left+s.width/2-r/2:u.top=s.top+s.height/2-l/2}return u.top=Math.round(u.top),u.left=Math.round(u.left),u.placement="center"===n[1]?n[0]:n[0]+"-"+n[1],u},positionArrow:function(e,a){e=this.getRawNode(e);var n=e.querySelector(".tooltip-inner, .popover-inner");if(n){var o=angular.element(n).hasClass("tooltip-inner"),r=e.querySelector(o?".tooltip-arrow":".arrow");if(r){if(a=this.parsePlacement(a),"center"===a[1])return void angular.element(r).css({top:"",bottom:"",right:"",left:"",margin:""});var l="border-"+a[0]+"-width",s=t.getComputedStyle(r)[l],u="border-";u+=i.vertical.test(a[0])?a[0]+"-"+a[1]:a[1]+"-"+a[0],u+="-radius";var c=t.getComputedStyle(o?n:e)[u],d={top:"auto",bottom:"auto",left:"auto",right:"auto",margin:0};switch(a[0]){case"top":d.bottom=o?"0":"-"+s;break;case"bottom":d.top=o?"0":"-"+s;break;case"left":d.right=o?"0":"-"+s;break;case"right":d.left=o?"0":"-"+s}d[a[1]]=c,angular.element(r).css(d)}}}}}]),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(e){var t=this,a=t.tabs=e.tabs=[];t.select=function(e){angular.forEach(a,function(t){t.active&&t!==e&&(t.active=!1,t.onDeselect(),e.selectCalled=!1)}),e.active=!0,e.selectCalled||(e.onSelect(),e.selectCalled=!0)},t.addTab=function(e){a.push(e),1===a.length&&e.active!==!1?e.active=!0:e.active?t.select(e):e.active=!1},t.removeTab=function(e){var i=a.indexOf(e);if(e.active&&a.length>1&&!n){var o=i===a.length-1?i-1:i+1;t.select(a[o])}a.splice(i,1)};var n;e.$on("$destroy",function(){n=!0})}]).directive("uibTabset",function(){return{transclude:!0,replace:!0,scope:{type:"@"},controller:"UibTabsetController",templateUrl:"uib/template/tabs/tabset.html",link:function(e,t,a){e.vertical=angular.isDefined(a.vertical)?e.$parent.$eval(a.vertical):!1,e.justified=angular.isDefined(a.justified)?e.$parent.$eval(a.justified):!1}}}).directive("uibTab",["$parse",function(e){return{require:"^uibTabset",replace:!0,templateUrl:"uib/template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},controllerAs:"tab",link:function(t,a,n,i,o){t.$watch("active",function(e){e&&i.select(t)}),t.disabled=!1,n.disable&&t.$parent.$watch(e(n.disable),function(e){t.disabled=!!e}),t.select=function(){t.disabled||(t.active=!0)},i.addTab(t),t.$on("$destroy",function(){i.removeTab(t)}),t.$transcludeFn=o}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:"^uibTab",link:function(e,t){e.$watch("headingElement",function(e){e&&(t.html(""),t.append(e))})}}}).directive("uibTabContentTransclude",function(){function e(e){return e.tagName&&(e.hasAttribute("uib-tab-heading")||e.hasAttribute("data-uib-tab-heading")||e.hasAttribute("x-uib-tab-heading")||"uib-tab-heading"===e.tagName.toLowerCase()||"data-uib-tab-heading"===e.tagName.toLowerCase()||"x-uib-tab-heading"===e.tagName.toLowerCase())}return{restrict:"A",require:"^uibTabset",link:function(t,a,n){var i=t.$eval(n.uibTabContentTransclude);i.$transcludeFn(i.$parent,function(t){angular.forEach(t,function(t){e(t)?i.headingElement=t:a.append(t)})})}}}),angular.module("uib/template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(e){e.put("uib/template/typeahead/typeahead-match.html",'\n')}]),angular.module("uib/template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(e){e.put("uib/template/typeahead/typeahead-popup.html",'\n')}]),angular.module("uib/template/tabs/tab.html",[]).run(["$templateCache",function(e){e.put("uib/template/tabs/tab.html",'
      • \n {{heading}}\n
      • \n')}]),angular.module("uib/template/tabs/tabset.html",[]).run(["$templateCache",function(e){e.put("uib/template/tabs/tabset.html",'
        \n \n
        \n
        \n
        \n
        \n
        \n')}]),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&angular.element(document).find("head").prepend('')}); \ No newline at end of file diff --git a/LiveChat/ClientComponents/waves/waves.min.js b/LiveChat/ClientComponents/waves/waves.min.js new file mode 100644 index 0000000..a626e11 --- /dev/null +++ b/LiveChat/ClientComponents/waves/waves.min.js @@ -0,0 +1,10 @@ +/*! + * Waves v0.7.2 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + */ +!function(a,b){"use strict";"function"==typeof define&&define.amd?define([],function(){return b.apply(a)}):"object"==typeof exports?module.exports=b.call(a):a.Waves=b.call(a)}("object"==typeof global?global:this,function(){"use strict";function a(a){return null!==a&&a===a.window}function b(b){return a(b)?b:9===b.nodeType&&b.defaultView}function c(a){var b=typeof a;return"function"===b||"object"===b&&!!a}function d(a){return c(a)&&a.nodeType>0}function e(a){var b=m.call(a);return"[object String]"===b?l(a):c(a)&&/^\[object (HTMLCollection|NodeList|Object)\]$/.test(b)&&a.hasOwnProperty("length")?a:d(a)?[a]:[]}function f(a){var c,d,e={top:0,left:0},f=a&&a.ownerDocument;return c=f.documentElement,"undefined"!=typeof a.getBoundingClientRect&&(e=a.getBoundingClientRect()),d=b(f),{top:e.top+d.pageYOffset-c.clientTop,left:e.left+d.pageXOffset-c.clientLeft}}function g(a){var b="";for(var c in a)a.hasOwnProperty(c)&&(b+=c+":"+a[c]+";");return b}function h(a,b,c){if(c){c.classList.remove("waves-rippling");var d=c.getAttribute("data-x"),e=c.getAttribute("data-y"),f=c.getAttribute("data-scale"),h=c.getAttribute("data-translate"),i=Date.now()-Number(c.getAttribute("data-hold")),j=350-i;0>j&&(j=0),"mousemove"===a.type&&(j=150);var k="mousemove"===a.type?2500:o.duration;setTimeout(function(){var a={top:e+"px",left:d+"px",opacity:"0","-webkit-transition-duration":k+"ms","-moz-transition-duration":k+"ms","-o-transition-duration":k+"ms","transition-duration":k+"ms","-webkit-transform":f+" "+h,"-moz-transform":f+" "+h,"-ms-transform":f+" "+h,"-o-transform":f+" "+h,transform:f+" "+h};c.setAttribute("style",g(a)),setTimeout(function(){try{b.removeChild(c)}catch(a){return!1}},k)},j)}}function i(a){if(q.allowEvent(a)===!1)return null;for(var b=null,c=a.target||a.srcElement;null!==c.parentElement;){if(c.classList.contains("waves-effect")&&!(c instanceof SVGElement)){b=c;break}c=c.parentElement}return b}function j(a){q.registerEvent(a);var b=i(a);if(null!==b)if("touchstart"===a.type&&o.delay){var c=!1,d=setTimeout(function(){d=null,o.show(a,b)},o.delay),e=function(e){d&&(clearTimeout(d),d=null,o.show(a,b)),c||(c=!0,o.hide(e,b))},f=function(a){d&&(clearTimeout(d),d=null),e(a)};b.addEventListener("touchmove",f,!1),b.addEventListener("touchend",e,!1),b.addEventListener("touchcancel",e,!1)}else o.show(a,b),n&&(b.addEventListener("touchend",o.hide,!1),b.addEventListener("touchcancel",o.hide,!1)),b.addEventListener("mouseup",o.hide,!1),b.addEventListener("mouseleave",o.hide,!1)}var k=k||{},l=document.querySelectorAll.bind(document),m=Object.prototype.toString,n="ontouchstart"in window,o={duration:750,delay:200,show:function(a,b,c){if(2===a.button)return!1;b=b||this;var d=document.createElement("div");d.className="waves-ripple waves-rippling",b.appendChild(d);var e=f(b),h=a.pageY-e.top,i=a.pageX-e.left,j="scale("+b.clientWidth/100*3+")",k="translate(0,0)";c&&(k="translate("+c.x+"px, "+c.y+"px)"),"touches"in a&&a.touches.length&&(h=a.touches[0].pageY-e.top,i=a.touches[0].pageX-e.left),d.setAttribute("data-hold",Date.now()),d.setAttribute("data-x",i),d.setAttribute("data-y",h),d.setAttribute("data-scale",j),d.setAttribute("data-translate",k);var l={top:h+"px",left:i+"px"};d.classList.add("waves-notransition"),d.setAttribute("style",g(l)),d.classList.remove("waves-notransition"),l["-webkit-transform"]=j+" "+k,l["-moz-transform"]=j+" "+k,l["-ms-transform"]=j+" "+k,l["-o-transform"]=j+" "+k,l.transform=j+" "+k,l.opacity="1";var m="mousemove"===a.type?2500:o.duration;l["-webkit-transition-duration"]=m+"ms",l["-moz-transition-duration"]=m+"ms",l["-o-transition-duration"]=m+"ms",l["transition-duration"]=m+"ms",d.setAttribute("style",g(l))},hide:function(a,b){b=b||this;for(var c=b.getElementsByClassName("waves-rippling"),d=0,e=c.length;e>d;d++)h(a,b,c[d])}},p={input:function(a){var b=a.parentNode;if("i"!==b.tagName.toLowerCase()||!b.classList.contains("waves-effect")){var c=document.createElement("i");c.className=a.className+" waves-input-wrapper",a.className="waves-button-input",b.replaceChild(c,a),c.appendChild(a);var d=window.getComputedStyle(a,null),e=d.color,f=d.backgroundColor;c.setAttribute("style","color:"+e+";background:"+f),a.setAttribute("style","background-color:rgba(0,0,0,0);")}},img:function(a){var b=a.parentNode;if("i"!==b.tagName.toLowerCase()||!b.classList.contains("waves-effect")){var c=document.createElement("i");b.replaceChild(c,a),c.appendChild(a)}}},q={touches:0,allowEvent:function(a){var b=!0;return/^(mousedown|mousemove)$/.test(a.type)&&q.touches&&(b=!1),b},registerEvent:function(a){var b=a.type;"touchstart"===b?q.touches+=1:/^(touchend|touchcancel)$/.test(b)&&setTimeout(function(){q.touches&&(q.touches-=1)},500)}};return k.init=function(a){var b=document.body;a=a||{},"duration"in a&&(o.duration=a.duration),"delay"in a&&(o.delay=a.delay),n&&(b.addEventListener("touchstart",j,!1),b.addEventListener("touchcancel",q.registerEvent,!1),b.addEventListener("touchend",q.registerEvent,!1)),b.addEventListener("mousedown",j,!1)},k.attach=function(a,b){a=e(a),"[object Array]"===m.call(b)&&(b=b.join(" ")),b=b?" "+b:"";for(var c,d,f=0,g=a.length;g>f;f++)c=a[f],d=c.tagName.toLowerCase(),-1!==["input","img"].indexOf(d)&&(p[d](c),c=c.parentElement),c.className+=" waves-effect"+b},k.ripple=function(a,b){a=e(a);var c=a.length;if(b=b||{},b.wait=b.wait||0,b.position=b.position||null,c)for(var d,g,h,i={},j=0,k={type:"mousedown",button:1},l=function(a,b){return function(){o.hide(a,b)}};c>j;j++)if(d=a[j],g=b.position||{x:d.clientWidth/2,y:d.clientHeight/2},h=f(d),i.x=h.left+g.x,i.y=h.top+g.y,k.pageX=i.x,k.pageY=i.y,o.show(k,d),b.wait>=0&&null!==b.wait){var m={type:"mouseup",button:1};setTimeout(l(m,d),b.wait)}},k.calm=function(a){a=e(a);for(var b={type:"mouseup",button:1},c=0,d=a.length;d>c;c++)o.hide(b,a[c])},k.displayEffect=function(a){console.error("Waves.displayEffect() has been deprecated and will be removed in future version. Please use Waves.init() to initialize Waves effect"),k.init(a)},k}); +//# sourceMappingURL=waves.min.js.map \ No newline at end of file diff --git a/LiveChat/Components/AgentManager.cs b/LiveChat/Components/AgentManager.cs new file mode 100644 index 0000000..5aaae69 --- /dev/null +++ b/LiveChat/Components/AgentManager.cs @@ -0,0 +1,280 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Framework; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using MyDnn.VisitorsOnline.Components; +using DotNetNuke.Common; +using MyDnn.VisitorsOnline.Api; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class AgentManager : ServiceLocator, IAgentManager + { + protected override Func GetFactory() + { + return () => new AgentManager(); + } + + /// + /// + /// + private const string CachePrefix = "Agents_"; + + /// + /// + /// + /// + /// + public int AddAgent(AgentInfo objAgentInfo) + { + Requires.NotNull(objAgentInfo); + Requires.PropertyNotNegative(objAgentInfo, "PortalID"); + Requires.PropertyNotNegative(objAgentInfo, "UserID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objAgentInfo); + + DataCache.ClearCache(CachePrefix); + + return objAgentInfo.AgentID; + } + } + + /// + /// + /// + /// + public void UpdateAgent(AgentInfo objAgentInfo) + { + Requires.NotNull(objAgentInfo); + Requires.PropertyNotNegative(objAgentInfo, "PortalID"); + Requires.PropertyNotNegative(objAgentInfo, "UserID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objAgentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + public void DeleteAgent(int portalID, int agentID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("agentID", agentID); + + AgentInfo objAgentInfo = GetAgent(portalID, agentID); + Requires.NotNull(objAgentInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objAgentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + /// + public AgentInfo GetAgent(int portalID, int agentID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("agentID", agentID); + + return GetAgents(portalID).SingleOrDefault(a => a.AgentID == agentID); + } + + /// + /// + /// + /// + /// + /// + public AgentView GetAgentView(int portalID, int agentID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("agentID", agentID); + + return GetAgentsFullView(portalID).SingleOrDefault(a => a.AgentID == agentID); + } + + /// + /// + /// + /// + /// + /// + public AgentView GetAgentByUserName(int portalID, string agentUserName) + { + Requires.NotNegative("portalID", portalID); + + var agents = GetAgentsFullView(portalID); + return agents.FirstOrDefault(a => a.Enabled && a.UserName == agentUserName); + } + + /// + /// + /// + /// + /// + /// + public AgentView GetAgentByUserID(int portalID, int agentUserID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("agentUserID", agentUserID); + + var agents = GetAgentsFullView(portalID); + return agents.FirstOrDefault(a => a.Enabled && a.UserID == agentUserID); + } + + /// + /// + /// + /// + /// + public IEnumerable GetAgents(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(portalID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetAgentsFullView(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(portalID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetAgentsViewModel(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "AgentsViewModel_" + portalID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var agents = GetAgentsFullView(portalID); + if (agents != null) + result = from agent in agents + select new AgentViewModel + { + AgentID = agent.AgentID, + UserID = agent.UserID, + DisplayName = agent.DisplayName, + Email = agent.Email, + Enabled = agent.Enabled, + Departments = DepartmentAgentManager.Instance.GetNamesOfDepartments(portalID, agent.AgentID) + }; + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + public IEnumerable GetAgentsUserID(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "AgentsUserID_" + portalID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var agents = GetAgents(portalID); + if (agents != null) + result = agents.Where(a => a.Enabled).Select(a => a.UserID); + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + public IEnumerable GetAgentsUserName(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "AgentsUserName_" + portalID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var agents = GetAgentsFullView(portalID); + if (agents != null) + result = agents.Where(a => a.Enabled).Select(a => a.UserName); + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + public bool IsAgentOnline(int portalID) + { + Requires.NotNegative("portalID", portalID); + + var usersOnline = VisitorsOnlineApi.Instance.GetVisitorsOnline(portalID); + + var agents = GetAgentsUserID(portalID); + + return usersOnline.Any(u => agents.Contains(u.UserID)); + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/Common/Common.cs b/LiveChat/Components/Common/Common.cs new file mode 100644 index 0000000..daf2982 --- /dev/null +++ b/LiveChat/Components/Common/Common.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Data; +using System.IO; + +namespace MyDnn.Modules.Support.LiveChat.Components.Common +{ + internal class Common + { + public static Common Instance + { + get + { + return new Common(); + } + } + + internal IEnumerable GetUsersByDisplayName(int portalID, string name) + { + return DataContext.Instance().ExecuteQuery(System.Data.CommandType.Text, string.Format("Select [UserID],[DisplayName] From [vw_Users] Where ([PortalID] is null or [PortalID] = {0}) and [DisplayName] like N'%{1}%'", portalID, name)); + } + + internal string GetUserDisplayName(int userID) + { + return DataContext.Instance().ExecuteScalar(System.Data.CommandType.Text, string.Format("Select DisplayName From Users Where [UserID]={0}", userID)); + } + + internal static string GetFileContent(string filename) + { + StreamReader objStreamReader = default(StreamReader); + objStreamReader = File.OpenText(filename); + string template = objStreamReader.ReadToEnd(); + objStreamReader.Close(); + return template; + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/Common/Localization.cs b/LiveChat/Components/Common/Localization.cs new file mode 100644 index 0000000..d0f0b8b --- /dev/null +++ b/LiveChat/Components/Common/Localization.cs @@ -0,0 +1,211 @@ +using DotNetNuke.Common.Utilities; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Resources; +using System.Web; +using System.Xml; + +namespace MyDnn.Modules.Support.LiveChat.Components.Common +{ + /// + /// + /// + public class Localization + { + /// + /// + /// + public static Localization Instance + { + get + { + return new Localization(); + } + } + + /// + /// + /// + /// + /// + /// + public Hashtable GetResources(string resource, string culture) + { + string currentCulture = (culture.ToLower() == "en-us" ? "" : "." + culture); + var resourceFilePath = HttpContext.Current.Request.MapPath(string.Format("{0}{1}.resx", resource, currentCulture)); + if (!File.Exists(resourceFilePath)) + resourceFilePath = HttpContext.Current.Request.MapPath(string.Format("{0}.resx", resource)); + + var cacheKey = Path.GetFileNameWithoutExtension(resourceFilePath); + + var result = DataCache.GetCache(cacheKey); + if (result != null) + return result; + + result = new Hashtable(); + + var d = new XmlDocument(); + bool xmlLoaded = false; + try + { + d.Load(resourceFilePath); + xmlLoaded = true; + } + catch + { + xmlLoaded = false; + } + if (xmlLoaded) + { + XmlNode n = null; + foreach (XmlNode n_loopVariable in d.SelectNodes("root/data")) + { + try + { + + n = n_loopVariable; + if (n.NodeType != XmlNodeType.Comment) + { + string val = n.SelectSingleNode("value").InnerXml; + string name = n.Attributes["name"].Value; + if (result[name] == null) + { + result.Add(name, val); + } + else + { + result[name] = val; + } + } + } + catch + { + } + } + } + + DataCache.SetCache(cacheKey, result); + + return result; + } + + /// + /// + /// + /// + /// + /// + /// + public string GetString(string resource, string curCulture, string key) + { + var resources = GetResources(resource, curCulture); + + return resources[key].ToString(); + } + + /// + /// + /// + /// + /// + /// + /// + public void UpdateString(string resource, string curCulture, string key, string value) + { + string currentCulture = (curCulture.ToLower() == "en-us" ? "" : "." + curCulture); + var resourceFilePath = HttpContext.Current.Request.MapPath(string.Format("{0}{1}.resx", resource, currentCulture)); + if (!File.Exists(resourceFilePath)) + resourceFilePath = HttpContext.Current.Request.MapPath(string.Format("{0}.resx", resource)); + + if (!File.Exists(resourceFilePath)) + return; + + try + { + XmlNode node; + XmlNode nodeData; + XmlAttribute attr; + + var resDoc = new XmlDocument(); + resDoc.Load(resourceFilePath); + + node = resDoc.SelectSingleNode("//root/data[@name='" + key + "']/value"); + if (node == null) + { + //missing entry + nodeData = resDoc.CreateElement("data"); + attr = resDoc.CreateAttribute("name"); + attr.Value = key; + nodeData.Attributes.Append(attr); + resDoc.SelectSingleNode("//root").AppendChild(nodeData); + + node = nodeData.AppendChild(resDoc.CreateElement("value")); + } + node.InnerXml = value; + + resDoc.Save(resourceFilePath); + } + catch + { + } + } + + /// + /// + /// + /// + /// + /// + /// + public void UpdateStrings(string resource, string curCulture, Hashtable locales) + { + string currentCulture = (curCulture.ToLower() == "en-us" ? "" : "." + curCulture); + var resourceFilePath = HttpContext.Current.Request.MapPath(string.Format("{0}{1}.resx", resource, currentCulture)); + if (!File.Exists(resourceFilePath)) + resourceFilePath = HttpContext.Current.Request.MapPath(string.Format("{0}.resx", resource)); + + if (!File.Exists(resourceFilePath)) + return; + + try + { + XmlNode node; + XmlNode nodeData; + XmlAttribute attr; + + var resDoc = new XmlDocument(); + resDoc.Load(resourceFilePath); + + foreach (DictionaryEntry item in locales) + { + node = resDoc.SelectSingleNode("//root/data[@name='" + item.Key + "']/value"); + if (node == null) + { + //missing entry + nodeData = resDoc.CreateElement("data"); + attr = resDoc.CreateAttribute("name"); + attr.Value = item.Key.ToString(); + nodeData.Attributes.Append(attr); + resDoc.SelectSingleNode("//root").AppendChild(nodeData); + + node = nodeData.AppendChild(resDoc.CreateElement("value")); + } + node.InnerXml = item.Value.ToString(); + + } + + resDoc.Save(resourceFilePath); + + var cacheKey = Path.GetFileNameWithoutExtension(resourceFilePath); + DataCache.ClearCache(cacheKey); + } + catch + { + } + } + + } +} \ No newline at end of file diff --git a/LiveChat/Components/DepartmentAgentManager.cs b/LiveChat/Components/DepartmentAgentManager.cs new file mode 100644 index 0000000..292479c --- /dev/null +++ b/LiveChat/Components/DepartmentAgentManager.cs @@ -0,0 +1,240 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Framework; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChats.ViewModels; +using MyDnn.VisitorsOnline.Api; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class DepartmentAgentManager : ServiceLocator, IDepartmentAgentManager + { + protected override Func GetFactory() + { + return () => new DepartmentAgentManager(); + } + + /// + /// + /// + private const string CachePrefix = "DepartmentAgents_"; + + /// + /// + /// + /// + public void AddDepartmentAgent(DepartmentAgentInfo objDepartmentAgentInfo) + { + Requires.NotNull(objDepartmentAgentInfo); + Requires.PropertyNotNegative(objDepartmentAgentInfo, "DepartmentID"); + Requires.PropertyNotNegative(objDepartmentAgentInfo, "AgentID"); + Requires.PropertyNotNegative(objDepartmentAgentInfo, "UserID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objDepartmentAgentInfo); + } + + DataCache.ClearCache(); + } + + /// + /// + /// + /// + public void UpdateDepartmentAgent(DepartmentAgentInfo objDepartmentAgentInfo) + { + Requires.PropertyNotNegative(objDepartmentAgentInfo, "DepartmentID"); + Requires.PropertyNotNegative(objDepartmentAgentInfo, "AgentID"); + Requires.PropertyNotNegative(objDepartmentAgentInfo, "UserID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objDepartmentAgentInfo); + } + + DataCache.ClearCache(); + } + + /// + /// + /// + /// + public void DeleteDepartmentAgent(int departmentID, int departmentAgentID) + { + Requires.NotNegative("departmentAgentID", departmentAgentID); + + DepartmentAgentInfo objDepartmentAgentInfo = GetDepartmentAgent(departmentID, departmentAgentID); + Requires.NotNull(objDepartmentAgentInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objDepartmentAgentInfo); + } + + DataCache.ClearCache(); + } + + /// + /// + /// + /// + public void DeleteAgentDepartments(int agentID) + { + Requires.NotNegative("agentID", agentID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete("Where ([AgentID]=@0)", agentID); + + DataCache.ClearCache(CachePrefix); + } + + DataCache.ClearCache(); + } + + /// + /// + /// + /// + /// + /// + public bool IsAgentOnlineByDepartment(int portalID, int departmentID) + { + var agents = GetDepartmentAgents(departmentID); + var usersOnline = VisitorsOnlineApi.Instance.GetVisitorsOnline(portalID); + bool isAgentOnline = false; + if (usersOnline != null && agents != null) + { + isAgentOnline = usersOnline.Any(u => agents.Select(a => a.UserID).Contains(u.UserID)); + } + return isAgentOnline; + } + + /// + /// + /// + /// + /// + public DepartmentAgentInfo GetDepartmentAgent(int departmentID, int departmentAgentID) + { + Requires.NotNegative("departmentID", departmentID); + Requires.NotNegative("departmentAgentID", departmentAgentID); + + return GetDepartmentAgents(departmentID).SingleOrDefault(da => da.DepartmentAgentID == departmentAgentID); + } + + /// + /// + /// + /// + /// + public IEnumerable GetDepartmentAgents(int departmentID) + { + Requires.NotNegative("departmentID", departmentID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(departmentID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetDepartmentAgentsViewModel(int departmentID) + { + Requires.NotNegative("departmentID", departmentID); + + string cacheKey = CachePrefix + "DepartmentAgentsViewModel_" + departmentID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var departmentAgents = GetDepartmentAgents(departmentID); + if (departmentAgents != null) + result = from agent in departmentAgents + select new DepartmentAgentViewModel + { + DepartmentID = agent.DepartmentID, + AgentID = agent.AgentID, + UserID = agent.UserID, + DisplayName = Common.Common.Instance.GetUserDisplayName(agent.UserID) + }; + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + public IEnumerable GetAgentDepartments(int agentID) + { + Requires.NotNegative("agentID", agentID); + + string cacheKey = "LSAgentDepartments_" + agentID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + result= rep.Find("Where (AgentID=@0)", agentID); + } + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + /// + public IEnumerable GetNamesOfDepartments(int portalID, int agentID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("agentID", agentID); + + string cacheKey = CachePrefix + "AgentDepartmentNames" + agentID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var agentDepartments = GetAgentDepartments(agentID); + var departments = DepartmentManager.Instance.GetDepartments(portalID); + if (agentDepartments != null && departments != null) + result = from agentdep in agentDepartments + join department in departments on agentdep.DepartmentID equals department.DepartmentID + select department.DepartmentName; + + DataCache.SetCache(cacheKey, result); + } + return result; + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/DepartmentManager.cs b/LiveChat/Components/DepartmentManager.cs new file mode 100644 index 0000000..f21a1e1 --- /dev/null +++ b/LiveChat/Components/DepartmentManager.cs @@ -0,0 +1,180 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Common; +using MyDnn.Modules.Support.LiveChats.ViewModels; +using DotNetNuke.Framework; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class DepartmentManager : ServiceLocator, IDepartmentManager + { + protected override Func GetFactory() + { + return () => new DepartmentManager(); + } + + /// + /// + /// + private const string CachePrefix = "Departments_"; + + /// + /// + /// + /// + /// + public int AddDepartment(DepartmentInfo objDepartmentInfo) + { + Requires.NotNull(objDepartmentInfo); + Requires.PropertyNotNegative(objDepartmentInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objDepartmentInfo); + + DataCache.ClearCache(CachePrefix); + + return objDepartmentInfo.DepartmentID; + } + } + + /// + /// + /// + /// + public void UpdateDepartment(DepartmentInfo objDepartmentInfo) + { + Requires.NotNull(objDepartmentInfo); + Requires.PropertyNotNegative(objDepartmentInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objDepartmentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + public void DeleteDepartment(int portalID, int departmentID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("departmentID", departmentID); + + DepartmentInfo objDepartmentInfo = GetDepartment(portalID,departmentID); + Requires.NotNull(objDepartmentInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objDepartmentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + /// + public DepartmentInfo GetDepartment(int portalID, int departmentID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("departmentID", departmentID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.GetById(departmentID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetDepartments(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(portalID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetDepartmentsViewModel(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "DepartmentsViewModel_" + portalID; + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var departments = GetDepartments(portalID); + if (departments != null) + result = from dep in departments + select new DepartmentViewModel + { + DepartmentID = dep.DepartmentID, + DepartmentName = dep.DepartmentName, + Description = dep.Description, + TicketEnabled = dep.TicketEnabled, + LiveChatEnabled = dep.LiveChatEnabled, + Agents = DepartmentAgentManager.Instance.GetDepartmentAgentsViewModel(dep.DepartmentID) + }; + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + public IEnumerable GetDepartmentsForLiveChat(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "DepartmentsForLiveChat_" + portalID; + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + var departments = GetDepartments(portalID); + if (departments != null) + result = departments.Where(d => d.LiveChatEnabled); + + DataCache.SetCache(cacheKey, result); + } + return result; + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/Enums/LiveChatJoinPermission.cs b/LiveChat/Components/Enums/LiveChatJoinPermission.cs new file mode 100644 index 0000000..0b0f0f3 --- /dev/null +++ b/LiveChat/Components/Enums/LiveChatJoinPermission.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Components.Enums +{ + internal enum LiveChatJoinPermission + { + OnlyCurrentAgents, + OnlyCurrentAgentsAndAdmin, + AllAgentsInDepartment + } +} \ No newline at end of file diff --git a/LiveChat/Components/Enums/LiveChatRating.cs b/LiveChat/Components/Enums/LiveChatRating.cs new file mode 100644 index 0000000..895f572 --- /dev/null +++ b/LiveChat/Components/Enums/LiveChatRating.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Components.Enums +{ + public enum LiveChatRating + { + None, + Good, + Bad + } +} \ No newline at end of file diff --git a/LiveChat/Components/Enums/LiveChatViewPermission.cs b/LiveChat/Components/Enums/LiveChatViewPermission.cs new file mode 100644 index 0000000..7600a41 --- /dev/null +++ b/LiveChat/Components/Enums/LiveChatViewPermission.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Components.Enums +{ + internal enum LiveChatViewPermission + { + OnlyCurrentAgents, + OnlyCurrentAgentsAndAdmin, + AllAgentsInDepartment + } +} \ No newline at end of file diff --git a/LiveChat/Components/Enums/MessageSentBy.cs b/LiveChat/Components/Enums/MessageSentBy.cs new file mode 100644 index 0000000..156916b --- /dev/null +++ b/LiveChat/Components/Enums/MessageSentBy.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Components.Enums +{ + public enum MessageSentBy + { + System, + Visitor, + Agent + } +} \ No newline at end of file diff --git a/LiveChat/Components/Enums/MessageType.cs b/LiveChat/Components/Enums/MessageType.cs new file mode 100644 index 0000000..7f6d7a4 --- /dev/null +++ b/LiveChat/Components/Enums/MessageType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Components.Enums +{ + public enum MessageType + { + Text, + File + } +} \ No newline at end of file diff --git a/LiveChat/Components/IAgentManager.cs b/LiveChat/Components/IAgentManager.cs new file mode 100644 index 0000000..38be9a6 --- /dev/null +++ b/LiveChat/Components/IAgentManager.cs @@ -0,0 +1,108 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Linq; +using DotNetNuke.Collections; +using System.Collections.Generic; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChat.ViewModels; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + interface IAgentManager + { + int AddAgent(AgentInfo objAgentInfo); + + /// + /// + /// + /// + void UpdateAgent(AgentInfo objAgentInfo); + + /// + /// + /// + /// + /// + void DeleteAgent(int portalID, int agentID); + + /// + /// + /// + /// + /// + /// + AgentInfo GetAgent(int portalID, int agentID); + + /// + /// + /// + /// + /// + /// + AgentView GetAgentView(int portalID, int agentID); + + /// + /// + /// + /// + /// + /// + AgentView GetAgentByUserName(int portalID, string agentUserName); + + /// + /// + /// + /// + /// + /// + AgentView GetAgentByUserID(int portalID, int agentUserID); + + /// + /// + /// + /// + /// + IEnumerable GetAgents(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetAgentsFullView(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetAgentsViewModel(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetAgentsUserID(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetAgentsUserName(int portalID); + + /// + /// + /// + /// + /// + bool IsAgentOnline(int portalID); + } +} + + diff --git a/LiveChat/Components/IDepartmentAgentManager.cs b/LiveChat/Components/IDepartmentAgentManager.cs new file mode 100644 index 0000000..086b556 --- /dev/null +++ b/LiveChat/Components/IDepartmentAgentManager.cs @@ -0,0 +1,86 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MyDnn.Modules.Support.LiveChats.ViewModels; +using MyDnn.Modules.Support.LiveChat.Models; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + interface IDepartmentAgentManager + { + /// + /// + /// + /// + void AddDepartmentAgent(DepartmentAgentInfo objDepartmentAgentInfo); + + /// + /// + /// + /// + void UpdateDepartmentAgent(DepartmentAgentInfo objDepartmentAgentInfo); + + /// + /// + /// + /// + void DeleteDepartmentAgent(int departmentID, int departmentAgentID); + + /// + /// + /// + /// + void DeleteAgentDepartments(int agentID); + + /// + /// + /// + /// + /// + /// + bool IsAgentOnlineByDepartment(int portalID, int departmentID); + + /// + /// + /// + /// + /// + DepartmentAgentInfo GetDepartmentAgent(int departmentID, int departmentAgentID); + + /// + /// + /// + /// + /// + IEnumerable GetDepartmentAgents(int departmentID); + + /// + /// + /// + /// + /// + IEnumerable GetDepartmentAgentsViewModel(int departmentID); + + /// + /// + /// + /// + /// + IEnumerable GetAgentDepartments(int agentID); + + /// + /// + /// + /// + /// + /// + IEnumerable GetNamesOfDepartments(int portalID, int agentID); + } +} diff --git a/LiveChat/Components/IDepartmentManager.cs b/LiveChat/Components/IDepartmentManager.cs new file mode 100644 index 0000000..a53cb72 --- /dev/null +++ b/LiveChat/Components/IDepartmentManager.cs @@ -0,0 +1,68 @@ +// Copyright (c); MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChats.ViewModels; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + interface IDepartmentManager + { + /// + /// + /// + /// + /// + int AddDepartment(DepartmentInfo objDepartmentInfo); + + /// + /// + /// + /// + void UpdateDepartment(DepartmentInfo objDepartmentInfo); + + /// + /// + /// + /// + /// + void DeleteDepartment(int portalID, int departmentID); + + /// + /// + /// + /// + /// + /// + DepartmentInfo GetDepartment(int portalID, int departmentID); + + /// + /// + /// + /// + /// + IEnumerable GetDepartments(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetDepartmentsViewModel(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetDepartmentsForLiveChat(int portalID); + } +} \ No newline at end of file diff --git a/LiveChat/Components/ILiveChatAgentManager.cs b/LiveChat/Components/ILiveChatAgentManager.cs new file mode 100644 index 0000000..1f4d64b --- /dev/null +++ b/LiveChat/Components/ILiveChatAgentManager.cs @@ -0,0 +1,62 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Common; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChat.ViewModels; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + interface ILiveChatAgentManager { + + /// + /// + /// + /// + /// + int AddLiveChatAgent(LiveChatAgentInfo objLiveChatAgentInfo); + + /// + /// + /// + /// + void UpdateLiveChatAgent(LiveChatAgentInfo objLiveChatAgentInfo); + + /// + /// + /// + /// + void DeleteLiveChatAgent(int livechatAgentID); + + /// + /// + /// + /// + /// + LiveChatAgentInfo GetLiveChatAgentByID(int livechatAgentID); + + /// + /// + /// + /// + /// + IEnumerable GetLiveChatAgents(int livechatID); + + /// + /// + /// + /// + /// + /// + IEnumerable GetLiveChatAgentsViewModel(int portalID, int livechatID); + } +} \ No newline at end of file diff --git a/LiveChat/Components/ILiveChatDepartmentManager.cs b/LiveChat/Components/ILiveChatDepartmentManager.cs new file mode 100644 index 0000000..6ba730c --- /dev/null +++ b/LiveChat/Components/ILiveChatDepartmentManager.cs @@ -0,0 +1,54 @@ +// Copyright (c); MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.Common.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Framework; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChat.ViewModels; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + interface ILiveChatDepartmentManager + { + /// + /// + /// + /// + /// + int AddLiveChatDepartment(LiveChatDepartmentInfo objLiveChatDepartmentInfo); + + /// + /// + /// + /// + void DeleteLiveChatDepartment(int livechatDepartmentID); + + /// + /// + /// + /// + /// + LiveChatDepartmentInfo GetLiveChatDepartmentByID(int livechatDepartmentID); + + /// + /// + /// + /// + /// + IEnumerable GetLiveChatDepartments(int livechatID); + + /// + /// + /// + /// + /// + IEnumerable GetLiveChatDepartmentsViewModel(int portalID, int livechatID); + } +} \ No newline at end of file diff --git a/LiveChat/Components/ILiveChatManager.cs b/LiveChat/Components/ILiveChatManager.cs new file mode 100644 index 0000000..c4b04fc --- /dev/null +++ b/LiveChat/Components/ILiveChatManager.cs @@ -0,0 +1,133 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Common; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using DotNetNuke.Collections; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + interface ILiveChatManager + { + /// + /// + /// + /// + /// + int AddLiveChat(LiveChatInfo objLiveChatInfo); + + /// + /// + /// + /// + void UpdateLiveChat(LiveChatInfo objLiveChatInfo); + + /// + /// + /// + /// + void DeleteLiveChat(int livechatID); + + /// + /// + /// + /// + /// + /// + void StartLiveChat(int livechatID, int agentID, int agentUserID); + + + /// + /// + /// + /// + /// + void CloseLiveChat(int livechatID, bool closedByAgent); + + /// + /// + /// + /// + void CloseLeftLiveChats(int portalID); + + /// + /// + /// + /// + /// + LiveChatInfo GetLiveChatByID(int livechatID); + + /// + /// + /// + /// + /// + /// + LiveChatInfo GetCurrentLiveChatByVisitor(int portalID, string visitorGUID); + + /// + /// + /// + /// + /// + /// + bool hasVisitorOpenedLiveChat(int portalID, string visitorGUID); + + /// + /// + /// + /// + /// + IEnumerable GetLiveChats(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetCurrentLiveChats(int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetIncomingLiveChats(int portalID); + + /// + /// + /// + /// + /// + /// + IEnumerable GetCurrentLiveChatsByAgent(int portalID, int agentUserID); + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + IPagedList GetChatHistory(int portalID, int type, string departments, string agents, string visitorEmail, DateTime? fromDate, DateTime? toDate, int rating, bool unread, int pageIndex, int pageSize, int totalCount); + + /// + /// + /// + /// + void PurgeHistory(int[] items); + } +} \ No newline at end of file diff --git a/LiveChat/Components/ILiveChatMessageManager.cs b/LiveChat/Components/ILiveChatMessageManager.cs new file mode 100644 index 0000000..9472237 --- /dev/null +++ b/LiveChat/Components/ILiveChatMessageManager.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Common; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + interface ILiveChatMessageManager + { + /// + /// + /// + /// + /// + int AddMessage(LiveChatMessageInfo objLiveChatMessageInfo); + + /// + /// + /// + /// + void SeenMessage(int messageID); + + /// + /// + /// + /// + void DeleteMessage(int liveChatID); + + /// + /// + /// + /// + /// + LiveChatMessageInfo GetMessageByID(int livechatMessageID); + + /// + /// + /// + /// + /// + IEnumerable GetMessages(int livechatID); + + /// + /// + /// + /// + /// + /// + IEnumerable GetUnreadMessages(int livechatID, int messageID); + } +} \ No newline at end of file diff --git a/LiveChat/Components/LiveChatAgentManager.cs b/LiveChat/Components/LiveChatAgentManager.cs new file mode 100644 index 0000000..4ccc34f --- /dev/null +++ b/LiveChat/Components/LiveChatAgentManager.cs @@ -0,0 +1,167 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Framework; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Common; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using MyDnn.VisitorsOnline.Api; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class LiveChatAgentManager : ServiceLocator, ILiveChatAgentManager + { + protected override Func GetFactory() + { + return () => new LiveChatAgentManager(); + } + + /// + /// + /// + private const string CachePrefix = "LiveChatAgents_"; + + /// + /// + /// + /// + /// + public int AddLiveChatAgent(LiveChatAgentInfo objLiveChatAgentInfo) + { + objLiveChatAgentInfo.LeftDate = DateTime.MaxValue; + + Requires.NotNull(objLiveChatAgentInfo); + Requires.PropertyNotNegative(objLiveChatAgentInfo, "LiveChatID"); + Requires.PropertyNotNegative(objLiveChatAgentInfo, "UserID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objLiveChatAgentInfo); + + DataCache.ClearCache(CachePrefix); + + return objLiveChatAgentInfo.LiveChatID; + } + } + + /// + /// + /// + /// + public void UpdateLiveChatAgent(LiveChatAgentInfo objLiveChatAgentInfo) + { + Requires.NotNull(objLiveChatAgentInfo); + Requires.PropertyNotNegative(objLiveChatAgentInfo, "LiveChatID"); + Requires.PropertyNotNegative(objLiveChatAgentInfo, "UserID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objLiveChatAgentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + public void DeleteLiveChatAgent(int livechatAgentID) + { + Requires.NotNegative("livechatAgentID", livechatAgentID); + + LiveChatAgentInfo objLiveChatAgentInfo = GetLiveChatAgentByID(livechatAgentID); + Requires.NotNull(objLiveChatAgentInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objLiveChatAgentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + public LiveChatAgentInfo GetLiveChatAgentByID(int livechatAgentID) + { + Requires.NotNegative("livechatAgentID", livechatAgentID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.GetById(livechatAgentID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetLiveChatAgents(int livechatID) + { + Requires.NotNegative("livechatID", livechatID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(livechatID); + } + } + + /// + /// + /// + /// + /// + /// + public IEnumerable GetLiveChatAgentsViewModel(int portalID, int livechatID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("livechatID", livechatID); + + string cacheKey = CachePrefix + "ViewModel_" + livechatID; + var result = (List)DataCache.GetCache(cacheKey); + if (result == null) + { + result = new List(); + + var agents = GetLiveChatAgents(livechatID); + foreach (LiveChatAgentInfo agent in agents) + { + var objAgentView = AgentManager.Instance.GetAgentByUserID(portalID, agent.UserID); + result.Add(new LiveChatAgentViewModel() + { + AgentID = objAgentView.AgentID, + UserID = objAgentView.UserID, + DisplayName = objAgentView.DisplayName, + Email = objAgentView.Email, + Avatar = DotNetNuke.Common.Globals.ResolveUrl("~/dnnimagehandler.ashx?mode=profilepic&userid=" + objAgentView.UserID), + JoinDate = agent.JoinDate, + LeftDate = agent.LeftDate, + IsOnline = VisitorsOnlineApi.Instance.IsVisitorOnline(portalID, objAgentView.UserID) + }); + } + + DataCache.SetCache(cacheKey, result); + } + return result; + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/LiveChatDepartmentManager.cs b/LiveChat/Components/LiveChatDepartmentManager.cs new file mode 100644 index 0000000..b9db256 --- /dev/null +++ b/LiveChat/Components/LiveChatDepartmentManager.cs @@ -0,0 +1,123 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.Common.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Framework; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using DotNetNuke.Common; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class LiveChatDepartmentManager : ServiceLocator, ILiveChatDepartmentManager + { + protected override Func GetFactory() + { + return () => new LiveChatDepartmentManager(); + } + + /// + /// + /// + private const string CachePrefix = "LiveChatDepartments_"; + + /// + /// + /// + /// + /// + public int AddLiveChatDepartment(LiveChatDepartmentInfo objLiveChatDepartmentInfo) + { + Requires.NotNull(objLiveChatDepartmentInfo); + Requires.PropertyNotNegative(objLiveChatDepartmentInfo, "LiveChatID"); + Requires.PropertyNotNegative(objLiveChatDepartmentInfo, "DepartmentID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objLiveChatDepartmentInfo); + + DataCache.ClearCache(CachePrefix); + + return objLiveChatDepartmentInfo.LiveChatID; + } + } + + /// + /// + /// + /// + public void DeleteLiveChatDepartment(int livechatDepartmentID) + { + Requires.NotNegative("livechatDepartmentID", livechatDepartmentID); + + LiveChatDepartmentInfo objLiveChatDepartmentInfo = GetLiveChatDepartmentByID(livechatDepartmentID); + Requires.NotNull(objLiveChatDepartmentInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objLiveChatDepartmentInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + public LiveChatDepartmentInfo GetLiveChatDepartmentByID(int livechatDepartmentID) + { + Requires.NotNegative("livechatDepartmentID", livechatDepartmentID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.GetById(livechatDepartmentID); + } + } + + public IEnumerable GetLiveChatDepartments(int livechatID) + { + Requires.NotNegative("livechatID", livechatID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(livechatID); + } + } + + public IEnumerable GetLiveChatDepartmentsViewModel(int portalID, int livechatID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("livechatID", livechatID); + + string cacheKey = CachePrefix + "ViewModel_" + livechatID; + + var result = (List)DataCache.GetCache(cacheKey); + if (result == null) + { + result = new List(); + var livechatDepartments = GetLiveChatDepartments(livechatID); + var departments = DepartmentManager.Instance.GetDepartments(portalID); + foreach (LiveChatDepartmentInfo department in livechatDepartments) + { + result.Add(new LiveChatDepartmentViewModel() + { + DepartmentID = department.DepartmentID, + DepartmentName = departments.SingleOrDefault(d => d.DepartmentID == department.DepartmentID).DepartmentName, + CreateDate = department.CreateDate + }); + } + DataCache.SetCache(cacheKey, result); + } + return result; + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/LiveChatManager.cs b/LiveChat/Components/LiveChatManager.cs new file mode 100644 index 0000000..ca24227 --- /dev/null +++ b/LiveChat/Components/LiveChatManager.cs @@ -0,0 +1,405 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Common; +using DotNetNuke.Framework; +using System.Text; +using System.Data.SqlTypes; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using DotNetNuke.Collections; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class LiveChatManager : ServiceLocator, ILiveChatManager + { + protected override Func GetFactory() + { + return () => new LiveChatManager(); + } + + /// + /// + /// + private const string CachePrefix = "LiveChats_"; + + /// + /// + /// + /// + /// + public int AddLiveChat(LiveChatInfo objLiveChatInfo) + { + Requires.NotNull(objLiveChatInfo); + Requires.PropertyNotNegative(objLiveChatInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + objLiveChatInfo.LastMessageDate = DateTime.Now; + var rep = ctx.GetRepository(); + rep.Insert(objLiveChatInfo); + + DataCache.ClearCache(CachePrefix); + + return objLiveChatInfo.LiveChatID; + } + } + + /// + /// + /// + /// + public void UpdateLiveChat(LiveChatInfo objLiveChatInfo) + { + Requires.NotNull(objLiveChatInfo); + Requires.PropertyNotNegative(objLiveChatInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objLiveChatInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + public void DeleteLiveChat(int livechatID) + { + Requires.NotNegative("livechatID", livechatID); + + LiveChatInfo objLiveChatInfo = GetLiveChatByID(livechatID); + Requires.NotNull(objLiveChatInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objLiveChatInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + /// + public void StartLiveChat(int livechatID, int agentID, int agentUserID) + { + Requires.NotNegative("livechatID", livechatID); + Requires.NotNegative("agentID", agentID); + Requires.NotNegative("agentUserID", agentUserID); + + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatStart", livechatID, agentID, agentUserID); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + public void CloseLiveChat(int livechatID, bool closedByAgent) + { + Requires.NotNegative("livechatID", livechatID); + + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatClose", livechatID, closedByAgent); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + public void CloseLeftLiveChats(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatCloseLeftChats", portalID); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + public LiveChatInfo GetLiveChatByID(int livechatID) + { + Requires.NotNegative("livechatID", livechatID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.GetById(livechatID); + } + } + + /// + /// + /// + /// + /// + /// + public bool hasVisitorOpenedLiveChat(int portalID, string visitorGUID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Find("Where (PortalID = @0 and VisitorGUID = @1 and IsClosed=0)", portalID, visitorGUID).Any(); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetLiveChats(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(portalID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetIncomingLiveChats(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "IncomingLiveChats_" + portalID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + using (IDataContext ctx = DataContext.Instance()) + { + result = ctx.ExecuteQuery(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatGetIncomingChats", portalID); + } + + DataCache.SetCache(cacheKey, result); + } + return result; + + } + + /// + /// + /// + /// + /// + public IEnumerable GetCurrentLiveChats(int portalID) + { + Requires.NotNegative("portalID", portalID); + + string cacheKey = CachePrefix + "CurrentLiveChats_" + portalID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + using (IDataContext ctx = DataContext.Instance()) + { + result = ctx.ExecuteQuery(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatGetCurrentChats", portalID); + } + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + /// + /// + /// + /// + /// + /// + public LiveChatInfo GetCurrentLiveChatByVisitor(int portalID, string visitorGUID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + return ctx.ExecuteSingleOrDefault(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatGetVisitorCurrentChat", portalID, visitorGUID); + } + } + + /// + /// + /// + /// + /// + /// + public IEnumerable GetCurrentLiveChatsByAgent(int portalID, int agentUserID) + { + Requires.NotNegative("portalID", portalID); + Requires.NotNegative("agentUserID", agentUserID); + + string cacheKey = CachePrefix + "CurrentLiveChats_" + portalID + "_" + agentUserID; + + var result = (IEnumerable)DataCache.GetCache(cacheKey); + if (result == null) + { + using (IDataContext ctx = DataContext.Instance()) + { + result = ctx.ExecuteQuery(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatGetCurrentChats", portalID, agentUserID); + } + + DataCache.SetCache(cacheKey, result); + } + return result; + } + + public IPagedList GetChatHistory(int portalID, int type, string departments, string agents, string visitorEmail, DateTime? fromDate, DateTime? toDate, int rating, bool unread, int pageIndex, int pageSize, int totalCount) + { + var condition = new StringBuilder(string.Format("PortalID={0} ", portalID)); + + string dbo = DataProvider.Instance().DatabaseOwner; + string oq = DataProvider.Instance().ObjectQualifier; + + //all | chat | offline + if (type == 1) //chat + condition.AppendFormat(" and LiveChatID in (Select LiveChatID From {0}[{1}MyDnnSupport_LiveChatAgents])", dbo, oq); + else if (type == 2) //offline + condition.AppendFormat(" and LiveChatID not in (Select LiveChatID From {0}[{1}MyDnnSupport_LiveChatAgents])", dbo, oq); + + if (rating == 1 || rating == 2) + condition.Append(string.Format(" and Rate = {0}", rating)); + else if (rating == 3) + condition.Append(" and (Rate = 1 or Rate = 2)"); + + //departments + if (type != 2 && !string.IsNullOrEmpty(departments)) + { + string departmentsCondition = " and LiveChatID in (Select LiveChatID From {0}[{1}MyDnnSupport_LiveChatDepartments] Where {2})"; + foreach (var dep in departments.Split(',')) + { + int value; + if (int.TryParse(dep, out value)) + { + departmentsCondition = departmentsCondition.Replace("[OR]", " or {0}"); + departmentsCondition = string.Format(departmentsCondition, dbo, oq, string.Format("DepartmentID = {0} [OR]", value)); + } + } + departmentsCondition = departmentsCondition.Replace("[OR]", string.Empty); + condition.Append(departmentsCondition); + } + + //agents + if (type != 2 && !string.IsNullOrEmpty(agents)) + { + string agentsCondition = " and LiveChatID in (Select LiveChatID From {0}[{1}MyDnnSupport_LiveChatAgents] Where {2})"; + foreach (var agent in agents.Split(',')) + { + int value; + if (int.TryParse(agent, out value)) + { + agentsCondition = agentsCondition.Replace("[OR]", " or {0}"); + agentsCondition = string.Format(agentsCondition, dbo, oq, string.Format("UserID = {0} [OR]", value)); + } + } + agentsCondition = agentsCondition.Replace("[OR]", string.Empty); + condition.Append(agentsCondition); + } + + //visitor email + if (!string.IsNullOrEmpty(visitorEmail)) + condition.AppendFormat(" and VisitorEmail like N'%{0}%'", visitorEmail); + + //date range + condition.AppendFormat(" and CreateDate >= '{0}' and CreateDate<= '{1}'", fromDate != null ? fromDate : SqlDateTime.MinValue.Value, toDate != null ? toDate : SqlDateTime.MaxValue.Value); + + int from = pageIndex * pageSize + 1; + int to = from + pageSize; + + string query = string.Format("SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY CreateDate desc) AS RowNum, * FROM {0}[{1}MyDnnSupport_LiveChats] Where {2}) AS RowConstrainedResult WHERE RowNum >= {3} AND RowNum < {4} ORDER BY RowNum", dbo, oq, condition.ToString(), from, to); + + var allDepartments = DepartmentManager.Instance.GetDepartments(portalID); + var allAgents = AgentManager.Instance.GetAgents(portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + if (pageIndex == 0) + totalCount = ctx.ExecuteScalar(System.Data.CommandType.Text, string.Format("Select Count(*) From {0}[{1}MyDnnSupport_LiveChats] Where {2}", dbo, oq, condition)); + + var livechats = ctx.ExecuteQuery(System.Data.CommandType.Text, query); + + var result = livechats.Select(r => new LiveChatViewModel() + { + LiveChatID = r.LiveChatID, + Visitor = new LiveChatVisitorViewModel() + { + UserID = r.VisitorUserID, + Avatar = r.VisitorUserID > 0 ? DotNetNuke.Common.Globals.ResolveUrl("~/dnnimagehandler.ashx?mode=profilepic&userid=" + r.VisitorUserID) : string.Empty, + DisplayName = r.VisitorName, + Email = r.VisitorEmail, + IP = r.VisitorIP, + UserAgent = r.VisitorUserAgent + }, + Departments = LiveChatDepartmentManager.Instance.GetLiveChatDepartmentsViewModel(portalID, r.LiveChatID), + Agents = LiveChatAgentManager.Instance.GetLiveChatAgentsViewModel(portalID, r.LiveChatID), + Message = r.VisitorMessage, + CreateDate = r.CreateDate + }); + + return new PagedList(result, totalCount, pageIndex, pageSize); + } + } + + public void PurgeHistory(int[] items) + { + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + + string condition = string.Empty; + foreach (var livechatID in items) + { + condition = condition.Replace("[OR]", " or "); + condition += string.Format(" LiveChatID = {0} [OR]", livechatID); + + } + condition = condition.Replace("[OR]", string.Empty); + + rep.Delete(string.Format("Where ({0})", condition)); + + DataCache.ClearCache(CachePrefix); + } + } + } +} \ No newline at end of file diff --git a/LiveChat/Components/LiveChatMessageManager.cs b/LiveChat/Components/LiveChatMessageManager.cs new file mode 100644 index 0000000..4b93f4c --- /dev/null +++ b/LiveChat/Components/LiveChatMessageManager.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Common; +using DotNetNuke.Framework; + +namespace MyDnn.Modules.Support.LiveChat.Components +{ + /// + /// + /// + internal class LiveChatMessageManager : ServiceLocator, ILiveChatMessageManager + { + protected override Func GetFactory() + { + return () => new LiveChatMessageManager(); + } + + /// + /// + /// + private const string CachePrefix = "LiveChatMessages_"; + + /// + /// + /// + /// + /// + public int AddMessage(LiveChatMessageInfo objLiveChatMessageInfo) + { + Requires.NotNull(objLiveChatMessageInfo); + Requires.PropertyNotNegative(objLiveChatMessageInfo, "LiveChatID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objLiveChatMessageInfo); + + DataCache.ClearCache(CachePrefix); + + return objLiveChatMessageInfo.MessageID; + } + } + + /// + /// + /// + /// + public void SeenMessage(int messageID) + { + Requires.NotNegative("messageID", messageID); + + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnSupport_LiveChatSeenMessage", messageID); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + public void DeleteMessage(int liveChatID) + { + Requires.NotNegative("liveChatID", liveChatID); + + LiveChatMessageInfo objLiveChatMessageInfo = GetMessageByID(liveChatID); + Requires.NotNull(objLiveChatMessageInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objLiveChatMessageInfo); + } + + DataCache.ClearCache(CachePrefix); + } + + /// + /// + /// + /// + /// + public LiveChatMessageInfo GetMessageByID(int livechatMessageID) + { + Requires.NotNegative("livechatMessageID", livechatMessageID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.GetById(livechatMessageID); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetMessages(int livechatID) + { + Requires.NotNegative("livechatMessageID", livechatID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(livechatID); + } + } + + /// + /// + /// + /// + /// + /// + public IEnumerable GetUnreadMessages(int livechatID, int messageID) + { + Requires.NotNegative("livechatID", livechatID); + Requires.NotNegative("messageID", messageID); + + var messages = GetMessages(livechatID); + return (messages != null ? messages.Where(m => m.MessageID > messageID) : null); + } + } +} \ No newline at end of file diff --git a/LiveChat/Controllers/AdminPanelController.cs b/LiveChat/Controllers/AdminPanelController.cs new file mode 100644 index 0000000..3f58048 --- /dev/null +++ b/LiveChat/Controllers/AdminPanelController.cs @@ -0,0 +1,59 @@ +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Web.Mvc.Framework.Controllers; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; + +namespace MyDnn.Modules.Support.LiveChat.Controllers +{ + public class AdminPanelController : DnnController + { + public ActionResult AdminPanel() + { + bool mustRedirect = false; + string newUrl = string.Empty; + + if (PortalSettings.EnablePopUps) + { + if (Request.QueryString["popUp"] == null || Request.QueryString["popUp"] != "true" || Request.Url.Query.IndexOf("popUp") == -1) + { + mustRedirect = true; + newUrl = ModuleContext.EditUrl("popUp", "true", "AdminPanel", "controller", "AdminPanel", "action", "AdminPanel"); + } + } + else + { + if (Request.QueryString["SkinSrc"] == null) + { + mustRedirect = true; + newUrl = ModuleContext.EditUrl("", "", "AdminPanel", "controller", "AdminPanel", "action", "AdminPanel", "SkinSrc=[G]Skins%2f_default%2fNo+Skin&ContainerSrc=[G]Containers%2f_default%2fNo+Container"); + } + } + + var model = new ModuleConfigStatusViewModel(); + model.VisitorsOnlineEnabled = bool.Parse(PortalController.GetPortalSetting("MyDnnVisitorsOnlineEnabled", PortalSettings.PortalId, "false")); ; + model.LiveChatEnabled = bool.Parse(PortalController.GetPortalSetting("MyDnnLiveChatEnabled", PortalSettings.PortalId, "false")); ; + + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + if (moduleID != -1) + { + var objModuleInfo = new ModuleController().GetModule(moduleID); + var Settings = objModuleInfo.ModuleSettings; + + model.ModuleID = objModuleInfo.ModuleID; + model.TabID = objModuleInfo.TabID; + model.BasicSettingsUpdated = Settings["UpdateBasicSettings"] != null ? bool.Parse(Settings["UpdateBasicSettings"].ToString()) : false; + model.WidgetSettingsUpdated = Settings["UpdateWidgetSettings"] != null ? bool.Parse(Settings["UpdateWidgetSettings"].ToString()) : false; ; + } + + if (mustRedirect) + return Redirect(newUrl); + else + return View(model); + } + } +} diff --git a/LiveChat/Controllers/HomeController.cs b/LiveChat/Controllers/HomeController.cs new file mode 100644 index 0000000..bdb2ac4 --- /dev/null +++ b/LiveChat/Controllers/HomeController.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using DotNetNuke.Web.Mvc.Framework.Controllers; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security.Roles; +using MyDnn.VisitorsOnline.Api; +using MyDnn.VisitorsOnline.Models; +using DotNetNuke.Common.Utilities; + +namespace MyDnn.Modules.Support.LiveChat.Controllers +{ + public class HomeController : DnnController + { + [HttpGet] + public ActionResult Index() + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + + if (moduleID == -1) + { + moduleID = ActiveModule.ModuleID; + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "MyDnnLiveChatModuleID", moduleID.ToString(), true); + + var role = RoleController.Instance.GetRoleByName(PortalSettings.PortalId, "MyDnnSupportAgent"); + if (role == null) + { + var objRoleInfo = new RoleInfo(); + objRoleInfo.PortalID = PortalSettings.PortalId; + objRoleInfo.Description = "mydnn live chat agent"; + objRoleInfo.RoleName = "MyDnnSupportAgent"; + objRoleInfo.IsPublic = false; + objRoleInfo.Status = RoleStatus.Approved; + objRoleInfo.RoleGroupID = Null.NullInteger; + RoleController.Instance.AddRole(objRoleInfo); + + var listeners = VisitorsOnlineApi.Instance.GetListeners(PortalSettings.PortalId); + if (listeners == null || !listeners.Any(l => l.RoleName == "MyDnnSupportAgent" && l.LoginState == VisitorsOnline.Components.Enums.LoginState.LoggedIn)) + { + VisitorsOnlineApi.Instance.AddListener(new ListenerInfo() + { + PortalID = PortalSettings.PortalId, + RoleName = "MyDnnSupportAgent", + LoginState = VisitorsOnline.Components.Enums.LoginState.LoggedIn, + InvokeScript = "$('#mydnnLiveChatMinButton').find('[data-livechat-isonline]').hide();$('#mydnnLiveChatMinButton').find('[data-livechat-isonline=\"online\"]').show();", + CreatedByModuleName = "MyDnnSupportLiveChat", + CreatedOnDate = DateTime.Now + }); + } + if (listeners == null || !listeners.Any(l => l.RoleName == "MyDnnSupportAgent" && l.LoginState == VisitorsOnline.Components.Enums.LoginState.LoggedOff)) + { + VisitorsOnlineApi.Instance.AddListener(new ListenerInfo() + { + PortalID = PortalSettings.PortalId, + RoleName = "MyDnnSupportAgent", + LoginState = VisitorsOnline.Components.Enums.LoginState.LoggedOff, + InvokeScript = "$('#mydnnLiveChatMinButton').find('[data-livechat-isonline]').hide();$('#mydnnLiveChatMinButton').find('[data-livechat-isonline=\"offline\"]').show();", + CreatedByModuleName = "MyDnnSupportLiveChat", + CreatedOnDate = DateTime.Now + }); + } + } + } + + return View(); + } + } +} diff --git a/LiveChat/Hubs/LiveChatHub.cs b/LiveChat/Hubs/LiveChatHub.cs new file mode 100644 index 0000000..b634ecd --- /dev/null +++ b/LiveChat/Hubs/LiveChatHub.cs @@ -0,0 +1,727 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Threading.Tasks; +using DotNetNuke.Entities.Portals; +using System.Threading; +using MyDnn.VisitorsOnline; +using System.Collections; +using System.Xml; +using System.IO; +using Microsoft.AspNet.SignalR; +using Microsoft.AspNet.SignalR.Hubs; +using MyDnn.VisitorsOnline.Api; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChat.Components.Enums; +using MyDnn.Modules.Support.LiveChat.Components; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using MyDnn.VisitorsOnline.Hubs; +using DotNetNuke.Common; +using DotNetNuke.Entities.Modules; + +namespace MyDnn.Modules.Support.LiveChat.Hubs +{ + /// + /// + /// + [HubName("MyDnnSupportLiveChatHub")] + public class LiveChatHub : Hub + { + #region Variable && Properties + + /// + /// + /// + private string UserName + { + get + { + if (Context.User.Identity.IsAuthenticated) + { + return Context.User.Identity.Name; + } + else + return string.Empty; + } + } + + /// + /// + /// + private static Timer LiveChatRequestTimer { get; set; } + + /// + /// + /// + private const string DepartmentAgentsGroupName = "LiveChat-Agents-Department-"; + + /// + /// + /// + private const string AgentGroupName = "LiveChat-Agent-"; + + /// + /// + /// + private const string AllAgentsGroupName = "LiveChat-AllAgents"; + + #endregion + + #region Override Methods + + /// + /// + /// + /// + public override Task OnConnected() + { + return base.OnConnected(); + } + + /// + /// + /// + /// + public override Task OnReconnected() + { + return base.OnReconnected(); + } + + /// + /// + /// + /// + /// + public override Task OnDisconnected(bool stopCalled) + { + return base.OnDisconnected(stopCalled); + } + + #endregion + + #region Hub Methods + + /// + /// + /// + /// + /// + /// + /// + public object JoinAgent(int portalID, bool loadIncommingLiveChats, bool loadLiveChats) + { + var agent = AgentManager.Instance.GetAgentByUserName(portalID, UserName); + if (agent == null) return null; + + var context = GlobalHost.ConnectionManager.GetHubContext(); + + Groups.Add(Context.ConnectionId, AllAgentsGroupName); + Groups.Add(Context.ConnectionId, AgentGroupName + agent.UserID); + + var agentDepartments = DepartmentAgentManager.Instance.GetAgentDepartments(agent.AgentID); + foreach (var department in agentDepartments) + { + Groups.Add(Context.ConnectionId, DepartmentAgentsGroupName + department.DepartmentID); + + //in bakhsh enghad pichidas ke hata nemitonam tozih bedam !! + context.Groups.Add(Context.ConnectionId, "MyDnnLiveChatAgents-" + department.DepartmentID); + } + + //hazf tamame darkhast haye chati ke visitorash rafte peye karash + LiveChatManager.Instance.CloseLeftLiveChats(portalID); + + List livechats = null; + IEnumerable incomingLiveChats = null; + + if (loadIncommingLiveChats) + { + incomingLiveChats = LiveChatManager.Instance.GetIncomingLiveChats(portalID); + } + + if (loadLiveChats) + { + livechats = new List(); + + var currentLiveChats = LiveChatManager.Instance.GetCurrentLiveChatsByAgent(portalID, agent.UserID); + foreach (LiveChatInfo objLiveChatInfo in currentLiveChats) + { + var livechat = GetLiveChatViewModel(objLiveChatInfo); + livechat.ChatStarted = true; + livechats.Add(livechat); + } + } + + return new { IncomingLiveChats = incomingLiveChats.Select(i => new { LiveChatID = i.LiveChatID, VisitorGUID = i.VisitorGUID }), LiveChats = livechats, Me = agent }; + } + + /// + /// + /// + /// + /// + /// + public object JoinVisitor(int portalID, string visitorGUID) + { + Groups.Add(Context.ConnectionId, portalID + "-" + visitorGUID); + + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", portalID, "-1")); + Requires.NotNegative("moduleID", moduleID); + var Settings = new ModuleController().GetModule(moduleID).ModuleSettings; + + var currentLiveChat = LiveChatManager.Instance.GetCurrentLiveChatByVisitor(portalID, visitorGUID); + + LiveChatViewModel livechat = null; + + if (currentLiveChat != null) + { + if (currentLiveChat.LastMessageDate != null && (DateTime.Now - currentLiveChat.LastMessageDate).TotalHours < 10) // in ghesmat baraye in ast ke agar az akharin post visitor bish az 10 saat gozashte bashad live chat ra neshan nadahad + { + livechat = GetLiveChatViewModel(currentLiveChat); + } + else + LiveChatManager.Instance.CloseLiveChat(currentLiveChat.LiveChatID, false); + } + + return livechat; + } + + /// + /// + /// + /// + /// + public int StartLiveChatByVisitor(LiveChatViewModel livechat) + { + if (LiveChatManager.Instance.hasVisitorOpenedLiveChat(livechat.PortalID, livechat.Visitor.VisitorGUID)) + return 0; + + var visitor = VisitorsOnlineApi.Instance.GetVisitorByGUID(livechat.PortalID, livechat.Visitor.VisitorGUID); + + var objLiveChatInfo = new LiveChatInfo() + { + PortalID = livechat.PortalID, + VisitorGUID = livechat.Visitor.VisitorGUID, + VisitorName = livechat.Visitor.DisplayName, + VisitorEmail = livechat.Visitor.Email, + VisitorUserID = visitor.UserID, + VisitorIP = visitor.IP, + VisitorUserAgent = visitor.UserAgent, + VisitorMessage = livechat.Message, + CreateDate = DateTime.Now, + CloseDate = DateTime.MaxValue, + IsClosed = false, + }; + int livechatID = LiveChatManager.Instance.AddLiveChat(objLiveChatInfo); + LiveChatDepartmentManager.Instance.AddLiveChatDepartment(new LiveChatDepartmentInfo() + { + LiveChatID = livechatID, + DepartmentID = livechat.Departments.First().DepartmentID, + CreateDate = DateTime.Now + }); + + //create messages + var objLiveChatMessageInfo = new LiveChatMessageInfo() + { + LiveChatID = livechatID, + SentBy = MessageSentBy.System, + CreateDate = DateTime.Now, + MessageType = MessageType.Text, + Message = "Chat started", + }; + LiveChatMessageManager.Instance.AddMessage(objLiveChatMessageInfo); + + if (!string.IsNullOrEmpty(livechat.Message)) + { + objLiveChatMessageInfo = new LiveChatMessageInfo() + { + LiveChatID = livechatID, + SentBy = MessageSentBy.Visitor, + CreateDate = DateTime.Now, + MessageType = MessageType.Text, + Message = livechat.Message + }; + LiveChatMessageManager.Instance.AddMessage(objLiveChatMessageInfo); + } + + livechat = GetLiveChatViewModel(objLiveChatInfo); + + //ersale live chat kamel shode be khode visitor(darkhast konande chat) + Clients.Group(livechat.PortalID + "-" + visitor.VisitorGUID).startLiveChat(livechat); + //send live chat request to agents + var department = livechat.Departments.First(); + Clients.Group(DepartmentAgentsGroupName + department.DepartmentID).incomingLiveChat(livechatID, visitor.VisitorGUID, livechat.Message, "add"); + + var context = GlobalHost.ConnectionManager.GetHubContext(); + context.Clients.Group("MyDnnLiveChatAgents-" + department.DepartmentID).invokeScript(string.Format("mydnnLiveChatRequests({0},'add');", livechatID)); + + //update visitor info in visitor list + visitor.DisplayName = livechat.Visitor.DisplayName; + visitor.Email = livechat.Visitor.Email; + + //eslah shavad + ///VisitorsOnlineApi.Instance.UpdateVisitorOnline(livechat.PortalID, visitor.VisitorGUID, visitor.UserName, visitor.DisplayName, visitor.Email, visitor.LastURL, Context.ConnectionId, true); + //var context = GlobalHost.ConnectionManager.GetHubContext(); + ///context.Clients.Group("MyDnnVisitorsOnline").updateVisitorInfo(visitor); + + return livechatID; + } + + /// + /// + /// + /// + /// + /// + public async Task InitialLiveChatForAgent(int livechatID, bool reInitialize = false) + { + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + + if (objLiveChatInfo != null) + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", objLiveChatInfo.PortalID, "-1")); + Requires.NotNegative("moduleID", moduleID); + var Settings = new ModuleController().GetModule(moduleID).ModuleSettings; + + var agent = AgentManager.Instance.GetAgentByUserName(objLiveChatInfo.PortalID, this.UserName); + bool isAdmin = agent.IsAdmin; + + var livechat = GetLiveChatViewModel(objLiveChatInfo); + + //if (reInitialize) + //agentUserID = agent.UserID; + + if (!livechat.Agents.Any() || Settings["AgentsViewPermission"].ToString() == LiveChatViewPermission.AllAgentsInDepartment.ToString() || + (Settings["AgentsViewPermission"].ToString() == LiveChatViewPermission.OnlyCurrentAgentsAndAdmin.ToString() && isAdmin)) + { + await Clients.Group(AgentGroupName + agent.UserID).initialLiveChatForAgent(livechat); + } + } + } + + /// + /// + /// + /// + public void StartLiveChatByAgent(int livechatID) + { + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + if (objLiveChatInfo != null) + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", objLiveChatInfo.PortalID, "-1")); + Requires.NotNegative("moduleID", moduleID); + var Settings = new ModuleController().GetModule(moduleID).ModuleSettings; + + var livechat = GetLiveChatViewModel(objLiveChatInfo); + + var meAsAgent = AgentManager.Instance.GetAgentByUserName(objLiveChatInfo.PortalID, this.UserName); + + Clients.Group(DepartmentAgentsGroupName + livechat.Departments.First().DepartmentID).incomingLiveChat(objLiveChatInfo.LiveChatID, null, null, "remove"); + + if (!livechat.Agents.Any()) + { + //in ghesmat baraye in ast ke pas az shoro goftego tavasote karshenas livechat az tamame karshenas hai ke permission didan goftefo ra nadaran hazf shavad + if (Settings["AgentsViewPermission"].ToString() != LiveChatViewPermission.AllAgentsInDepartment.ToString()) + { + foreach (var agent in DepartmentAgentManager.Instance.GetDepartmentAgents(livechat.Departments.First().DepartmentID)) + { + if (meAsAgent.UserID == agent.UserID) continue; + + var objAgentView = AgentManager.Instance.GetAgentByUserID(objLiveChatInfo.PortalID, agent.UserID); + bool isAdmin = objAgentView.IsAdmin; + + if (Settings["AgentsViewPermission"].ToString() == LiveChatViewPermission.OnlyCurrentAgents.ToString() || + (Settings["AgentsViewPermission"].ToString() == LiveChatViewPermission.OnlyCurrentAgentsAndAdmin.ToString() && !isAdmin)) + { + Clients.Group(AgentGroupName + agent.UserID).removeLiveChat(objLiveChatInfo.LiveChatID); + } + } + } + } + + AgentHasJoin(objLiveChatInfo, meAsAgent, true, true); + + Clients.Group(AllAgentsGroupName).visitorIsChatting(objLiveChatInfo.VisitorGUID); + } + } + + /// + /// + /// + /// + /// + /// + /// + public int SendMessage(int portalID, LiveChatMessageInfo message, bool reOpen = false) + { + try + { + if (message.SentBy == MessageSentBy.System || message.SentBy == MessageSentBy.Visitor) + message.AgentUserID = -1; + else + { + message.AgentUserID = AgentManager.Instance.GetAgentByUserName(portalID, UserName).UserID; + } + + message.CreateDate = DateTime.Now; + message.MessageID = LiveChatMessageManager.Instance.AddMessage(message); + + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(message.LiveChatID); + + //ersal payam be visitor be joz tab jari + Clients.Group(portalID + "-" + objLiveChatInfo.VisitorGUID, Context.ConnectionId).reciveMessage(message); + + //ersal payam be agent ha + var agents = LiveChatAgentManager.Instance.GetLiveChatAgents(objLiveChatInfo.LiveChatID); + if (!agents.Any(a => a.hasLeft == false)) // agar hich agenti join nashode bayad payam roye tamame agenthaye department ersal shavad + { + var departments = LiveChatDepartmentManager.Instance.GetLiveChatDepartments(objLiveChatInfo.LiveChatID); + Clients.Group(DepartmentAgentsGroupName + departments.First().DepartmentID).reciveMessage(message); + } + else + { + foreach (var agent in agents) + { + Clients.Group(AgentGroupName + agent.UserID, Context.ConnectionId).reciveMessage(message); + } + } + + if (objLiveChatInfo.IsClosed) + { + //re open live chat -- next version :) + } + + return message.MessageID; + } + catch + { + return -1; + } + } + + public void VisitorIsTyping(int portalID, int livechatID) + { + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + + var agents = LiveChatAgentManager.Instance.GetLiveChatAgents(objLiveChatInfo.LiveChatID); + if (!agents.Any(a => a.hasLeft == false)) // agar hich agenti join nashode bayad payam roye tamame agenthaye department ersal shavad + { + var departments = LiveChatDepartmentManager.Instance.GetLiveChatDepartments(objLiveChatInfo.LiveChatID); + Clients.Group(DepartmentAgentsGroupName + departments.First().DepartmentID).visitorIsTyping(); + } + else + { + foreach (var agent in agents) + { + Clients.Group(AgentGroupName + agent.UserID).visitorIsTyping(); + } + } + } + + /// + /// + /// + /// + /// + public void SeenMessage(int portalID, LiveChatMessageInfo message) + { + LiveChatMessageManager.Instance.SeenMessage(message.MessageID); + + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(message.LiveChatID); + Clients.Group(portalID + "-" + objLiveChatInfo.VisitorGUID).seenMessage(message.MessageID); + } + + /// + /// + /// + /// + /// + /// + public bool RateChat(int liveChatID, LiveChatRating rate) + { + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(liveChatID); + + objLiveChatInfo.Rate = rate; + LiveChatManager.Instance.UpdateLiveChat(objLiveChatInfo); + + return true; + } + + /// + /// + /// + /// + public void VisitorHasLeftChat(int livechatID) + { + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + LiveChatManager.Instance.CloseLiveChat(objLiveChatInfo.LiveChatID, false); + + var objLiveChatMessageInfo = new LiveChatMessageInfo() + { + LiveChatID = objLiveChatInfo.LiveChatID, + CreateDate = DateTime.Now, + SentBy = MessageSentBy.System, + MessageType = MessageType.Text, + Message = "Visitor has left chat", + }; + int messageID = LiveChatMessageManager.Instance.AddMessage(objLiveChatMessageInfo); + objLiveChatMessageInfo.MessageID = messageID; + + //ersal payam be agent ha + var agents = LiveChatAgentManager.Instance.GetLiveChatAgents(objLiveChatInfo.LiveChatID); + if (!agents.Any(a => a.hasLeft == false)) // agar hich agenti join nashode bayad payam roye tamame agenthaye department ersal shavad + { + var departments = LiveChatDepartmentManager.Instance.GetLiveChatDepartments(objLiveChatInfo.LiveChatID); + Clients.Group(DepartmentAgentsGroupName + departments.First().DepartmentID).reciveMessage(objLiveChatMessageInfo); + } + else + { + foreach (var agent in agents) + { + Clients.Group(AgentGroupName + agent.UserID).reciveMessage(objLiveChatMessageInfo); + } + } + } + + /// + /// + /// + /// + /// + /// + /// + /// + public object VisitorReconnectedToLiveChat(int portalID, int livechatID, int agentUserID, int lastMessageID) + { + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + if (objLiveChatInfo != null) + { + var messages = LiveChatMessageManager.Instance.GetUnreadMessages(objLiveChatInfo.LiveChatID, lastMessageID); //daryaft payamhai ke visitor baad az ghat shodane internetash nadide ast + + //if (objLiveChatInfo.AgentUserID != agentUserID) // in yani visitor be karshenasi vasl nabode va zamani ke internetesh ghat mishavad yek karshenas be darkhastash pasokh mosbat midahad + //{ + // AgentHasJoin(objLiveChatInfo, null, true, false); + //} + + return new { IsClosed = objLiveChatInfo.IsClosed, Messages = messages }; + } + return null; + } + + /// + /// + /// + /// + /// + /// + public bool CloseLiveChatByVisitor(int portalID, int livechatID) + { + var isClosed = false; + + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + if (objLiveChatInfo != null && !objLiveChatInfo.IsClosed) + { + LiveChatManager.Instance.CloseLiveChat(livechatID, false); + + var objLiveChatMessageInfo = new LiveChatMessageInfo() + { + LiveChatID = objLiveChatInfo.LiveChatID, + CreateDate = DateTime.Now, + SentBy = MessageSentBy.System, + MessageType = MessageType.Text, + Message = "Visitor closed the live chat", + }; + int messageID = LiveChatMessageManager.Instance.AddMessage(objLiveChatMessageInfo); + objLiveChatMessageInfo.MessageID = messageID; + + Clients.Group(portalID + "-" + objLiveChatInfo.VisitorGUID).closeLiveChatByVisitor(objLiveChatInfo.LiveChatID); + Clients.Group(portalID + "-" + objLiveChatInfo.VisitorGUID).reciveMessage(objLiveChatMessageInfo); + + //ersal payam be agent ha + var agents = LiveChatAgentManager.Instance.GetLiveChatAgents(objLiveChatInfo.LiveChatID); + if (!agents.Any(a => a.hasLeft == false)) // agar hich agenti join nashode bayad payam roye tamame agenthaye department ersal shavad + { + var departments = LiveChatDepartmentManager.Instance.GetLiveChatDepartments(objLiveChatInfo.LiveChatID); + Clients.Group(DepartmentAgentsGroupName + departments.First().DepartmentID).reciveMessage(objLiveChatMessageInfo); + Clients.Group(DepartmentAgentsGroupName + departments.First().DepartmentID).closeLiveChatByVisitor(objLiveChatInfo.LiveChatID); + } + else + { + foreach (var agent in agents) + { + Clients.Group(AgentGroupName + agent.UserID).reciveMessage(objLiveChatMessageInfo); + Clients.Group(AgentGroupName + agent.UserID).closeLiveChatByVisitor(objLiveChatInfo.LiveChatID); + } + } + + isClosed = true; + } + return isClosed; + } + + /// + /// + /// + /// + /// + /// + public bool CloseLiveChatByAgent(int portalID, int livechatID) + { + var isClosed = false; + + var objLiveChatInfo = LiveChatManager.Instance.GetLiveChatByID(livechatID); + if (objLiveChatInfo != null && !objLiveChatInfo.IsClosed) + { + LiveChatManager.Instance.CloseLiveChat(livechatID, true); + + var objLiveChatMessageInfo = new LiveChatMessageInfo() + { + LiveChatID = objLiveChatInfo.LiveChatID, + CreateDate = DateTime.Now, + SentBy = MessageSentBy.System, + MessageType = MessageType.Text, + Message = "Agent closed the live chat", + }; + int messageID = LiveChatMessageManager.Instance.AddMessage(objLiveChatMessageInfo); + objLiveChatMessageInfo.MessageID = messageID; + + Clients.Group(portalID + "-" + objLiveChatInfo.VisitorGUID).closeLiveChatByAgent(objLiveChatInfo.LiveChatID); + Clients.Group(portalID + "-" + objLiveChatInfo.VisitorGUID).reciveMessage(objLiveChatMessageInfo); + + //ersal payam be agent ha + var agents = LiveChatAgentManager.Instance.GetLiveChatAgents(objLiveChatInfo.LiveChatID); + foreach (var agent in agents) + { + Clients.Group(AgentGroupName + agent.UserID, Context.ConnectionId).reciveMessage(objLiveChatMessageInfo); + Clients.Group(AgentGroupName + agent.UserID, Context.ConnectionId).closeLiveChatByAgent(objLiveChatInfo.LiveChatID); + } + + isClosed = true; + } + return isClosed; + } + + /// + /// + /// + /// + /// + /// + public void AgentReconnectedToLiveChat(int portalID, int livechatID, DateTime lastMessageDate) + { + // -- next version :) + } + + #endregion + + #region Private Methods + + /// + /// + /// + /// + /// + private LiveChatViewModel GetLiveChatViewModel(LiveChatInfo objLiveChatInfo) + { + var livechat = new LiveChatViewModel(); + livechat.LiveChatID = objLiveChatInfo.LiveChatID; + livechat.PortalID = objLiveChatInfo.PortalID; + + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", objLiveChatInfo.PortalID, "-1")); + Requires.NotNegative("moduleID", moduleID); + var Settings = new ModuleController().GetModule(moduleID).ModuleSettings; + + //Visitor + livechat.Visitor = new LiveChatVisitorViewModel() + { + UserID = objLiveChatInfo.VisitorUserID, + VisitorGUID = objLiveChatInfo.VisitorGUID, + DisplayName = objLiveChatInfo.VisitorName, + Email = objLiveChatInfo.VisitorEmail, + IP = objLiveChatInfo.VisitorIP, + UserAgent = objLiveChatInfo.VisitorUserAgent, + Avatar = (Settings["VisitorDefaultAvatar"] != null ? Settings["VisitorDefaultAvatar"].ToString() : string.Empty) + }; + var visitor = VisitorsOnlineApi.Instance.GetVisitorByGUID(objLiveChatInfo.PortalID, objLiveChatInfo.VisitorGUID); + if (visitor != null) + { + if (visitor.UserID > 0) livechat.Visitor.Avatar = DotNetNuke.Common.Globals.ResolveUrl("~/dnnimagehandler.ashx?mode=profilepic&userid=" + visitor.UserID); + livechat.Visitor.LastURL = visitor.LastURL; + livechat.Visitor.ReferrerURL = visitor.ReferrerURL; + livechat.Visitor.PastVisits = visitor.TotalConnections; + livechat.Visitor.OnlineDate = visitor.OnlineDate; + } + + //Departments + livechat.Departments = LiveChatDepartmentManager.Instance.GetLiveChatDepartmentsViewModel(objLiveChatInfo.PortalID, objLiveChatInfo.LiveChatID); + + //Agents + livechat.Agents = LiveChatAgentManager.Instance.GetLiveChatAgentsViewModel(objLiveChatInfo.PortalID, objLiveChatInfo.LiveChatID); + livechat.AgentDefaultAvatar = (Settings["AgentDefaultAvatar"] != null ? Settings["AgentDefaultAvatar"].ToString() : string.Empty); + + //Messages + var messages = LiveChatMessageManager.Instance.GetMessages(objLiveChatInfo.LiveChatID); + livechat.Messages = messages; + + livechat.Rate = objLiveChatInfo.Rate; + + livechat.IsClosed = objLiveChatInfo.IsClosed; + + return livechat; + } + + /// + /// + /// + /// + /// + /// + /// + private void AgentHasJoin(LiveChatInfo objLiveChatInfo, AgentView objAgentView, bool sendToVisitor, bool sendToAgent) + { + var agent = new LiveChatAgentViewModel() + { + AgentID = objAgentView.AgentID, + UserID = objAgentView.UserID, + DisplayName = objAgentView.DisplayName, + Email = objAgentView.Email, + Avatar = DotNetNuke.Common.Globals.ResolveUrl("~/dnnimagehandler.ashx?mode=profilepic&userid=" + objAgentView.UserID), + IsOnline = VisitorsOnlineApi.Instance.IsVisitorOnline(objLiveChatInfo.PortalID, objAgentView.UserID), + JoinDate = DateTime.Now + }; + + LiveChatAgentManager.Instance.AddLiveChatAgent(new LiveChatAgentInfo() { AgentID = agent.AgentID, UserID = agent.UserID, LiveChatID = objLiveChatInfo.LiveChatID, JoinDate = DateTime.Now }); + + var objLiveChatMessageInfo = new LiveChatMessageInfo() + { + LiveChatID = objLiveChatInfo.LiveChatID, + SentBy = MessageSentBy.System, + CreateDate = DateTime.Now, + MessageType = MessageType.Text, + Message = objAgentView.DisplayName + " join chat" + }; + int messageID = LiveChatMessageManager.Instance.AddMessage(objLiveChatMessageInfo); + objLiveChatMessageInfo.MessageID = messageID; + + if (sendToVisitor) + { + Clients.Group(objLiveChatInfo.PortalID + "-" + objLiveChatInfo.VisitorGUID).agentHasJoin(objLiveChatInfo.LiveChatID, agent); + Clients.Group(objLiveChatInfo.PortalID + "-" + objLiveChatInfo.VisitorGUID).reciveMessage(objLiveChatMessageInfo); + } + + if (sendToAgent) + { + foreach (var item in LiveChatAgentManager.Instance.GetLiveChatAgents(objLiveChatInfo.LiveChatID)) + { + Clients.Group(AgentGroupName + item.UserID).agentHasJoin(objLiveChatInfo.LiveChatID, agent); + Clients.Group(AgentGroupName + item.UserID).reciveMessage(objLiveChatMessageInfo); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/LiveChat/Models/AgentInfo.cs b/LiveChat/Models/AgentInfo.cs new file mode 100644 index 0000000..603c801 --- /dev/null +++ b/LiveChat/Models/AgentInfo.cs @@ -0,0 +1,62 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + /// + /// + /// + [TableName("MyDnnSupport_Agents")] + [PrimaryKey("AgentID", AutoIncrement = true)] + [Cacheable("Agents_", CacheItemPriority.Default, 20)] + [Scope("PortalID")] + public class AgentInfo + { + /// + /// + /// + public int AgentID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public int UserID { get; set; } + + /// + /// + /// + public bool Enabled { get; set; } + + /// + /// + /// + public int Priority { get; set; } + + /// + /// + /// + public bool IsAdmin { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + + /// + /// + /// + public int CreateByUser { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/AgentView.cs b/LiveChat/Models/AgentView.cs new file mode 100644 index 0000000..cea7150 --- /dev/null +++ b/LiveChat/Models/AgentView.cs @@ -0,0 +1,76 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + /// + /// + /// + [TableName("vw_MyDnnSupport_Agents")] + [PrimaryKey("AgentID", AutoIncrement = false)] + [Scope("PortalID")] + public class AgentView + { + /// + /// + /// + public int AgentID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public int UserID { get; set; } + + /// + /// + /// + public string UserName { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + + /// + /// + /// + public int CreateByUser { get; set; } + + /// + /// + /// + public bool Enabled { get; set; } + + /// + /// + /// + public int Priority { get; set; } + + /// + /// + /// + public bool IsAdmin { get; set; } + + /// + /// + /// + public string DisplayName { get; set; } + + /// + /// + /// + public string Email { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/DeparmentInfo.cs b/LiveChat/Models/DeparmentInfo.cs new file mode 100644 index 0000000..51cdafd --- /dev/null +++ b/LiveChat/Models/DeparmentInfo.cs @@ -0,0 +1,62 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + /// + /// + /// + [TableName("MyDnnSupport_Departments")] + [PrimaryKey("DepartmentID", AutoIncrement = true)] + [Cacheable("Departments_", CacheItemPriority.Default, 20)] + [Scope("PortalID")] + public class DepartmentInfo + { + /// + /// + /// + public int DepartmentID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public string DepartmentName { get; set; } + + /// + /// + /// + public string Description { get; set; } + + /// + /// + /// + public bool TicketEnabled { get; set; } + + /// + /// + /// + public bool LiveChatEnabled { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + + /// + /// + /// + public int CreateByUser { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/DepartmentAgentInfo.cs b/LiveChat/Models/DepartmentAgentInfo.cs new file mode 100644 index 0000000..e9e081d --- /dev/null +++ b/LiveChat/Models/DepartmentAgentInfo.cs @@ -0,0 +1,42 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + /// + /// + /// + [TableName("MyDnnSupport_DepartmentAgents")] + [PrimaryKey("DepartmentAgentID", AutoIncrement = true)] + [Cacheable("DepartmentAgents_", CacheItemPriority.Default, 20)] + [Scope("DepartmentID")] + public class DepartmentAgentInfo + { + /// + /// + /// + public int DepartmentAgentID { get; set; } + + /// + /// + /// + public int DepartmentID { get; set; } + + /// + /// + /// + public int AgentID { get; set; } + + /// + /// + /// + public int UserID { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/LiveChatAgentInfo.cs b/LiveChat/Models/LiveChatAgentInfo.cs new file mode 100644 index 0000000..8e145d9 --- /dev/null +++ b/LiveChat/Models/LiveChatAgentInfo.cs @@ -0,0 +1,54 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + [TableName("MyDnnSupport_LiveChatAgents")] + [PrimaryKey("LiveChatAgentID", AutoIncrement = true)] + [Cacheable("LiveChatAgents_", CacheItemPriority.Normal, 20)] + [Scope("LiveChatID")] + public class LiveChatAgentInfo + { + /// + /// + /// + public int LiveChatAgentID { get; set; } + + /// + /// + /// + public int LiveChatID { get; set; } + + /// + /// + /// + public int AgentID { get; set; } + + /// + /// + /// + public int UserID { get; set; } + + /// + /// + /// + public DateTime JoinDate { get; set; } + + /// + /// + /// + public bool hasLeft { get; set; } + + /// + /// + /// + public DateTime LeftDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/LiveChatDepartmentInfo.cs b/LiveChat/Models/LiveChatDepartmentInfo.cs new file mode 100644 index 0000000..6d42466 --- /dev/null +++ b/LiveChat/Models/LiveChatDepartmentInfo.cs @@ -0,0 +1,39 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + [TableName("MyDnnSupport_LiveChatDepartments")] + [PrimaryKey("LiveChatDepartmentID", AutoIncrement = true)] + [Cacheable("LiveChatDepartments_", CacheItemPriority.Normal, 20)] + [Scope("LiveChatID")] + public class LiveChatDepartmentInfo + { + /// + /// + /// + public int LiveChatDepartmentID { get; set; } + + /// + /// + /// + public int LiveChatID { get; set; } + + /// + /// + /// + public int DepartmentID { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/LiveChatInfo.cs b/LiveChat/Models/LiveChatInfo.cs new file mode 100644 index 0000000..951b4dd --- /dev/null +++ b/LiveChat/Models/LiveChatInfo.cs @@ -0,0 +1,100 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; +using MyDnn.Modules.Support.LiveChat.Components.Enums; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + [TableName("MyDnnSupport_LiveChats")] + [PrimaryKey("LiveChatID", AutoIncrement = true)] + [Cacheable("LiveChats_", CacheItemPriority.Normal, 20)] + [Scope("PortalID")] + public class LiveChatInfo + { + /// + /// + /// + public int LiveChatID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public string VisitorGUID { get; set; } + + /// + /// + /// + public string VisitorName { get; set; } + + /// + /// + /// + public string VisitorEmail { get; set; } + + /// + /// + /// + public string VisitorMessage { get; set; } + + /// + /// + /// + public int VisitorUserID { get; set; } + + /// + /// + /// + public string VisitorIP { get; set; } + + /// + /// + /// + public string VisitorUserAgent { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + + /// + /// + /// + public bool IsClosed { get; set; } + + /// + /// + /// + public DateTime CloseDate { get; set; } + + /// + /// + /// + public int ClosedBy { get; set; } + + /// + /// + /// + public LiveChatRating Rate { get; set; } + + /// + /// + /// + public string VisitorComment { get; set; } + + /// + /// + /// + public DateTime LastMessageDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/LiveChatMessageInfo.cs b/LiveChat/Models/LiveChatMessageInfo.cs new file mode 100644 index 0000000..5c6812b --- /dev/null +++ b/LiveChat/Models/LiveChatMessageInfo.cs @@ -0,0 +1,60 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using MyDnn.Modules.Support.LiveChat.Components.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + [TableName("MyDnnSupport_LiveChatMessages")] + [PrimaryKey("MessageID", AutoIncrement = true)] + [Cacheable("LiveChatMessages_", CacheItemPriority.Normal, 20)] + [Scope("LiveChatID")] + public class LiveChatMessageInfo + { + /// + /// + /// + public int MessageID { get; set; } + + /// + /// + /// + public int LiveChatID { get; set; } + + /// + /// + /// + public MessageSentBy SentBy { get; set; } + + /// + /// + /// + public int AgentUserID { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + + /// + /// + /// + public MessageType MessageType { get; set; } + + /// + /// + /// + public string Message { get; set; } + + /// + /// + /// + public bool Seen { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Models/UserView.cs b/LiveChat/Models/UserView.cs new file mode 100644 index 0000000..c991f33 --- /dev/null +++ b/LiveChat/Models/UserView.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.Models +{ + public class UserView + { + public int UserID { get; set; } + public string DisplayName { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/MyDnn.Modules.Support.LiveChat.csproj b/LiveChat/MyDnn.Modules.Support.LiveChat.csproj new file mode 100644 index 0000000..c27d008 --- /dev/null +++ b/LiveChat/MyDnn.Modules.Support.LiveChat.csproj @@ -0,0 +1,593 @@ + + + + + Debug + AnyCPU + + + 2.0 + {0341E00F-4C86-40DD-9434-9C5FCD8A7801} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + MyDnn.Modules.Support.LiveChat + MyDnn.Modules.Support.LiveChat + v4.5 + false + true + + enabled + enabled + false + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\ + TRACE + prompt + 4 + false + + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\ClientDependency.Core.dll + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\DotNetNuke.dll + + + False + ..\..\..\..\bin\DotNetNuke.Instrumentation.dll + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\DotNetNuke.Web.dll + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\DotNetNuke.Web.Client.dll + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\DotNetNuke.Web.Mvc.dll + + + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\DotNetNuke.Web.Razor.dll + + + False + ..\..\..\..\bin\Microsoft.AspNet.SignalR.Core.dll + + + False + ..\..\..\..\bin\Microsoft.AspNet.SignalR.SystemWeb.dll + + + + False + ..\..\..\..\bin\Microsoft.Owin.dll + + + False + ..\..\..\..\bin\Microsoft.Owin.Host.SystemWeb.dll + + + False + ..\..\..\..\bin\Microsoft.Owin.Security.dll + + + ..\..\..\Beta\Test1\bin\Newtonsoft.Json.dll + + + False + ..\..\..\..\bin\Owin.dll + + + + + + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\System.Net.Http.Formatting.dll + + + + + + + + False + ..\..\..\..\..\..\8.0.0\Beta\Test1\bin\System.Web.Http.dll + + + False + ..\..\..\..\bin\System.Web.Mvc.dll + + + C:\Users\mydnn\Desktop\System.Web.Optimization.dll + + + True + ..\packages\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll + + + + + + + + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + True + ..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll + + + True + ..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.20710.0\lib\net40\System.Web.Http.WebHost.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {aa9fe893-27c4-494a-9287-fe235acb9ebf} + MyDnn.VisitorsOnline + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + + + + True + True + 8712 + / + http://localhost:11002/ + False + False + + + False + + + + + + IF NOT ($(ConfigurationName)) == (Debug) GOTO END +cd $(ProjectDir) +copy /y obj\debug\MyDnn.Modules.Support.LiveChat.dll F:\MyDnnPackage\dnn8contest\Website\bin +:END + + + \ No newline at end of file diff --git a/LiveChat/MyDnn.Modules.Support.LiveChat.csproj.user b/LiveChat/MyDnn.Modules.Support.LiveChat.csproj.user new file mode 100644 index 0000000..cee1650 --- /dev/null +++ b/LiveChat/MyDnn.Modules.Support.LiveChat.csproj.user @@ -0,0 +1,31 @@ + + + + ProjectFiles + + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + False + True + + + + + \ No newline at end of file diff --git a/LiveChat/Properties/AssemblyInfo.cs b/LiveChat/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9489c61 --- /dev/null +++ b/LiveChat/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MvcAngular.Web")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MvcAngular.Web")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3cb0454d-44f0-46a0-a927-99c824954ffe")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/LiveChat/Scripts/functions.js b/LiveChat/Scripts/functions.js new file mode 100644 index 0000000..9f21e4f --- /dev/null +++ b/LiveChat/Scripts/functions.js @@ -0,0 +1,473 @@ + +/* +* Layout +*/ + +(function () { + $(document).ready(function () { + //Get saved layout type from LocalStorage + var layoutStatus = localStorage.getItem('ma-layout-status'); + if (layoutStatus == null || layoutStatus == undefined || layoutStatus == 1) { + $('.body').addClass('sw-toggled'); + $('#tw-switch').prop('checked', true); + } + + $('body').on('change', '#toggle-width input:checkbox', function () { + if ($(this).is(':checked')) { + setTimeout(function () { + $('.body').addClass('toggled sw-toggled'); + localStorage.setItem('ma-layout-status', 1); + }, 250); + } + else { + setTimeout(function () { + $('.body').removeClass('toggled sw-toggled'); + localStorage.setItem('ma-layout-status', 0); + $('.main-menu > li').removeClass('animated'); + }, 250); + } + }); + }); +})(); + + +/* + * Detact Mobile Browser + */ +if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { + $('html').addClass('ismobile'); +} + +$(document).ready(function () { + + /* + * Sidebar + */ + (function () { + //Toggle + $('.body').on('click', '#menu-trigger, #log-trigger', function (e) { + e.preventDefault(); + var x = $(this).data('trigger'); + + $(x).toggleClass('toggled'); + $(this).toggleClass('open'); + $('.body').toggleClass('modal-open'); + + //Close opened sub-menus + $('.sub-menu.toggled').not('.active').each(function () { + $(this).removeClass('toggled'); + $(this).find('ul').hide(); + }); + + $('.profile-menu .main-menu').hide(); + + if (x == '#sidebar') { + $elem = '#sidebar'; + $elem2 = '#menu-trigger'; + + $('#log-trigger').removeClass('open'); + + if (!$('#action-center').hasClass('toggled')) { + $('#header').toggleClass('sidebar-toggled'); + } + else { + $('#action-center').removeClass('toggled'); + } + } + + if (x == '#action-center') { + $elem = '#action-center'; + $elem2 = '#log-trigger'; + + $('#menu-trigger').removeClass('open'); + + if (!$('#sidebar').hasClass('toggled')) { + $('#header').toggleClass('sidebar-toggled'); + } + else { + $('#sidebar').removeClass('toggled'); + } + } + + //When clicking outside + if ($('#header').hasClass('sidebar-toggled')) { + $(document).on('click', function (e) { + if (($(e.target).closest($elem).length === 0) && ($(e.target).closest($elem2).length === 0)) { + setTimeout(function () { + $('.body').removeClass('modal-open'); + $($elem).removeClass('toggled'); + $('#header').removeClass('sidebar-toggled'); + $($elem2).removeClass('open'); + }); + } + }); + } + }) + + //Submenu + $('.body').on('click', '.sub-menu > a', function (e) { + e.preventDefault(); + $(this).next().slideToggle(200); + $(this).parent().toggleClass('toggled'); + }); + })(); + + /* + * Clear Notification + */ + $('.body').on('click', '[data-clear="notification"]', function (e) { + e.preventDefault(); + + var x = $(this).closest('.listview'); + var y = x.find('.lv-item'); + var z = y.size(); + + $(this).parent().fadeOut(); + + x.find('.list-group').prepend(''); + x.find('.grid-loading').fadeIn(1500); + + + var w = 0; + y.each(function () { + var z = $(this); + setTimeout(function () { + z.addClass('animated fadeOutRightBig').delay(1000).queue(function () { + z.remove(); + }); + }, w += 150); + }) + + //Popup empty message + setTimeout(function () { + $('#notifications').addClass('empty'); + }, (z * 150) + 200); + }); + + /* + * Dropdown Menu + */ + if ($('.dropdown')[0]) { + //Propagate + $('.body').on('click', '.dropdown.open .dropdown-menu', function (e) { + e.stopPropagation(); + }); + + $('.dropdown').on('shown.bs.dropdown', function (e) { + if ($(this).attr('data-animation')) { + $animArray = []; + $animation = $(this).data('animation'); + $animArray = $animation.split(','); + $animationIn = 'animated ' + $animArray[0]; + $animationOut = 'animated ' + $animArray[1]; + $animationDuration = '' + if (!$animArray[2]) { + $animationDuration = 500; //if duration is not defined, default is set to 500ms + } + else { + $animationDuration = $animArray[2]; + } + + $(this).find('.dropdown-menu').removeClass($animationOut) + $(this).find('.dropdown-menu').addClass($animationIn); + } + }); + + $('.dropdown').on('hide.bs.dropdown', function (e) { + if ($(this).attr('data-animation')) { + e.preventDefault(); + $this = $(this); + $dropdownMenu = $this.find('.dropdown-menu'); + + $dropdownMenu.addClass($animationOut); + setTimeout(function () { + $this.removeClass('open') + + }, $animationDuration); + } + }); + } + + /* + * Custom Scrollbars + */ + function scrollbar(className, color, cursorWidth) { + $(className).niceScroll({ + cursorcolor: color, + cursorborder: 0, + cursorborderradius: 0, + cursorwidth: cursorWidth, + bouncescroll: true, + }); + } + + //Scrollbar for HTML(not mobile) but not for login page + if (!$('html').hasClass('ismobile')) { + if (!$('.login-content')[0]) { + scrollbar('html', 'rgba(0,0,0,0.3)', '5px'); + } + + //Scrollbar Tables + if ($('.table-responsive')[0]) { + scrollbar('.table-responsive', 'rgba(0,0,0,0.5)', '5px'); + } + + //Scrill bar for Chosen + if ($('.chosen-results')[0]) { + scrollbar('.chosen-results', 'rgba(0,0,0,0.5)', '5px'); + } + + //Scroll bar for tabs + if ($('.tab-nav')[0]) { + scrollbar('.tab-nav', 'rgba(0,0,0,0)', '1px'); + } + + //Scroll bar for dropdowm-menu + if ($('.dropdown-menu .c-overflow')[0]) { + scrollbar('.dropdown-menu .c-overflow', 'rgba(0,0,0,0.5)', '0px'); + } + + //Scrollbar for rest + if ($('.c-overflow')[0]) { + scrollbar('.c-overflow', 'rgba(0,0,0,0.5)', '5px'); + } + } + + /* + * Profile Menu + */ + $('.body').on('click', '.profile-menu > a', function (e) { + e.preventDefault(); + $(this).parent().toggleClass('toggled'); + $(this).next().slideToggle(200); + }); + + /* + * Bootstrap Growl - Notifications popups + */ + function notify(message, type) { + $.growl({ + message: message + }, { + type: type, + allow_dismiss: false, + label: 'Cancel', + className: 'btn-xs btn-inverse', + placement: { + from: 'top', + align: 'right' + }, + delay: 2500, + animate: { + enter: 'animated bounceIn', + exit: 'animated bounceOut' + }, + offset: { + x: 20, + y: 85 + } + }); + }; + + /* + * Waves Animation + */ + (function () { + Waves.attach('.btn:not(.btn-icon)'); + Waves.attach('.btn-icon', ['waves-circle', 'waves-float']); + Waves.init(); + })(); + + /* + * Collaspe Fix + */ + if ($('.collapse')[0]) { + + //Add active class for opened items + $('.collapse').on('show.bs.collapse', function (e) { + $(this).closest('.panel').find('.panel-heading').addClass('active'); + }); + + $('.collapse').on('hide.bs.collapse', function (e) { + $(this).closest('.panel').find('.panel-heading').removeClass('active'); + }); + + //Add active class for pre opened items + $('.collapse.in').each(function () { + $(this).closest('.panel').find('.panel-heading').addClass('active'); + }); + } + + /* + * Tooltips + */ + $('.body').tooltip({ + selector: '[data-toggle="tooltip"]' + }); + /* + * Popover + */ + if ($('[data-toggle="popover"]')[0]) { + $('[data-toggle="popover"]').popover(); + } + + /* + * Message + */ + + //Actions + if ($('.on-select')[0]) { + var checkboxes = '.lv-avatar-content input:checkbox'; + var actions = $('.on-select').closest('.lv-actions'); + + $('.body').on('click', checkboxes, function () { + if ($(checkboxes + ':checked')[0]) { + actions.addClass('toggled'); + } + else { + actions.removeClass('toggled'); + } + }); + } + + if ($('#ms-menu-trigger')[0]) { + $('.body').on('click', '#ms-menu-trigger', function (e) { + e.preventDefault(); + $(this).toggleClass('open'); + $('.ms-menu').toggleClass('toggled'); + }); + } + + /* + * Fullscreen Browsing + */ + if ($('[data-action="fullscreen"]')[0]) { + var fs = $("[data-action='fullscreen']"); + fs.on('click', function (e) { + e.preventDefault(); + + //Launch + function launchIntoFullscreen(element) { + + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } + } + + //Exit + function exitFullscreen() { + + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } + } + + launchIntoFullscreen(document.documentElement); + fs.closest('.dropdown').removeClass('open'); + }); + } + + /* + * Clear Local Storage + */ + if ($('[data-action="clear-localstorage"]')[0]) { + var cls = $('[data-action="clear-localstorage"]'); + + cls.on('click', function (e) { + e.preventDefault(); + + swal({ + title: "Are you sure?", + text: "All your saved localStorage values will be removed", + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: "Yes, delete it!", + closeOnConfirm: false + }, function () { + localStorage.clear(); + swal("Done!", "localStorage is cleared", "success"); + }); + }); + } + + /* + * Date Time Picker + */ + + //Date Time Picker + if ($('.date-time-picker')[0]) { + $('.date-time-picker').datetimepicker(); + } + + //Time + if ($('.time-picker')[0]) { + $('.time-picker').datetimepicker({ + format: 'LT' + }); + } + + /* + * Text Feild + */ + + //Add blue animated border and remove with condition when focus and blur + $('.body').on('focus', '.form-control', function () { + $(this).closest('.fg-line').addClass('fg-toggled'); + }) + + $('.body').on('blur', '.form-control', function () { + var p = $(this).closest('.form-group'); + var i = p.find('.form-control').val(); + + if (p.hasClass('fg-float')) { + if (i.length == 0) { + $(this).closest('.fg-line').removeClass('fg-toggled'); + } + } + else { + $(this).closest('.fg-line').removeClass('fg-toggled'); + } + }); + + //Add blue border for pre-valued fg-flot text feilds + $('.fg-float .form-control').each(function () { + var i = $(this).val(); + + if (!i.length == 0) { + $(this).closest('.fg-line').addClass('fg-toggled'); + } + + }); + + $('.sidebar-inner').jScrollPane({ + autoReinitialise: true + }); +}); + +(function ($, Sys) { + mydnnNotify = function (message, type, delay, label, allow_dismiss, animate, placement, offset, className) { + $.growl({ + message: message + }, { + type: type, + allow_dismiss: allow_dismiss, + label: label, + className: className, + placement: placement, + delay: delay, + animate: animate, + offset: offset + }); + }; +}(jQuery, window.Sys)); diff --git a/LiveChat/Scripts/init-widget.js b/LiveChat/Scripts/init-widget.js new file mode 100644 index 0000000..d2dcb96 --- /dev/null +++ b/LiveChat/Scripts/init-widget.js @@ -0,0 +1,161 @@ +var mydnnLiveChatBaseData; +var mydnnLiveChatRequests; +(function ($, Sys) { + $(document).ready(function () { + var __mydnnLiveChatRequests = []; + var __isAgentOnline = false; + var __livechatIsLoaded = false; + var __requestsString; + var __adminPanelUrl; + var __rootUrl = "/"; + var __visitorGUID; + var __portalID; + var __me = this; + var __counter = 0; + + if (typeof dnn == "undefined" || typeof mydnnSupportLiveChat != "undefined") return; + + $.ajax({ + type: "GET", + url: dnn.getVar("sf_siteRoot", "/") + "DesktopModules/MyDnnSupport.LiveChat/API/VisitorService/LiveChatWidget", + }).done(function (data) { + if (typeof mydnnSupportLiveChat != "undefined") return; // This means that i am in adminpanel page + + __rootUrl = data.RootUrl; + __portalID = data.PortalID; + + if (data.LiveChatEnabled) { + $('body').append(''); + + __visitorGUID = localStorage["MyDnnVisitorsOnline_VisitorGUID"]; + __isAgentOnline = data.IsAgentOnline; + + __me.initialLiveChat(data); + } + }); + + this.initialLiveChat = function (data) { + if (__counter++ < 10 && (typeof $.connection == "undefined")) { + setTimeout(function () { + __me.initialLiveChat(data); + }, 1000); + } + else { + if (typeof $.connection == "undefined") { + alert('signalR is not enabled!'); + } + + var $minButton = $('
        ').html(data.LiveChatMinButton); + $('body').append($minButton); + + //check agent is online or offline and show button by visibility + $('#mydnnLiveChatMinButton').find('[data-livechat-isonline]').hide(); + var status = (__isAgentOnline ? "online" : "offline"); + $('#mydnnLiveChatMinButton').find('[data-livechat-isonline="' + status + '"]').show(); + + //when min button click + $('#mydnnLiveChatMinButton').on('click', function () { + if (__livechatIsLoaded == false) { + __me.loadAngularAndScripts(data); + $("#mydnnLiveChatMinButton").hide(); + __livechatIsLoaded = true; + } + else { + $("#mydnnLiveChatMinButton").hide(); + angular.element(document.getElementById('mydnnLiveChatWidget')).scope().reloadLiveChat(); + } + }); + + //if visitor is chatting + if (localStorage["MyDnnLiveChatCurrentChat"]) + $('#mydnnLiveChatMinButton').trigger('click'); + + //if visitor is dnn user and agent + if (data.IsAgent) { + __requestsString = data.RequestsString; + __adminPanelUrl = data.AdminPanelUrl; + __me.joinAgent(); + } + } + } + + this.joinAgent = function () { + if (__counter++ < 10 && (typeof $.connection == "undefined" || $.connection.MyDnnSupportLiveChatHub.connection.state != 1)) { + setTimeout(function () { + __me.joinAgent(); + }, 1000); + } + else { + $.connection.MyDnnSupportLiveChatHub.invoke('JoinAgent', __portalID, true, false).done(function (data) { + if (data.IncomingLiveChats && data.IncomingLiveChats.length) { + __mydnnLiveChatRequests = data.IncomingLiveChats; + __me.liveChatRequests(0, "add"); + } + }); + } + } + + mydnnLiveChatRequests = this.liveChatRequests = function (livechatID, mode) { + var result = $.grep(__mydnnLiveChatRequests, function (e) { return e.LiveChatID == livechatID; }); + if (livechatID && !result.length && mode == "add") { + var req = { + LiveChatID: livechatID, + }; + __mydnnLiveChatRequests.push(req); + } + else if (result.length && mode == "remove") { + var indx = __mydnnLiveChatRequests.indexOf(result[0]); + __mydnnLiveChatRequests.splice(indx, 1); + if (!__mydnnLiveChatRequests.length) + $("#mydnnSupportLiveChatRequests").fadeOut(100); + } + + if (__mydnnLiveChatRequests.length) { + if (!$('body').find('#mydnnSupportLiveChatRequests').length) { + $('body').append('
        '); + $("#mydnnSupportLiveChatRequests").click(function () { + window.location = __adminPanelUrl; + }); + } + setTimeout(function () { + $("#mydnnSupportLiveChatRequests").html(__requestsString + "(" + __mydnnLiveChatRequests.length + ")"); + $("#mydnnSupportLiveChatRequests").fadeIn(100); + }, 500); + } + } + + this.loadAngularAndScripts = function (data) { + if (typeof angular == "undefined") + $.getScript(__rootUrl + "DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/angular.min.js", function () { + __me.loadLiveChatScripts(data); + }); + else + __me.loadLiveChatScripts(data); + } + + this.loadLiveChatScripts = function (data) { + $.getScript(__rootUrl + "DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Services/signalr.service.js", function () { + $.getScript(__rootUrl + "DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Services/ng-mydnn-services.js", function () { + $.getScript(__rootUrl + "DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/moment.js/moment.min.js", function () { + $.getScript(__rootUrl + "DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/livechat-visitor-controller.js", function () { + mydnnLiveChatBaseData = { RootUrl: __rootUrl, VisitorGUID: __visitorGUID }; + var $ang = $('
        '); + $ang.appendTo($('body')); + angular.bootstrap(document.getElementById('mydnnSupportLiveChat'), ['MyDnnSupportLiveChatApp']); + }); + }); + }); + }); + } + + this.getCookie = function (cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name) == 0) return c.substring(name.length, c.length); + } + return ""; + } + }); +}(jQuery, window.Sys)); diff --git a/LiveChat/Scripts/jquery.signalR-2.1.0.min.js b/LiveChat/Scripts/jquery.signalR-2.1.0.min.js new file mode 100644 index 0000000..dc3cf2d --- /dev/null +++ b/LiveChat/Scripts/jquery.signalR-2.1.0.min.js @@ -0,0 +1,8 @@ +/*! + * ASP.NET SignalR JavaScript Library v2.1.0 + * http://signalr.net/ + * + * Copyright (C) Microsoft Corporation. All rights reserved. + * + */ +(function(n,t,i){function w(t,i){var u,f;if(n.isArray(t)){for(u=t.length-1;u>=0;u--)f=t[u],n.type(f)==="string"&&r.transports[f]||(i.log("Invalid transport: "+f+", removing it from the transports list."),t.splice(u,1));t.length===0&&(i.log("No transports remain within the specified transport array."),t=null)}else if(r.transports[t]||t==="auto"){if(t==="auto"&&r._.ieVersion<=8)return["longPolling"]}else i.log("Invalid transport: "+t.toString()+"."),t=null;return t}function b(n){return n==="http:"?80:n==="https:"?443:void 0}function a(n,t){return t.match(/:\d+$/)?t:t+":"+b(n)}function k(t,i){var u=this,r=[];u.tryBuffer=function(i){return t.state===n.signalR.connectionState.connecting?(r.push(i),!0):!1};u.drain=function(){if(t.state===n.signalR.connectionState.connected)while(r.length>0)i(r.shift())};u.clear=function(){r=[]}}var f={nojQuery:"jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.",noTransportOnInit:"No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.",errorOnNegotiate:"Error during negotiation request.",stoppedWhileLoading:"The connection was stopped during page load.",stoppedWhileNegotiating:"The connection was stopped during the negotiate request.",errorParsingNegotiateResponse:"Error parsing negotiate response.",errorDuringStartRequest:"Error during start request. Stopping the connection.",stoppedDuringStartRequest:"The connection was stopped during the start request.",errorParsingStartResponse:"Error parsing start response: '{0}'. Stopping the connection.",invalidStartResponse:"Invalid start response: '{0}'. Stopping the connection.",protocolIncompatible:"You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.",sendFailed:"Send failed.",parseFailed:"Failed at parsing response: {0}",longPollFailed:"Long polling request failed.",eventSourceFailedToConnect:"EventSource failed to connect.",eventSourceError:"Error raised by EventSource",webSocketClosed:"WebSocket closed.",pingServerFailedInvalidResponse:"Invalid ping response when pinging server: '{0}'.",pingServerFailed:"Failed to ping server.",pingServerFailedStatusCode:"Failed to ping server. Server responded with status code {0}, stopping the connection.",pingServerFailedParse:"Failed to parse ping server response, stopping the connection.",noConnectionTransport:"Connection is in an invalid state, there is no transport active.",webSocketsInvalidState:"The Web Socket transport is in an invalid state, transitioning into reconnecting.",reconnectTimeout:"Couldn't reconnect within the configured timeout of {0} ms, disconnecting.",reconnectWindowTimeout:"The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection."};if(typeof n!="function")throw new Error(f.nojQuery);var r,h,s=t.document.readyState==="complete",e=n(t),c="__Negotiate Aborted__",u={onStart:"onStart",onStarting:"onStarting",onReceived:"onReceived",onError:"onError",onConnectionSlow:"onConnectionSlow",onReconnecting:"onReconnecting",onReconnect:"onReconnect",onStateChanged:"onStateChanged",onDisconnect:"onDisconnect"},v=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},o=function(t,i,r){return i===t.state?(t.state=r,n(t).triggerHandler(u.onStateChanged,[{oldState:i,newState:r}]),!0):!1},y=function(n){return n.state===r.connectionState.disconnected},l=function(n){return n._.keepAliveData.activated&&n.transport.supportsKeepAlive(n)},p=function(i){var f,e;i._.configuredStopReconnectingTimeout||(e=function(t){var i=r._.format(r.resources.reconnectTimeout,t.disconnectTimeout);t.log(i);n(t).triggerHandler(u.onError,[r._.error(i,"TimeoutException")]);t.stop(!1,!1)},i.reconnecting(function(){var n=this;n.state===r.connectionState.reconnecting&&(f=t.setTimeout(function(){e(n)},n.disconnectTimeout))}),i.stateChanged(function(n){n.oldState===r.connectionState.reconnecting&&t.clearTimeout(f)}),i._.configuredStopReconnectingTimeout=!0)};r=function(n,t,i){return new r.fn.init(n,t,i)};r._={defaultContentType:"application/x-www-form-urlencoded; charset=UTF-8",ieVersion:function(){var i,n;return t.navigator.appName==="Microsoft Internet Explorer"&&(n=/MSIE ([0-9]+\.[0-9]+)/.exec(t.navigator.userAgent),n&&(i=t.parseFloat(n[1]))),i}(),error:function(n,t,i){var r=new Error(n);return r.source=t,typeof i!="undefined"&&(r.context=i),r},transportError:function(n,t,r,u){var f=this.error(n,r,u);return f.transport=t?t.name:i,f},format:function(){for(var t=arguments[0],n=0;n<\/script>.");}};e.load(function(){s=!0});r.fn=r.prototype={init:function(t,i,r){var f=n(this);this.url=t;this.qs=i;this.lastError=null;this._={keepAliveData:{},connectingMessageBuffer:new k(this,function(n){f.triggerHandler(u.onReceived,[n])}),onFailedTimeoutHandle:null,lastMessageAt:(new Date).getTime(),lastActiveAt:(new Date).getTime(),beatInterval:5e3,beatHandle:null,totalTransportConnectTimeout:0};typeof r=="boolean"&&(this.logging=r)},_parseResponse:function(n){var t=this;return n?typeof n=="string"?t.json.parse(n):n:n},_originalJson:t.JSON,json:t.JSON,isCrossDomain:function(i,r){var u;return(i=n.trim(i),r=r||t.location,i.indexOf("http")!==0)?!1:(u=t.document.createElement("a"),u.href=i,u.protocol+a(u.protocol,u.host)!==r.protocol+a(r.protocol,r.host))},ajaxDataType:"text",contentType:"application/json; charset=UTF-8",logging:!1,state:r.connectionState.disconnected,clientProtocol:"1.4",reconnectDelay:2e3,transportConnectTimeout:0,disconnectTimeout:3e4,reconnectWindow:3e4,keepAliveWarnAt:2/3,start:function(i,h){var a=this,v={pingInterval:3e5,waitForPageLoad:!0,transport:"auto",jsonp:!1},d,y=a._deferral||n.Deferred(),b=t.document.createElement("a"),k,g;if(a.lastError=null,a._deferral=y,!a.json)throw new Error("SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.");if(n.type(i)==="function"?h=i:n.type(i)==="object"&&(n.extend(v,i),n.type(v.callback)==="function"&&(h=v.callback)),v.transport=w(v.transport,a),!v.transport)throw new Error("SignalR: Invalid transport(s) specified, aborting start.");return(a._.config=v,!s&&v.waitForPageLoad===!0)?(a._.deferredStartHandler=function(){a.start(i,h)},e.bind("load",a._.deferredStartHandler),y.promise()):a.state===r.connectionState.connecting?y.promise():o(a,r.connectionState.disconnected,r.connectionState.connecting)===!1?(y.resolve(a),y.promise()):(p(a),b.href=a.url,b.protocol&&b.protocol!==":"?(a.protocol=b.protocol,a.host=b.host):(a.protocol=t.document.location.protocol,a.host=b.host||t.document.location.host),a.baseUrl=a.protocol+"//"+a.host,a.wsProtocol=a.protocol==="https:"?"wss://":"ws://",v.transport==="auto"&&v.jsonp===!0&&(v.transport="longPolling"),a.url.indexOf("//")===0&&(a.url=t.location.protocol+a.url,a.log("Protocol relative URL detected, normalizing it to '"+a.url+"'.")),this.isCrossDomain(a.url)&&(a.log("Auto detected cross domain url."),v.transport==="auto"&&(v.transport=["webSockets","serverSentEvents","longPolling"]),typeof v.withCredentials=="undefined"&&(v.withCredentials=!0),v.jsonp||(v.jsonp=!n.support.cors,v.jsonp&&a.log("Using jsonp because this browser doesn't support CORS.")),a.contentType=r._.defaultContentType),a.withCredentials=v.withCredentials,a.ajaxDataType=v.jsonp?"jsonp":"text",n(a).bind(u.onStart,function(){n.type(h)==="function"&&h.call(a);y.resolve(a)}),d=function(i,s){var p=r._.error(f.noTransportOnInit);if(s=s||0,s>=i.length){n(a).triggerHandler(u.onError,[p]);y.reject(p);a.stop();return}if(a.state!==r.connectionState.disconnected){var w=i[s],h=r.transports[w],c=!1,v=function(){c||(c=!0,t.clearTimeout(a._.onFailedTimeoutHandle),h.stop(a),d(i,s+1))};a.transport=h;try{a._.onFailedTimeoutHandle=t.setTimeout(function(){a.log(h.name+" timed out when trying to connect.");v()},a._.totalTransportConnectTimeout);h.start(a,function(){var i=r._.firefoxMajorVersion(t.navigator.userAgent)>=11,f=!!a.withCredentials&&i;a.state!==r.connectionState.disconnected&&(c||(c=!0,t.clearTimeout(a._.onFailedTimeoutHandle),l(a)&&r.transports._logic.monitorKeepAlive(a),r.transports._logic.startHeartbeat(a),r._.configurePingInterval(a),o(a,r.connectionState.connecting,r.connectionState.connected),a._.connectingMessageBuffer.drain(),n(a).triggerHandler(u.onStart),e.bind("unload",function(){a.log("Window unloading, stopping the connection.");a.stop(f)}),i&&e.bind("beforeunload",function(){t.setTimeout(function(){a.stop(f)},0)})))},v)}catch(b){a.log(h.name+" transport threw '"+b.message+"' when attempting to start.");v()}}},k=a.url+"/negotiate",g=function(t,i){var e=r._.error(f.errorOnNegotiate,t,i._.negotiateRequest);n(i).triggerHandler(u.onError,e);y.reject(e);i.stop()},n(a).triggerHandler(u.onStarting),k=r.transports._logic.prepareQueryString(a,k),a.log("Negotiating with '"+k+"'."),a._.negotiateRequest=r.transports._logic.ajax(a,{url:k,error:function(n,t){t!==c?g(n,a):y.reject(r._.error(f.stoppedWhileNegotiating,null,a._.negotiateRequest))},success:function(t){var i,e,h,o=[],s=[];try{i=a._parseResponse(t)}catch(c){g(r._.error(f.errorParsingNegotiateResponse,c),a);return}if(e=a._.keepAliveData,a.appRelativeUrl=i.Url,a.id=i.ConnectionId,a.token=i.ConnectionToken,a.webSocketServerUrl=i.WebSocketServerUrl,a._.longPollDelay=i.LongPollDelay*1e3,a.disconnectTimeout=i.DisconnectTimeout*1e3,a._.totalTransportConnectTimeout=a.transportConnectTimeout+i.TransportConnectTimeout*1e3,i.KeepAliveTimeout?(e.activated=!0,e.timeout=i.KeepAliveTimeout*1e3,e.timeoutWarning=e.timeout*a.keepAliveWarnAt,a._.beatInterval=(e.timeout-e.timeoutWarning)/3):e.activated=!1,a.reconnectWindow=a.disconnectTimeout+(e.timeout||0),!i.ProtocolVersion||i.ProtocolVersion!==a.clientProtocol){h=r._.error(r._.format(f.protocolIncompatible,a.clientProtocol,i.ProtocolVersion));n(a).triggerHandler(u.onError,[h]);y.reject(h);return}n.each(r.transports,function(n){if(n.indexOf("_")===0||n==="webSockets"&&!i.TryWebSockets)return!0;s.push(n)});n.isArray(v.transport)?n.each(v.transport,function(t,i){n.inArray(i,s)>=0&&o.push(i)}):v.transport==="auto"?o=s:n.inArray(v.transport,s)>=0&&o.push(v.transport);d(o)}}),y.promise())},starting:function(t){var i=this;return n(i).bind(u.onStarting,function(){t.call(i)}),i},send:function(n){var t=this;if(t.state===r.connectionState.disconnected)throw new Error("SignalR: Connection must be started before data can be sent. Call .start() before .send()");if(t.state===r.connectionState.connecting)throw new Error("SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.");return t.transport.send(t,n),t},received:function(t){var i=this;return n(i).bind(u.onReceived,function(n,r){t.call(i,r)}),i},stateChanged:function(t){var i=this;return n(i).bind(u.onStateChanged,function(n,r){t.call(i,r)}),i},error:function(t){var i=this;return n(i).bind(u.onError,function(n,r,u){i.lastError=r;t.call(i,r,u)}),i},disconnected:function(t){var i=this;return n(i).bind(u.onDisconnect,function(){t.call(i)}),i},connectionSlow:function(t){var i=this;return n(i).bind(u.onConnectionSlow,function(){t.call(i)}),i},reconnecting:function(t){var i=this;return n(i).bind(u.onReconnecting,function(){t.call(i)}),i},reconnected:function(t){var i=this;return n(i).bind(u.onReconnect,function(){t.call(i)}),i},stop:function(i,h){var a=this,v=a._deferral;if(a._.deferredStartHandler&&e.unbind("load",a._.deferredStartHandler),delete a._.config,delete a._.deferredStartHandler,!s&&(!a._.config||a._.config.waitForPageLoad===!0)){a.log("Stopping connection prior to negotiate.");v&&v.reject(r._.error(f.stoppedWhileLoading));return}if(a.state!==r.connectionState.disconnected)return a.log("Stopping connection."),o(a,a.state,r.connectionState.disconnected),t.clearTimeout(a._.beatHandle),t.clearTimeout(a._.onFailedTimeoutHandle),t.clearInterval(a._.pingIntervalId),a.transport&&(a.transport.stop(a),h!==!1&&a.transport.abort(a,i),l(a)&&r.transports._logic.stopMonitoringKeepAlive(a),a.transport=null),a._.negotiateRequest&&(a._.negotiateRequest.abort(c),delete a._.negotiateRequest),r.transports._logic.tryAbortStartRequest(a),n(a).triggerHandler(u.onDisconnect),delete a._deferral,delete a.messageId,delete a.groupsToken,delete a.id,delete a._.pingIntervalId,delete a._.lastMessageAt,delete a._.lastActiveAt,delete a._.longPollDelay,a._.connectingMessageBuffer.clear(),a},log:function(n){v(n,this.logging)}};r.fn.init.prototype=r.fn;r.noConflict=function(){return n.connection===r&&(n.connection=h),r};n.connection&&(h=n.connection);n.connection=n.signalR=r})(window.jQuery,window),function(n,t){function o(n){n._.keepAliveData.monitoring&&h(n);r.markActive(n)&&(n._.beatHandle=t.setTimeout(function(){o(n)},n._.beatInterval))}function h(t){var r=t._.keepAliveData,f;t.state===i.connectionState.connected&&(f=(new Date).getTime()-t._.lastMessageAt,f>=r.timeout?(t.log("Keep alive timed out. Notifying transport that connection has been lost."),t.transport.lostConnection(t)):f>=r.timeoutWarning?r.userNotified||(t.log("Keep alive has been missed, connection may be dead/slow."),n(t).triggerHandler(u.onConnectionSlow),r.userNotified=!0):r.userNotified=!1)}function f(n,t){var i=n.url+t;return n.transport&&(i+="?transport="+n.transport.name),r.prepareQueryString(n,i)}var i=n.signalR,u=n.signalR.events,s=n.signalR.changeState,e="__Start Aborted__",r;i.transports={};r=i.transports._logic={ajax:function(t,i){return n.ajax(n.extend(!0,{},n.signalR.ajaxDefaults,{type:"GET",data:{},xhrFields:{withCredentials:t.withCredentials},contentType:t.contentType,dataType:t.ajaxDataType},i))},pingServer:function(t){var e,f,u=n.Deferred();return t.transport?(e=t.url+"/ping",e=r.addQs(e,t.qs),f=r.ajax(t,{url:e,success:function(n){var r;try{r=t._parseResponse(n)}catch(e){u.reject(i._.transportError(i.resources.pingServerFailedParse,t.transport,e,f));t.stop();return}r.Response==="pong"?u.resolve():u.reject(i._.transportError(i._.format(i.resources.pingServerFailedInvalidResponse,n),t.transport,null,f))},error:function(n){n.status===401||n.status===403?(u.reject(i._.transportError(i._.format(i.resources.pingServerFailedStatusCode,n.status),t.transport,n,f)),t.stop()):u.reject(i._.transportError(i.resources.pingServerFailed,t.transport,n,f))}})):u.reject(i._.transportError(i.resources.noConnectionTransport,t.transport)),u.promise()},prepareQueryString:function(n,i){var u;return u=r.addQs(i,"clientProtocol="+n.clientProtocol),u=r.addQs(u,n.qs),n.token&&(u+="&connectionToken="+t.encodeURIComponent(n.token)),n.data&&(u+="&connectionData="+t.encodeURIComponent(n.data)),u},addQs:function(t,i){var r=t.indexOf("?")!==-1?"&":"?",u;if(!i)return t;if(typeof i=="object")return t+r+n.param(i);if(typeof i=="string")return u=i.charAt(0),(u==="?"||u==="&")&&(r=""),t+r+i;throw new Error("Query string property must be either a string or object.");},getUrl:function(n,i,u,f){var s=i==="webSockets"?"":n.baseUrl,e=s+n.appRelativeUrl,o="transport="+i;return n.groupsToken&&(o+="&groupsToken="+t.encodeURIComponent(n.groupsToken)),u?(e+=f?"/poll":"/reconnect",n.messageId&&(o+="&messageId="+t.encodeURIComponent(n.messageId))):e+="/connect",e+="?"+o,e=r.prepareQueryString(n,e),e+("&tid="+Math.floor(Math.random()*11))},maximizePersistentResponse:function(n){return{MessageId:n.C,Messages:n.M,Initialized:typeof n.S!="undefined"?!0:!1,Disconnect:typeof n.D!="undefined"?!0:!1,ShouldReconnect:typeof n.T!="undefined"?!0:!1,LongPollDelay:n.L,GroupsToken:n.G}},updateGroups:function(n,t){t&&(n.groupsToken=t)},stringifySend:function(n,t){return typeof t=="string"||typeof t=="undefined"||t===null?t:n.json.stringify(t)},ajaxSend:function(t,e){var h=r.stringifySend(t,e),c=f(t,"/send"),o,s=function(t,r){n(r).triggerHandler(u.onError,[i._.transportError(i.resources.sendFailed,r.transport,t,o),e])};return o=r.ajax(t,{url:c,type:t.ajaxDataType==="jsonp"?"GET":"POST",contentType:i._.defaultContentType,data:{data:h},success:function(n){var i;if(n){try{i=t._parseResponse(n)}catch(u){s(u,t);t.stop();return}r.triggerReceived(t,i)}},error:function(n,i){i!=="abort"&&i!=="parsererror"&&s(n,t)}})},ajaxAbort:function(n,t){if(typeof n.transport!="undefined"){t=typeof t=="undefined"?!0:t;var i=f(n,"/abort");r.ajax(n,{url:i,async:t,timeout:1e3,type:"POST"});n.log("Fired ajax abort async = "+t+".")}},tryInitialize:function(t,o,s){var l,h,a=function(n){var i=t._deferral;i&&i.reject(n)},c=function(i){n(t).triggerHandler(u.onError,[i]);a(i);t.stop()};o.Initialized&&(l=f(t,"/start"),h=r.ajax(t,{url:l,success:function(n){var r;try{r=t._parseResponse(n)}catch(u){c(i._.error(i._.format(i.resources.errorParsingStartResponse,n),u,h));return}r.Response==="started"?s():c(i._.error(i._.format(i.resources.invalidStartResponse,n),null,h))},error:function(n,t){t!==e?c(i._.error(i.resources.errorDuringStartRequest,n,h)):a(i._.error(i.resources.stoppedDuringStartRequest,null,h))}}),t._.startRequest=h)},tryAbortStartRequest:function(n){n._.startRequest&&(n._.startRequest.abort(e),delete n._.startRequest)},triggerReceived:function(t,i){t._.connectingMessageBuffer.tryBuffer(i)||n(t).triggerHandler(u.onReceived,[i])},processMessages:function(t,i,u){var f;r.markLastMessage(t);i&&(f=r.maximizePersistentResponse(i),r.updateGroups(t,f.GroupsToken),f.MessageId&&(t.messageId=f.MessageId),f.Messages&&(n.each(f.Messages,function(n,i){r.triggerReceived(t,i)}),r.tryInitialize(t,f,u)))},monitorKeepAlive:function(t){var i=t._.keepAliveData;i.monitoring?t.log("Tried to monitor keep alive but it's already being monitored."):(i.monitoring=!0,r.markLastMessage(t),t._.keepAliveData.reconnectKeepAliveUpdate=function(){r.markLastMessage(t)},n(t).bind(u.onReconnect,t._.keepAliveData.reconnectKeepAliveUpdate),t.log("Now monitoring keep alive with a warning timeout of "+i.timeoutWarning+" and a connection lost timeout of "+i.timeout+"."))},stopMonitoringKeepAlive:function(t){var i=t._.keepAliveData;i.monitoring&&(i.monitoring=!1,n(t).unbind(u.onReconnect,t._.keepAliveData.reconnectKeepAliveUpdate),t._.keepAliveData={},t.log("Stopping the monitoring of the keep alive."))},startHeartbeat:function(n){n._.lastActiveAt=(new Date).getTime();o(n)},markLastMessage:function(n){n._.lastMessageAt=(new Date).getTime()},markActive:function(n){return r.verifyLastActive(n)?(n._.lastActiveAt=(new Date).getTime(),!0):!1},isConnectedOrReconnecting:function(n){return n.state===i.connectionState.connected||n.state===i.connectionState.reconnecting},ensureReconnectingState:function(t){return s(t,i.connectionState.connected,i.connectionState.reconnecting)===!0&&n(t).triggerHandler(u.onReconnecting),t.state===i.connectionState.reconnecting},clearReconnectTimeout:function(n){n&&n._.reconnectTimeout&&(t.clearTimeout(n._.reconnectTimeout),delete n._.reconnectTimeout)},verifyLastActive:function(t){if((new Date).getTime()-t._.lastActiveAt>=t.reconnectWindow){var r=i._.format(i.resources.reconnectWindowTimeout,new Date(t._.lastActiveAt),t.reconnectWindow);return t.log(r),n(t).triggerHandler(u.onError,[i._.error(r,"TimeoutException")]),t.stop(!1,!1),!1}return!0},reconnect:function(n,u){var f=i.transports[u];if(r.isConnectedOrReconnecting(n)&&!n._.reconnectTimeout){if(!r.verifyLastActive(n))return;n._.reconnectTimeout=t.setTimeout(function(){r.verifyLastActive(n)&&(f.stop(n),r.ensureReconnectingState(n)&&(n.log(u+" reconnecting."),f.start(n)))},n.reconnectDelay)}},handleParseFailure:function(t,r,f,e,o){t.state===i.connectionState.connecting?(t.log("Failed to parse server response while attempting to connect."),e()):(n(t).triggerHandler(u.onError,[i._.transportError(i._.format(i.resources.parseFailed,r),t.transport,f,o)]),t.stop())},foreverFrame:{count:0,connections:{}}}}(window.jQuery,window),function(n,t){var r=n.signalR,u=n.signalR.events,f=n.signalR.changeState,i=r.transports._logic;r.transports.webSockets={name:"webSockets",supportsKeepAlive:function(){return!0},send:function(t,f){var e=i.stringifySend(t,f);try{t.socket.send(e)}catch(o){n(t).triggerHandler(u.onError,[r._.transportError(r.resources.webSocketsInvalidState,t.transport,o,t.socket),f])}},start:function(e,o,s){var h,c=!1,l=this,a=!o,v=n(e);if(!t.WebSocket){s();return}e.socket||(h=e.webSocketServerUrl?e.webSocketServerUrl:e.wsProtocol+e.host,h+=i.getUrl(e,this.name,a),e.log("Connecting to websocket endpoint '"+h+"'."),e.socket=new t.WebSocket(h),e.socket.onopen=function(){c=!0;e.log("Websocket opened.");i.clearReconnectTimeout(e);f(e,r.connectionState.reconnecting,r.connectionState.connected)===!0&&v.triggerHandler(u.onReconnect)},e.socket.onclose=function(t){if(this===e.socket){if(c)typeof t.wasClean!="undefined"&&t.wasClean===!1?(n(e).triggerHandler(u.onError,[r._.transportError(r.resources.webSocketClosed,e.transport,t)]),e.log("Unclean disconnect from websocket: "+t.reason||"[no reason given].")):e.log("Websocket closed.");else{s?s():a&&l.reconnect(e);return}l.reconnect(e)}},e.socket.onmessage=function(t){var r;try{r=e._parseResponse(t.data)}catch(u){i.handleParseFailure(e,t.data,u,s,t);return}r&&(n.isEmptyObject(r)||r.M?i.processMessages(e,r,o):i.triggerReceived(e,r))})},reconnect:function(n){i.reconnect(n,this.name)},lostConnection:function(n){this.reconnect(n)},stop:function(n){i.clearReconnectTimeout(n);n.socket&&(n.log("Closing the Websocket."),n.socket.close(),n.socket=null)},abort:function(n,t){i.ajaxAbort(n,t)}}}(window.jQuery,window),function(n,t){var i=n.signalR,u=n.signalR.events,e=n.signalR.changeState,r=i.transports._logic,f=function(n){t.clearTimeout(n._.reconnectAttemptTimeoutHandle);delete n._.reconnectAttemptTimeoutHandle};i.transports.serverSentEvents={name:"serverSentEvents",supportsKeepAlive:function(){return!0},timeOut:3e3,start:function(o,s,h){var c=this,l=!1,a=n(o),v=!s,y;if(o.eventSource&&(o.log("The connection already has an event source. Stopping it."),o.stop()),!t.EventSource){h&&(o.log("This browser doesn't support SSE."),h());return}y=r.getUrl(o,this.name,v);try{o.log("Attempting to connect to SSE endpoint '"+y+"'.");o.eventSource=new t.EventSource(y,{withCredentials:o.withCredentials})}catch(p){o.log("EventSource failed trying to connect with error "+p.Message+".");h?h():(a.triggerHandler(u.onError,[i._.transportError(i.resources.eventSourceFailedToConnect,o.transport,p)]),v&&c.reconnect(o));return}v&&(o._.reconnectAttemptTimeoutHandle=t.setTimeout(function(){l===!1&&o.eventSource.readyState!==t.EventSource.OPEN&&c.reconnect(o)},c.timeOut));o.eventSource.addEventListener("open",function(){o.log("EventSource connected.");f(o);r.clearReconnectTimeout(o);l===!1&&(l=!0,e(o,i.connectionState.reconnecting,i.connectionState.connected)===!0&&a.triggerHandler(u.onReconnect))},!1);o.eventSource.addEventListener("message",function(n){var t;if(n.data!=="initialized"){try{t=o._parseResponse(n.data)}catch(i){r.handleParseFailure(o,n.data,i,h,n);return}r.processMessages(o,t,s)}},!1);o.eventSource.addEventListener("error",function(n){if(this===o.eventSource){if(!l){h&&h();return}o.log("EventSource readyState: "+o.eventSource.readyState+".");n.eventPhase===t.EventSource.CLOSED?(o.log("EventSource reconnecting due to the server connection ending."),c.reconnect(o)):(o.log("EventSource error."),a.triggerHandler(u.onError,[i._.transportError(i.resources.eventSourceError,o.transport,n)]))}},!1)},reconnect:function(n){r.reconnect(n,this.name)},lostConnection:function(n){this.reconnect(n)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){f(n);r.clearReconnectTimeout(n);n&&n.eventSource&&(n.log("EventSource calling close()."),n.eventSource.close(),n.eventSource=null,delete n.eventSource)},abort:function(n,t){r.ajaxAbort(n,t)}}}(window.jQuery,window),function(n,t){var r=n.signalR,e=n.signalR.events,o=n.signalR.changeState,i=r.transports._logic,u=function(){var n=t.document.createElement("iframe");return n.setAttribute("style","position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;"),n},f=function(){var i=null,f=1e3,n=0;return{prevent:function(){r._.ieVersion<=8&&(n===0&&(i=t.setInterval(function(){var n=u();t.document.body.appendChild(n);t.document.body.removeChild(n);n=null},f)),n++)},cancel:function(){n===1&&t.clearInterval(i);n>0&&n--}}}();r.transports.foreverFrame={name:"foreverFrame",supportsKeepAlive:function(){return!0},iframeClearThreshold:50,start:function(n,r,e){var l=this,s=i.foreverFrame.count+=1,h,o=u(),c=function(){n.log("Forever frame iframe finished loading and is no longer receiving messages.");l.reconnect(n)};if(t.EventSource){e&&(n.log("This browser supports SSE, skipping Forever Frame."),e());return}o.setAttribute("data-signalr-connection-id",n.id);f.prevent();h=i.getUrl(n,this.name);h+="&frameId="+s;t.document.body.appendChild(o);n.log("Binding to iframe's load event.");o.addEventListener?o.addEventListener("load",c,!1):o.attachEvent&&o.attachEvent("onload",c);o.src=h;i.foreverFrame.connections[s]=n;n.frame=o;n.frameId=s;r&&(n.onSuccess=function(){n.log("Iframe transport started.");r()})},reconnect:function(n){var r=this;i.isConnectedOrReconnecting(n)&&i.verifyLastActive(n)&&t.setTimeout(function(){if(i.verifyLastActive(n)&&n.frame&&i.ensureReconnectingState(n)){var u=n.frame,t=i.getUrl(n,r.name,!0)+"&frameId="+n.frameId;n.log("Updating iframe src to '"+t+"'.");u.src=t}},n.reconnectDelay)},lostConnection:function(n){this.reconnect(n)},send:function(n,t){i.ajaxSend(n,t)},receive:function(t,u){var f,e,o;if(t.json!==t._originalJson&&(u=t._originalJson.stringify(u)),o=t._parseResponse(u),i.processMessages(t,o,t.onSuccess),t.state===n.signalR.connectionState.connected&&(t.frameMessageCount=(t.frameMessageCount||0)+1,t.frameMessageCount>r.transports.foreverFrame.iframeClearThreshold&&(t.frameMessageCount=0,f=t.frame.contentWindow||t.frame.contentDocument,f&&f.document&&f.document.body)))for(e=f.document.body;e.firstChild;)e.removeChild(e.firstChild)},stop:function(n){var r=null;if(f.cancel(),n.frame){if(n.frame.stop)n.frame.stop();else try{r=n.frame.contentWindow||n.frame.contentDocument;r.document&&r.document.execCommand&&r.document.execCommand("Stop")}catch(u){n.log("Error occured when stopping foreverFrame transport. Message = "+u.message+".")}n.frame.parentNode===t.document.body&&t.document.body.removeChild(n.frame);delete i.foreverFrame.connections[n.frameId];n.frame=null;n.frameId=null;delete n.frame;delete n.frameId;delete n.onSuccess;delete n.frameMessageCount;n.log("Stopping forever frame.")}},abort:function(n,t){i.ajaxAbort(n,t)},getConnection:function(n){return i.foreverFrame.connections[n]},started:function(t){o(t,r.connectionState.reconnecting,r.connectionState.connected)===!0&&n(t).triggerHandler(e.onReconnect)}}}(window.jQuery,window),function(n,t){var r=n.signalR,u=n.signalR.events,e=n.signalR.changeState,f=n.signalR.isDisconnecting,i=r.transports._logic,o=function(){try{return"onprogress"in new t.XMLHttpRequest}catch(n){return!1}}();r.transports.longPolling={name:"longPolling",supportsKeepAlive:function(n){return o&&n.ajaxDataType!=="jsonp"&&n._.longPollDelay===0},reconnectDelay:3e3,start:function(o,s,h){var a=this,v=function(){v=n.noop;h=null;o.log("LongPolling connected.");s()},y=function(){return h?(h(),h=null,o.log("LongPolling failed to connect."),!0):!1},c=o._,l=0,p=function(i){t.clearTimeout(c.reconnectTimeoutId);c.reconnectTimeoutId=null;e(i,r.connectionState.reconnecting,r.connectionState.connected)===!0&&(i.log("Raising the reconnect event"),n(i).triggerHandler(u.onReconnect))},w=36e5;o.pollXhr&&(o.log("Polling xhr requests already exists, aborting."),o.stop());o.messageId=null;c.reconnectTimeoutId=null;c.pollTimeoutId=t.setTimeout(function(){(function e(s,h){var d=s.messageId,g=d===null,b=!g,nt=!h,k=i.getUrl(s,a.name,b,nt);f(s)!==!0&&(o.log("Opening long polling request to '"+k+"'."),s.pollXhr=i.ajax(o,{xhrFields:{onprogress:function(){i.markLastMessage(o)}},url:k,success:function(r){var h,w=0,u,a;o.log("Long poll complete.");l=0;try{h=o._parseResponse(r)}catch(b){i.handleParseFailure(s,r,b,y,s.pollXhr);return}(c.reconnectTimeoutId!==null&&p(s),h&&(u=i.maximizePersistentResponse(h)),i.processMessages(s,h,v),u&&n.type(u.LongPollDelay)==="number"&&(w=u.LongPollDelay),u&&u.Disconnect)||f(s)!==!0&&(a=u&&u.ShouldReconnect,!a||i.ensureReconnectingState(s))&&(w>0?c.pollTimeoutId=t.setTimeout(function(){e(s,a)},w):e(s,a))},error:function(f,h){if(t.clearTimeout(c.reconnectTimeoutId),c.reconnectTimeoutId=null,h==="abort"){o.log("Aborted xhr request.");return}if(!y()){if(l++,o.state!==r.connectionState.reconnecting&&(o.log("An error occurred using longPolling. Status = "+h+". Response = "+f.responseText+"."),n(s).triggerHandler(u.onError,[r._.transportError(r.resources.longPollFailed,o.transport,f,s.pollXhr)])),(o.state===r.connectionState.connected||o.state===r.connectionState.reconnecting)&&!i.verifyLastActive(o))return;if(!i.ensureReconnectingState(s))return;c.pollTimeoutId=t.setTimeout(function(){e(s,!0)},a.reconnectDelay)}}}),b&&h===!0&&(c.reconnectTimeoutId=t.setTimeout(function(){p(s)},Math.min(1e3*(Math.pow(2,l)-1),w))))})(o)},250)},lostConnection:function(n){n.pollXhr&&n.pollXhr.abort("lostConnection")},send:function(n,t){i.ajaxSend(n,t)},stop:function(n){t.clearTimeout(n._.pollTimeoutId);t.clearTimeout(n._.reconnectTimeoutId);delete n._.pollTimeoutId;delete n._.reconnectTimeoutId;n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr)},abort:function(n,t){i.ajaxAbort(n,t)}}}(window.jQuery,window),function(n){function r(n){return n+e}function s(n,t,i){for(var f=n.length,u=[],r=0;r + /// + /// + public class PostData + { + public int ID { get; set; } + } + + /// + /// + /// + public class WidgetSettingsDTO + { + public Hashtable WidgetSettings { get; set; } + public Hashtable MinButtonSettings { get; set; } + public Hashtable Locales { get; set; } + } + + public class BasicSettingsDTO + { + public Hashtable PortalSettings { get; set; } + public Hashtable ModuleSettings { get; set; } + } + + /// + /// + /// + public class HistoryDTO + { + public int[] Items { get; set; } + } + + #endregion + + /// + /// + /// + [DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)] + [SupportedModules("MyDnnSupport.LiveChat")] + [DnnAuthorize(StaticRoles = "MyDnnSupportAgent")] + public class AgentServiceController : DnnApiController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(AgentServiceController)); + + #region WebApi Methods + + #region Visitor List + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetVisitorList() + { + try + { + Thread.Sleep(500); + + var visitors = VisitorsOnlineApi.Instance.GetVisitorsOnline(PortalSettings.PortalId); + + //agent nabayd khodesh be onvane visitor bebinad + //visitors = visitors.Except(visitors.Where(v => v.UserID == UserInfo.UserID)); + + var incomingLiveChats = LiveChatManager.Instance.GetIncomingLiveChats(PortalSettings.PortalId); + + var currentLiveChats = LiveChatManager.Instance.GetCurrentLiveChats(PortalSettings.PortalId); + + var result = from v in visitors + join i in incomingLiveChats on v.VisitorGUID equals i.VisitorGUID into al + from f in al.DefaultIfEmpty() + join c in currentLiveChats on v.VisitorGUID equals c.VisitorGUID into r + from cc in r.DefaultIfEmpty() + select new + { + VisitorID = v.VisitorID, + VisitorGUID = v.VisitorGUID, + PortalID = v.PortalID, + UserName = v.UserName, + DisplayName = v.DisplayName, + Email = v.Email, + OnlineDate = v.OnlineDate, + IP = v.IP, + UserAgent = v.UserAgent, + LastURL = v.LastURL, + ReferrerURL = v.ReferrerURL, + TotalConnections = v.TotalConnections, + UserID = v.UserID, + IncomingLiveChat = (f == null ? false : true), + CurrentLiveChat = (cc == null ? false : true), + Message = (f == null ? string.Empty : f.VisitorMessage) + }; + + return Request.CreateResponse(HttpStatusCode.OK, result); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + #endregion + + #region Department + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetDepartments() + { + try + { + var departments = DepartmentManager.Instance.GetDepartmentsViewModel(PortalSettings.PortalId); + return Request.CreateResponse(HttpStatusCode.OK, departments); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetNamesOfDepartments() + { + try + { + var departments = DepartmentManager.Instance.GetDepartmentsViewModel(PortalSettings.PortalId); + var result = from department in departments select department.DepartmentName; + return Request.CreateResponse(HttpStatusCode.OK, result); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage SearchDepartments(string filter) + { + try + { + var departments = DepartmentManager.Instance.GetDepartments(PortalSettings.PortalId); + if (filter != null) + departments = departments.Where(d => d.DepartmentName.ToLower().Contains(filter)); + return Request.CreateResponse(HttpStatusCode.OK, departments); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage AddDepartment(DepartmentViewModel department) + { + try + { + var objDepartmentInfo = new DepartmentInfo() + { + PortalID = PortalSettings.PortalId, + DepartmentName = department.DepartmentName, + Description = department.Description, + TicketEnabled = department.TicketEnabled, + LiveChatEnabled = department.LiveChatEnabled, + CreateByUser = UserInfo.UserID, + CreateDate = DateTime.Now + }; + int departmentID = DepartmentManager.Instance.AddDepartment(objDepartmentInfo); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true, DepartmentID = departmentID }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage UpdateDepartment(DepartmentViewModel department) + { + try + { + var objDepartmentInfo = DepartmentManager.Instance.GetDepartment(PortalSettings.PortalId, department.DepartmentID); + objDepartmentInfo.DepartmentName = department.DepartmentName; + objDepartmentInfo.Description = department.Description; + objDepartmentInfo.TicketEnabled = department.TicketEnabled; + objDepartmentInfo.LiveChatEnabled = department.LiveChatEnabled; + DepartmentManager.Instance.UpdateDepartment(objDepartmentInfo); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage DeleteDepartment(PostData postData) + { + try + { + DepartmentManager.Instance.DeleteDepartment(PortalSettings.PortalId, postData.ID); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + + string msg = string.Empty; + if (((System.Data.SqlClient.SqlException)(ex)).Number == 547) + msg = Localization.Instance.GetString(DotNetNuke.Common.Globals.ResolveUrl("~/MyDnnPackage/dnn8contest/Website/DesktopModules/MVC/MyDnnSupport/LiveChat/App_LocalResources/SharedResources"), PortalSettings.CultureCode, "DeleteDepartmentError.Text"); + + return Request.CreateResponse(HttpStatusCode.InternalServerError, msg); + } + } + + #endregion + + #region Agent + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetAgents() + { + try + { + var agents = AgentManager.Instance.GetAgentsViewModel(PortalSettings.PortalId); + return Request.CreateResponse(HttpStatusCode.OK, agents); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetUserByDisplayName(string name) + { + try + { + var users = Common.Instance.GetUsersByDisplayName(PortalSettings.PortalId, name); + return Request.CreateResponse(HttpStatusCode.OK, users); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage SearchAgents(int searchType, string filter) + { + try + { + var agents = AgentManager.Instance.GetAgentsViewModel(PortalSettings.PortalId); + if (searchType == 1 && filter != null) + agents = agents.Where(a => a.DisplayName.ToLower().Contains(filter)); + else if (searchType == 2 && filter != null) + agents = agents.Where(a => a.Departments.Any(d => filter.Split(',').Contains(d))); + + return Request.CreateResponse(HttpStatusCode.OK, agents); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage AddAgent(AgentViewModel agent) + { + try + { + Requires.NotNegative("agent.UserID", agent.UserID); + + var user = DotNetNuke.Entities.Users.UserController.GetUserById(PortalSettings.PortalId, agent.UserID); + + var objAgentInfo = new AgentInfo() + { + PortalID = PortalSettings.PortalId, + UserID = agent.UserID, + Priority = agent.Priority, + Enabled = agent.Enabled, + CreateByUser = UserInfo.UserID, + CreateDate = DateTime.Now + }; + int agentID = AgentManager.Instance.AddAgent(objAgentInfo); + agent.AgentID = agentID; + + var role = RoleController.Instance.GetRoleByName(PortalSettings.PortalId, "MyDnnSupportAgent"); + RoleController.AddUserRole(user, role, PortalSettings, DotNetNuke.Security.Roles.RoleStatus.Approved, DateTime.Now, DateTime.Now.AddYears(100), true, false); + + var departments = DepartmentManager.Instance.GetDepartments(PortalSettings.PortalId); + foreach (var item in agent.Departments) + { + var department = departments.FirstOrDefault(d => d.DepartmentName == item); + if (department == null) continue; + var objDepartmentAgentInfo = new DepartmentAgentInfo() + { + DepartmentID = department.DepartmentID, + AgentID = agentID, + UserID = agent.UserID + }; + DepartmentAgentManager.Instance.AddDepartmentAgent(objDepartmentAgentInfo); + } + + agent.Email = user.Email; + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true, Agent = agent }); + } + catch (Exception ex) + { + Logger.Error(ex); + + string msg = ex.Message; + + if (((System.Data.SqlClient.SqlException)(ex)).Number == 2627) // user entekhab shode ghablan dar system be onvane agent sabt shode ast + msg = string.Format(Localization.Instance.GetString(DotNetNuke.Common.Globals.ResolveUrl("~/MyDnnPackage/dnn8contest/Website/DesktopModules/MVC/MyDnnSupport/LiveChat/App_LocalResources/SharedResources"), PortalSettings.CultureCode, "DuplicateAgent.Text"), agent.DisplayName); + + return Request.CreateResponse(HttpStatusCode.InternalServerError, msg); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage UpdateAgent(AgentViewModel agent) + { + try + { + var objAgentInfo = AgentManager.Instance.GetAgent(PortalSettings.PortalId, agent.AgentID); + objAgentInfo.PortalID = PortalSettings.PortalId; + objAgentInfo.Priority = agent.Priority; + objAgentInfo.Enabled = agent.Enabled; + AgentManager.Instance.UpdateAgent(objAgentInfo); + + DepartmentAgentManager.Instance.DeleteAgentDepartments(agent.AgentID); + var departments = DepartmentManager.Instance.GetDepartments(PortalSettings.PortalId); + foreach (var item in agent.Departments) + { + var department = departments.FirstOrDefault(d => d.DepartmentName == item); + if (department == null) continue; + var objDepartmentAgentInfo = new DepartmentAgentInfo() + { + DepartmentID = department.DepartmentID, + AgentID = agent.AgentID, + UserID = agent.UserID + }; + DepartmentAgentManager.Instance.AddDepartmentAgent(objDepartmentAgentInfo); + } + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage DeleteAgent(PostData postData) + { + try + { + DepartmentAgentManager.Instance.DeleteAgentDepartments(postData.ID); + AgentManager.Instance.DeleteAgent(PortalSettings.PortalId, postData.ID); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + #endregion + + #region LiveChat + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetIncomingLiveChats() + { + try + { + var incomingLiveChats = LiveChatManager.Instance.GetIncomingLiveChats(PortalSettings.PortalId); + return Request.CreateResponse(HttpStatusCode.OK, incomingLiveChats); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetChatHistory(int type, string departments, string agents, string visitorEmail, DateTime? fromDate, DateTime? toDate, int rating, bool unread, int pageIndex, int pageSize, int totalCount) + { + try + { + var result = LiveChatManager.Instance.GetChatHistory(PortalSettings.PortalId, type, departments, agents, visitorEmail, fromDate, toDate, rating, unread, pageIndex, pageSize, totalCount); + + int pageCount = (int)Math.Ceiling((double)result.TotalCount / pageSize); + + var paging = new + { + PageIndex = result.PageIndex, + PageSize = result.PageSize, + PageCount = pageCount, + TotalCount = result.TotalCount, + HasNextPage = result.HasNextPage, + HasPreviousPage = result.HasPreviousPage, + IsFirstPage = result.IsFirstPage, + IsLastPage = result.IsLastPage, + Pages = new int[pageCount] + }; + return Request.CreateResponse(HttpStatusCode.OK, new { LiveChats = result, Paging = paging }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + [HttpPost] + public HttpResponseMessage PurgeHistory(HistoryDTO postData) + { + try + { + LiveChatManager.Instance.PurgeHistory(postData.Items); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetMessages(int livechatID) + { + try + { + var messages = LiveChatMessageManager.Instance.GetMessages(livechatID); + + return Request.CreateResponse(HttpStatusCode.OK, new { Messages = messages }); + + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetBasicSettings() + { + try + { + Hashtable moduleSettings = null; + Hashtable portalSettings = new Hashtable(); + + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + if (moduleID > 0) + { + var moduleInfo = new ModuleController().GetModule(moduleID); + moduleSettings = moduleInfo.ModuleSettings; + + portalSettings.Add("VisitorsOnlineEnabled", PortalController.GetPortalSetting("MyDnnVisitorsOnlineEnabled", PortalSettings.PortalId, "false")); + portalSettings.Add("LiveChatEnabled", PortalController.GetPortalSetting("MyDnnLiveChatEnabled", PortalSettings.PortalId, "false")); + } + + return Request.CreateResponse(HttpStatusCode.OK, new + { + PortalSettings = portalSettings, + ModuleSettings = moduleSettings + }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage UpdateBasicSettings(BasicSettingsDTO postData) + { + try + { + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "MyDnnVisitorsOnlineEnabled", postData.PortalSettings["VisitorsOnlineEnabled"].ToString(), true); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "MyDnnLiveChatEnabled", postData.PortalSettings["LiveChatEnabled"].ToString(), true); + + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + + Requires.NotNegative("moduleID", moduleID); + + ModuleController.Instance.UpdateModuleSetting(moduleID, "UpdateBasicSettings", "True"); + + ModuleController.Instance.UpdateModuleSetting(moduleID, "AgentDefaultAvatar", Globals.ResolveUrl("~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/images/agent-avatar.png")); + ModuleController.Instance.UpdateModuleSetting(moduleID, "VisitorDefaultAvatar", Globals.ResolveUrl("~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/images/visitor-avatar.png")); + + ModuleController.Instance.UpdateModuleSetting(moduleID, "PlaySoundWhenNewMsg", postData.ModuleSettings["PlaySoundWhenNewMsg"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "ShowDekstopNotificationForIncoming", postData.ModuleSettings["ShowDekstopNotificationForIncoming"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "ShowDekstopNotificationForNewMsg", postData.ModuleSettings["ShowDekstopNotificationForNewMsg"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "AgentsViewPermission", postData.ModuleSettings["AgentsViewPermission"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "SendEmailForOffline", postData.ModuleSettings["SendEmailForOffline"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "SendEmailAfterChat", postData.ModuleSettings["SendEmailAfterChat"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "TranscriptEmailTemplate", postData.ModuleSettings["TranscriptEmailTemplate"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "OfflineEmailTemplate", postData.ModuleSettings["OfflineEmailTemplate"].ToString()); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetWidgetSettings() + { + try + { + string template = string.Empty; + string liveChatWidget = string.Empty; + Hashtable Settings = null; + + var livechatEnabled = bool.Parse(PortalController.GetPortalSetting("MyDnnLiveChatEnabled", PortalSettings.PortalId, "false")); + if (livechatEnabled) + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + if (moduleID > 0) + { + var moduleInfo = new ModuleController().GetModule(moduleID); + Settings = moduleInfo.ModuleSettings; + template = (Settings["Template"] != null ? Settings["Template"].ToString() : "default"); + liveChatWidget = Common.GetFileContent(HttpContext.Current.Request.MapPath(Globals.ResolveUrl(string.Format("~/DesktopModules/MVC/MyDnnSupport/LiveChat/Templates/{0}/view.html", template)))); + } + } + + return Request.CreateResponse(HttpStatusCode.OK, new + { + Template = template, + Settings = Settings, + LiveChatWidget = liveChatWidget + }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage UpdateWidgetSettings(WidgetSettingsDTO postData) + { + try + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + + Requires.NotNegative("moduleID", moduleID); + + ModuleController.Instance.UpdateModuleSetting(moduleID, "UpdateWidgetSettings", "True"); + + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatThemeColor", postData.WidgetSettings["LiveChatThemeColor"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatTitleColor", postData.WidgetSettings["LiveChatTitleColor"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatWindowSize", postData.WidgetSettings["LiveChatWindowSize"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatWidgetPosition", postData.WidgetSettings["LiveChatWidgetPosition"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatEnableRating", postData.WidgetSettings["LiveChatEnableRating"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatShowAvatar", postData.WidgetSettings["LiveChatShowAvatar"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMessageStyle", postData.WidgetSettings["LiveChatMessageStyle"].ToString()); + + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnOnline", postData.MinButtonSettings["OnlineButton"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnOnlineBgColor", postData.MinButtonSettings["OnlineButtonBGColor"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnOnlineColor", postData.MinButtonSettings["OnlineButtonColor"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnOffline", postData.MinButtonSettings["OfflineButton"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnOfflineBgColor", postData.MinButtonSettings["OfflineButtonBGColor"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnOfflineColor", postData.MinButtonSettings["OfflineButtonColor"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnHPos", postData.MinButtonSettings["HorizontalPosition"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnVPos", postData.MinButtonSettings["VerticalPosition"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnRotate", postData.MinButtonSettings["Rotate"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnCssStyle", postData.MinButtonSettings["CssStyle"].ToString()); + ModuleController.Instance.UpdateModuleSetting(moduleID, "LiveChatMinBtnHtmlTemplate", postData.MinButtonSettings["HtmlTemplate"].ToString().Replace("ng-hide", string.Empty)); + + Localization.Instance.UpdateStrings("~/DesktopModules/MVC/MyDnnSupport/LiveChat/App_LocalResources/SharedResources", PortalSettings.CultureCode, postData.Locales); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + [HttpPost] + public HttpResponseMessage SendEmail(EmailDTO postData) + { + try + { + DotNetNuke.Services.Mail.Mail.SendEmail(PortalSettings.Email, postData.To, postData.Subject, postData.Body); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + #endregion + + #endregion + } +} \ No newline at end of file diff --git a/LiveChat/Services/VisitorServiceController.cs b/LiveChat/Services/VisitorServiceController.cs new file mode 100644 index 0000000..8149411 --- /dev/null +++ b/LiveChat/Services/VisitorServiceController.cs @@ -0,0 +1,320 @@ +using DotNetNuke.Security; +using DotNetNuke.Web.Api; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Web; +using System.Web.Http; +using System.Collections; +using DotNetNuke.Common; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Users.Internal; +using System.Globalization; +using System.Resources; +using System.Xml; +using System.Web.Script.Serialization; +using System.IO; +using System.Threading; +using MyDnn.Modules.Support.LiveChat.Components.Common; +using MyDnn.VisitorsOnline.Api; +using MyDnn.Modules.Support.LiveChat.Components; +using MyDnn.Modules.Support.LiveChat.ViewModels; +using MyDnn.Modules.Support.LiveChats.ViewModels; +using MyDnn.Modules.Support.LiveChat.Models; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Modules; +using System.Text.RegularExpressions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Instrumentation; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Mail; + +namespace MyDnn.Modules.Support.LiveChat.Services +{ + #region DTO Models + + /// + /// + /// + public class DepartmentDTO + { + public int DepartmentID { get; set; } + public string DepartmentName { get; set; } + public bool IsAgentOnline { get; set; } + } + + /// + /// + /// + public class EmailDTO + { + public int DepartmentID { get; set; } + public string To { get; set; } + public string Subject { get; set; } + public string Body { get; set; } + } + + #endregion + + /// + /// + /// + [AllowAnonymous] + public class VisitorServiceController : DnnApiController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(VisitorServiceController)); + + #region WebApi Methods + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage LiveChatWidget() + { + try + { + string liveChatMinButton = string.Empty; + bool isAgentOnline = false; + string template = string.Empty; + bool isAgent = false; + string requestsString = string.Empty; + string adminPanelUrl = string.Empty; + + var livechatEnabled = bool.Parse(PortalController.GetPortalSetting("MyDnnLiveChatEnabled", PortalSettings.PortalId, "false")); + if (livechatEnabled) + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + if (moduleID > 0) + { + isAgentOnline = AgentManager.Instance.IsAgentOnline(PortalSettings.PortalId); + + var moduleInfo = new ModuleController().GetModule(moduleID); + var Settings = moduleInfo.ModuleSettings; + liveChatMinButton = (Settings["LiveChatMinBtnHtmlTemplate"] != null ? Settings["LiveChatMinBtnHtmlTemplate"].ToString() : string.Empty); + template = (Settings["Template"] != null ? Settings["Template"].ToString() : "default"); + + if (UserInfo.UserID != -1) + { + isAgent = AgentManager.Instance.GetAgentByUserName(PortalSettings.PortalId, UserInfo.Username) != null; + if (isAgent) + { + requestsString = Localization.Instance.GetString("~/DesktopModules/MVC/MyDnnSupport/LiveChat/App_LocalResources/SharedResources", PortalSettings.CultureCode, "ServeRequests.Text"); + adminPanelUrl = DotNetNuke.Common.Globals.NavigateURL(moduleInfo.TabID, PortalSettings, "AdminPanel", "mid", moduleInfo.ModuleID.ToString(), "popUp", "true"); + } + } + } + } + + return Request.CreateResponse(HttpStatusCode.OK, new + { + RootUrl = DotNetNuke.Common.Globals.ResolveUrl("~/"), + PortalID = PortalSettings.PortalId, + Template = template, + LiveChatEnabled = livechatEnabled, + LiveChatMinButton = liveChatMinButton, + IsAgentOnline = isAgentOnline, + IsAgent = isAgent, + RequestsString = requestsString, + AdminPanelUrl = adminPanelUrl + }); + } + catch (Exception ex) + { + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetResources(string resource) + { + var result = Localization.Instance.GetResources(resource, CultureInfo.CurrentCulture.ToString()); + + return Request.CreateResponse(HttpStatusCode.OK, result); + } + + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage InitialLiveChat(string visitorGUID) + { + try + { + var moduleID = int.Parse(PortalController.GetPortalSetting("MyDnnLiveChatModuleID", PortalSettings.PortalId, "-1")); + + Requires.NotNegative("moduleID", moduleID); + + var Settings = new ModuleController().GetModule(moduleID).ModuleSettings; + + string template = (Settings["Template"] != null ? Settings["Template"].ToString() : "default"); + string liveChatWidget = Common.GetFileContent(HttpContext.Current.Request.MapPath(Globals.ResolveUrl(string.Format("~/DesktopModules/MVC/MyDnnSupport/LiveChat/Templates/{0}/view.html", template)))); + + var resources = Localization.Instance.GetResources(string.Format("~/DesktopModules/MVC/MyDnnSupport/LiveChat/App_LocalResources/SharedResources"), CultureInfo.CurrentCulture.ToString()); + + bool isAgentOnline = false; + + var departments = GetDepartments(out isAgentOnline); + + return Request.CreateResponse(HttpStatusCode.OK, new + { + PortalID = PortalSettings.PortalId, + Resources = resources, + Departments = departments, + Settings = Settings, + Template = template, + Widget = liveChatWidget, + UserID = UserInfo.UserID, + DisplayName = (UserInfo.UserID != -1 ? UserInfo.DisplayName : string.Empty), + Email = (UserInfo.UserID != -1 ? UserInfo.Email : string.Empty), + }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage GetDepartmentsForLiveChat() + { + try + { + bool isAgentOnline = false; + var departments = GetDepartments(out isAgentOnline); + + return Request.CreateResponse(HttpStatusCode.OK, new { Departments = departments, IsAgentOnline = isAgentOnline }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpGet] + public HttpResponseMessage IsAgentOnlineByDepartment(int departmentID) + { + try + { + var isAgentOnline = DepartmentAgentManager.Instance.IsAgentOnlineByDepartment(PortalSettings.PortalId, departmentID); + return Request.CreateResponse(HttpStatusCode.OK, isAgentOnline); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage SendEmail(EmailDTO postData) + { + try + { + Mail.SendEmail(PortalSettings.Email, postData.To, postData.Subject, postData.Body); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + /// + /// + /// + /// + /// + [HttpPost] + public HttpResponseMessage SendOfflineMessageEmail(EmailDTO postData) + { + try + { + var agents = DepartmentAgentManager.Instance.GetDepartmentAgents(postData.DepartmentID); + foreach (var agent in agents) + { + var user = UserController.GetUserById(PortalSettings.PortalId, agent.UserID); + if (user != null) + Mail.SendEmail(PortalSettings.Email, user.Email, postData.Subject, postData.Body); + } + + if (agents == null || !agents.Any()) + Mail.SendEmail(PortalSettings.Email, PortalSettings.Email, postData.Subject, postData.Body); + + return Request.CreateResponse(HttpStatusCode.OK, new { Success = true }); + } + catch (Exception ex) + { + Logger.Error(ex); + return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); + } + } + + + #endregion + + #region Private Methods + + /// + /// + /// + /// + /// + private List GetDepartments(out bool isAgentOnline) + { + isAgentOnline = false; + + List departments = new List(); + var usersOnline = VisitorsOnlineApi.Instance.GetVisitorsOnline(PortalSettings.PortalId); + var deps = DepartmentManager.Instance.GetDepartmentsForLiveChat(PortalSettings.PortalId); + foreach (DepartmentInfo dep in deps) + { + var department = new DepartmentDTO() + { + DepartmentID = dep.DepartmentID, + DepartmentName = dep.DepartmentName, + IsAgentOnline = false + }; + var agents = DepartmentAgentManager.Instance.GetDepartmentAgents(dep.DepartmentID); + if (usersOnline != null && agents != null) + { + isAgentOnline = usersOnline.Any(u => agents.Select(a => a.UserID).Contains(u.UserID)); + department.IsAgentOnline = isAgentOnline; + } + departments.Add(department); + } + + return departments; + } + + #endregion + } +} \ No newline at end of file diff --git a/LiveChat/Styles/animate.min.css b/LiveChat/Styles/animate.min.css new file mode 100644 index 0000000..86ce696 --- /dev/null +++ b/LiveChat/Styles/animate.min.css @@ -0,0 +1 @@ +@charset "UTF-8";/*!Animate.css - http://daneden.me/animate Licensed under the MIT license -http://opensource.org/licenses/MIT Copyright (c) 2015 Daniel Eden*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut{-webkit-animation-duration:.75s;animation-duration:.75s}.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{0%,20%,53%,80%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,20%,53%,80%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);animation-timing-function:cubic-bezier(0.755,0.050,0.855,0.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,0.75,1);transform:scale3d(1.25,0.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,0.85,1);transform:scale3d(1.15,0.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,0.75,1);transform:scale3d(1.25,0.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,0.85,1);transform:scale3d(1.15,0.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}@keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes jello{11.1%{-webkit-transform:none;transform:none}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-0.78125deg) skewY(-0.78125deg);transform:skewX(-0.78125deg) skewY(-0.78125deg)}77.7%{-webkit-transform:skewX(0.390625deg) skewY(0.390625deg);transform:skewX(0.390625deg) skewY(0.390625deg)}88.8%{-webkit-transform:skewX(-0.1953125deg) skewY(-0.1953125deg);transform:skewX(-0.1953125deg) skewY(-0.1953125deg)}100%{-webkit-transform:none;transform:none}}@keyframes jello{11.1%{-webkit-transform:none;transform:none}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-0.78125deg) skewY(-0.78125deg);transform:skewX(-0.78125deg) skewY(-0.78125deg)}77.7%{-webkit-transform:skewX(0.390625deg) skewY(0.390625deg);transform:skewX(0.390625deg) skewY(0.390625deg)}88.8%{-webkit-transform:skewX(-0.1953125deg) skewY(-0.1953125deg);transform:skewX(-0.1953125deg) skewY(-0.1953125deg)}100%{-webkit-transform:none;transform:none}}.jello{-webkit-animation-name:jello;animation-name:jello;-webkit-transform-origin:center;transform-origin:center}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInDown{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInRight{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{0%,60%,75%,90%,100%{-webkit-animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000);animation-timing-function:cubic-bezier(0.215,0.610,0.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190);animation-timing-function:cubic-bezier(0.550,0.055,0.675,0.190)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,0.885,0.320,1);animation-timing-function:cubic-bezier(0.175,0.885,0.320,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp} diff --git a/LiveChat/Styles/custom.css b/LiveChat/Styles/custom.css new file mode 100644 index 0000000..5bd44d7 --- /dev/null +++ b/LiveChat/Styles/custom.css @@ -0,0 +1,914 @@ +/* angular styles*/ +input.check-validate.ng-invalid-required { + border-bottom-color: #f44336; + border-bottom-width: 2px; +} + + input.check-validate.ng-invalid-required::-moz-placeholder { + color: #f44336; + } + + input.check-validate.ng-invalid-required::-webkit-input-placeholder { + color: #f44336; + } + + input.check-validate.ng-invalid-required:-ms-input-placeholder { + color: #f44336; + } + + +/* bootstrap styles*/ +.modal { + text-align: center; +} + +@media screen and (min-width: 768px) { + .modal:before { + display: inline-block; + vertical-align: middle; + content: " "; + height: 100%; + } +} + +.modal-dialog { + display: inline-block; + text-align: left; + vertical-align: middle; +} + +.mouse-handle { + cursor: pointer; +} + +.gray-color { + color: #ccc; +} + +.card-body .row-icon { + color: #5e5e5e; + font-size: 23px; + margin-left: 5px; + vertical-align: middle; +} + +table.table tbody td { + vertical-align: middle; +} + +.table th, .table td { + text-overflow: ellipsis; +} + +.right-position { + right: 1px; +} + +.b-radius-5 { + border-radius: 5px; +} + +.font-20 { + font-size: 20px; +} + +.px40 { + width: 40px; +} + +.no-padding-lr { + padding-left: 0 !important; + padding-right: 0 !important; +} + +.pd-tb-5 { + padding-top: 5px !important; + padding-bottom: 5px !important; +} + +.pd-tb-15 { + padding-top: 15px !important; + padding-bottom: 15px !important; +} + +.mg-r-5 { + margin-right: 5px; +} + +.mg-b-10 { + margin-bottom: 10px !important; +} + +.no-box-shadow { + box-shadow: none !important; +} + +.f-12 { + font-size: 12px !important; +} + +.wh-33 { + height: 33px !important; + width: 33px !important; +} + +.w-50 { + width: 50px !important; +} + +.w-100 { + width: 100px !important; +} + +.w-120 { + width: 120px !important; +} + +.w-150 { + width: 150px !important; +} + +.w-200 { + width: 200px !important; +} + +.w-300 { + width: 300px !important; +} + +.w-400 { + width: 400px !important; +} + +.w-500 { + width: 500px !important; +} + +.w-600 { + width: 500px !important; +} + +.m-w-200 { + max-width: 200px !important; +} + +.m-w-300 { + max-width: 300px !important; +} + +.m-h-400 { + min-height: 400px !important; +} + +.rsize { + resize: both !important; +} + +.text-center { + text-align: center; +} + +.comma-after::after { + content: ","; +} + +.comma-after:last-child::after { + content: none; +} + +.card-header > h2 > i { + font-size: 25px; +} + +.user-prfilepic-wrapper { + border-radius: 30px; + display: block; + float: left; + height: 25px; + margin: 0 6px 0 0; + overflow: hidden; + width: 25px; +} + + .user-prfilepic-wrapper > img { + height: 25px; + width: 100%; + } + +.fg-line input[type="text"].form-control { + background: none; + border: 1px solid #bfbfbf; + border-style: none none solid; + box-shadow: none; + padding: 1px; + margin: 0; +} + +.departments { +} + + .departments .department-agents { + list-style-type: none; + margin: 0; + padding: 0; + } + + .departments .department-agents li { + background: #FBFBFB none repeat scroll 0 0; + float: left; + margin: 0 5px 3px 0; + border-radius: 35px; + padding: 3px; + } + + + + .departments .department-agents li .user-displayname { + float: left; + font-size: 12px; + margin: 4px 5px 0 0; + } + +.agents { +} + + .agents .agent-filter-department { + float: right; + position: absolute; + bottom: 15px; + right: 100px; + width: 300px; + } + + .agents .agent-departments { + list-style-type: none; + margin: 0; + padding: 0; + } + + .agents .agent-departments li { + background: #FBFBFB none repeat scroll 0 0; + float: left; + margin: 0 5px 3px 0; + border-radius: 35px; + padding: 3px 8px; + } + + .agents .agent-departments li .user-displayname { + float: left; + font-size: 12px; + } + +.visitors { +} + + .visitors .search-group { + margin-top: 10px; + } + + .visitors .list-title { + color: #444; + font-family: helvetica; + font-size: 15px; + font-weight: 300; + margin: 5px 10px 0; + } + + .visitors .table { + margin-bottom: 0; + } + + .visitors .table thead th { + color: #bbb; + font-family: helvetica; + font-size: 12px; + font-weight: 700; + } + + .visitors .table .visitor-avatar { + float: left; + border-radius: 50%; + display: inline-block; + height: 35px; + margin: 0 5px 0 0; + overflow: hidden; + width: 35px; + } + + .visitors .table .visitor-avatar > img { + border-radius: 50%; + max-height: 35px; + width: 100%; + } + + .visitors .table .visitor-name { + color: #555; + float: left; + font-size: 12px; + font-weight: bold; + height: 30px; + line-height: 30px; + margin-right: 5px; + overflow: hidden; + text-overflow: ellipsis; + width: 150px; + } + + .visitors .table .visitor-name > span { + white-space: pre; + } + + .visitors .table .visitor-country { + display: inline-block; + float: left; + height: 11px; + margin: 10px 10px 0 0; + opacity: 0.5; + } + + .visitors .table .visitor-os { + background-image: url("images/os.png"); + background-position: -110px 0; + display: inline-block; + float: left; + height: 16px; + margin: 7px 5px 0 0; + width: 16px; + } + + .visitors .table .visitor-os.Windows { + background-position: 0 0; + } + + .visitors .table .visitor-os.Android { + background-position: -63px 0; + } + + .visitors .table .visitor-os.iOS { + background-position: -45px 0; + } + + .visitors .table .visitor-os.Linux { + background-position: -31px 0; + } + + .visitors .table .visitor-os.Mac { + background-position: -15px 0; + } + + .visitors .table .visitor-browser { + background-image: url("images/browsers.png"); + background-position: -47px 0; + display: inline-block; + float: left; + height: 16px; + margin: 7px 5px 0 0; + width: 16px; + } + + .visitors .table .visitor-browser.Chrome { + background-position: 0 0; + } + + .visitors .table .visitor-browser.Firefox { + background-position: -16px 0; + } + + .visitors .table .visitor-browser.Opera { + background-position: -31px 0; + } + + .visitors .table .visitor-browser.IE, .visitors .visitor-browser.Edge { + background-position: -64px 0; + } + + .visitors .table .visitor-browser.Safari { + background-position: -79px 0; + } + + .visitors .table .visitor-url span { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre; + } + + .visitors .table .visitor-ischatting span { + background: #75985a none repeat scroll 0 0; + border-radius: 3px; + color: #fff; + display: block; + font-size: 11px; + max-width: 85px; + padding: 5px; + text-align: center; + } + +/* Custom Objects*/ + +.drop-down-wrapper { + background: #fff none repeat scroll 0 0; + border: 1px solid #ddd; + border-radius: 5px; + display: inline-block; + outline: medium none; + padding: 5px; + position: relative; +} + + .drop-down-wrapper::before { + color: #999; + content: ""; + font-family: "Material Design Iconic Font"; + font-size: 20px; + margin: 0; + position: absolute; + right: 3px; + top: 2px; + } + + .drop-down-wrapper select { + -moz-appearance: none; + -webkit-appearance: none; + background: transparent none repeat scroll 0 0; + border: none; + box-shadow: none; + outline: none; + padding: 0; + margin: 0; + } + +.cust-sel { + background: #fff none repeat scroll 0 0; + border: 1px solid #ddd; + border-radius: 5px; + display: inline-block; + max-width: 300px; + min-height: 30px; + min-width: 220px; + outline: medium none; + padding: 3px 7px; + position: relative; +} + + .cust-sel::before { + color: #999; + content: ""; + font-family: "Material Design Iconic Font"; + font-size: 20px; + margin: 0; + position: absolute; + right: 3px; + top: 0; + } + + .cust-sel .chosen-container-multi .chosen-choices { + border: none; + } + + .cust-sel .chosen-container-multi .chosen-choices li.search-choice { + font-size: 12px; + font-weight: 400; + line-height: 17px; + margin: 0 5px 0 0; + padding: 4px 25px 1px 7px; + } + + .cust-sel .chosen-container-multi .chosen-choices li.search-choice .search-choice-close { + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + right: 7px; + top: 3px; + } + + .cust-sel .chosen-container-multi .chosen-choices li.search-field > input[type="text"] { + height: 20px; + } + + .cust-sel .chosen-container-single::before { + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + } + + .cust-sel .chosen-container-single .chosen-single { + height: 26px; + } + + .cust-sel .chosen-container .chosen-drop { + top: 25px; + } + + .cust-sel select.form-control { + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + border: medium none; + height: 23px; + line-height: normal; + padding: 0; + width: 100%; + } + +.cust-input { + -moz-appearance: none; + -webkit-appearance: none; + background: #fff none repeat scroll 0 0 !important; + border: solid 1px#ddd !important; + border-radius: 5px !important; + box-shadow: none !important; + color: #333 !important; + display: block; + font-size: 12px; + font-style: normal; + margin: 0 !important; + padding: 6px !important; + width: 100%; + resize: none; +} + +.search-group { + background: #fff none repeat scroll 0 0; + border: 1px solid #ddd; + border-radius: 5px; + line-height: normal; + padding: 5px; + width: 200px; +} + + .search-group > input[type="text"] { + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + border: medium none; + box-shadow: none; + font-size: 12px; + line-height: normal; + margin: 0; + padding: 0 0 0 2px; + width: 168px; + } + + .search-group > i { + font-size: 15px; + color: #bebebe; + } + +.input-group { + width: 217px; +} + +.custom-tabs { + display: list-item; + float: left; + list-style: none; + margin: 0; + padding: 0; +} + + .custom-tabs > li { + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + border-color: #ddd; + border-image: none; + border-style: solid; + border-width: 1px 1px 1px 0; + box-shadow: 1px 0 rgba(255, 255, 255, 1) inset, 0 1px 0 rgba(0, 0, 0, 0.05); + color: #666666; + cursor: pointer; + display: inline-block; + float: left; + font-size: 11px; + font-weight: bold; + line-height: 22px; + list-style: none; + padding: 2px 12px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + } + + .custom-tabs > li.active { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #dfdfdf, #d7d7d7) repeat scroll 0 0; + border-top: 1px solid #bbb; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) inset, 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 0 rgba(255, 255, 255, 0.5); + color: #666; + cursor: default; + } + + .custom-tabs > li:first-child { + border-left: 1px solid #d9d9d9; + border-radius: 5px 0 0 5px; + } + + .custom-tabs > li:last-child { + border-radius: 0 5px 5px 0; + } + +.history { + min-width: 920px; +} + + .history .advanced-search { + height: 35px; + transition: all 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; + width: 100%; + display: none; + } + + .history .selected-livechat { + border-left: 1px solid #ddd; + box-sizing: border-box; + padding: 10px !important; + min-height: 400px; + max-height: 450px; + overflow-y: auto; + } + + .history .close-livechat { + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + position: absolute; + right: 10px; + top: 10px; + width: 25px; + height: 25px; + line-height: 20px; + z-index: 99; + } + + .history .close-livechat:hover { + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + } + + .history .close-livechat > i { + color: #666; + font-size: 12px; + } + + .history .split { + border-bottom: dashed 1px #ddd; + } + + .history .messages { + margin: 0; + padding: 0; + } + + .history .messages .message-body { + font-size: 13px; + list-style: outside none none; + margin: 5px 0; + padding-bottom: 5px; + position: relative; + } + + .history .messages .message-body.message-0 { + color: #999999; + font-style: italic; + font-weight: 300; + text-align: center; + } + + .history .messages .message-body .sender { + display: block; + font-weight: 700; + } + + .history .messages .message-body .message { + margin: 0; + width: 90%; + } + + .history .messages .message-body .time { + color: #888; + font-style: initial; + position: absolute; + right: 5px; + top: 2px; + } + + .history .userinfo { + box-sizing: border-box; + height: 100%; + padding: 12px 10px; + } + + .history .userinfo .visitor-avatar { + background: url(images/visitor-avatar.png) no-repeat center center #314f7f; + border-radius: 5px; + display: inline-block; + float: left; + height: 50px; + margin: -2px 5px 0 0; + overflow: hidden; + padding: 0; + width: 50px; + } + + .history .userinfo .visitor-avatar img { + height: 100%; + max-width: 60px; + } + + .history .userinfo .visitor-displayname { + color: #333333; + display: block; + font-size: 18px; + line-height: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .history .userinfo .visitor-email { + color: #576263; + display: block; + font-size: 12px; + margin-top: 2px; + text-overflow: ellipsis; + } + + .history .userinfo .split { + border-top: 1px solid #e5e5e5; + box-shadow: 0 1px rgba(255, 255, 255, 0.65) inset; + padding: 10px 0; + } + + .history .userinfo .statistics { + display: table; + margin: 15px 0 0; + padding: 15px 0 0; + text-transform: uppercase; + width: 100%; + } + + .history .userinfo .statistics.split > li { + background: #fafafa none repeat scroll 0 0; + border: 1px solid #e5e5e5; + border-radius: 0; + color: #888; + float: left; + font-size: 10px; + list-style: outside none none; + margin: 0; + padding: 10px; + width: 33%; + } + + .history .userinfo .statistics.split > li:first-child { + border-left: 1px solid #e5e5e5; + border-radius: 3px 0 0 3px; + border-right: medium none; + } + + .history .userinfo .statistics.split > li:last-child { + border-left: medium none; + border-radius: 0 3px 3px 0; + width: 34%; + } + + .history .userinfo .statistics.split > li .val { + color: #222; + display: block; + font-size: 15px; + font-weight: bold; + text-transform: none; + } + + .history .userinfo .sideinfo { + background: #fafafa none repeat scroll 0 0; + border: 1px solid #e5e5e5; + box-sizing: border-box; + font-size: 12px; + margin-top: 10px; + padding: 10px; + width: 100%; + } + + .history .userinfo .sideinfo > h5 { + color: #888; + font-size: 10px; + margin: 10px 0 3px; + } + + .history .userinfo .sideinfo > h5:first-child { + margin-top: 0; + } + + .history .userinfo .sideinfo .val { + color: #222; + font-size: 12px; + } + + .history .table > tbody > tr:hover { + background-color: #f4f4f4; + cursor: pointer; + } + +.b-p { + border: 1px solid #ddd; + border-radius: 5px; + padding: 5px 10px 2px !important; +} + + .b-p label { + font-size: 12px; + font-weight: 400; + line-height: 20px; + } + + .b-p .toggle-switch .ts-helper::before { + height: 20px; + width: 20px; + } + + .b-p .toggle-switch .ts-helper { + height: 13px; + margin-top: 4px; + width: 40px; + } + +.basic-settings .form-group > label { + color: #333; + font-size: 13px; + font-weight: normal; +} + +.widget-settings .btn-on-off { + border: 1px solid #ddd; + border-radius: 3px; + box-shadow: none; + overflow: hidden; + position: absolute; + right: 15px; + top: 15px; +} + +.widget-settings .split { + border-bottom: dashed 1px #ddd; +} + +.widget-settings .form-group > label { + color: #333; + font-size: 13px; + font-weight: normal; +} + +.widget-settings label.btn { + padding: 4px 10px; + text-transform: capitalize; + font-weight: normal; + font-size: 12px; +} + +.widget-settings label.btn-default.active { + color: #fff; + background-color: #2196f3; + border-color: #0d8aee; +} + +.widget-settings i.tab-icon { + font-size: 19px; + line-height: 19px; + margin-right: 4px; +} + +.head { + box-shadow: 0 -2px 0 0 #eeeeee inset; + margin: 10px 0 20px; +} + + .head > h3 { + border-bottom: 2px solid #4caf50; + display: inline-block; + font-size: 20px; + margin: 0; + padding: 0 0 10px; + } + +tr:nth-of-type(5) td:nth-of-type(1) { + visibility: hidden; +} + +.rotate { + /* FF3.5+ */ + -moz-transform: rotate(-90.0deg); + /* Opera 10.5 */ + -o-transform: rotate(-90.0deg); + /* Saf3.1+, Chrome */ + -webkit-transform: rotate(-90.0deg); + /* IE6,IE7 */ + filter: progid: DXImageTransform.Microsoft.BasicImage(rotation=0.083); + /* IE8 */ + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; + /* Standard */ + transform: rotate(-90.0deg); +} + +.custom-fix-alerts { + position: fixed; + right: 10px; + z-index: 9999999; +} + + .custom-fix-alerts a { + color: #fff; + display: block; + } + +.livechat-minbutton.lhidden-true { + display: none; +} diff --git a/LiveChat/Styles/fonts/Material-Design-Iconic-Font.eot b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.eot new file mode 100644 index 0000000..df3fa77 Binary files /dev/null and b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.eot differ diff --git a/LiveChat/Styles/fonts/Material-Design-Iconic-Font.svg b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.svg new file mode 100644 index 0000000..9874501 --- /dev/null +++ b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.svg @@ -0,0 +1,773 @@ + + + + + +{ + "fontFamily": "Material-Design-Iconic-Font", + "majorVersion": 1, + "minorVersion": 0, + "fontURL": "http://zavoloklom.github.io/material-design-iconic-font/", + "description": "Material Design Iconic Font is a full suite of material design icons (created and maintained by Google) for easy scalable vector graphics on websites.\nFont generated by IcoMoon.", + "copyright": "CSS: Kupletsky Sergey, Icons: Google", + "designerURL": "http://zavoloklom.github.io/", + "license": "Attribution-ShareAlike 4.0 International license", + "licenseURL": "http://creativecommons.org/licenses/by-sa/4.0/", + "version": "Version 1.0", + "fontId": "Material-Design-Iconic-Font", + "psName": "Material-Design-Iconic-Font", + "subFamily": "Regular", + "fullName": "Material-Design-Iconic-Font" +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LiveChat/Styles/fonts/Material-Design-Iconic-Font.ttf b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.ttf new file mode 100644 index 0000000..b41cdc3 Binary files /dev/null and b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.ttf differ diff --git a/LiveChat/Styles/fonts/Material-Design-Iconic-Font.woff b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.woff new file mode 100644 index 0000000..ccca1b0 Binary files /dev/null and b/LiveChat/Styles/fonts/Material-Design-Iconic-Font.woff differ diff --git a/LiveChat/Styles/fonts/Roboto-Bold-webfont.eot b/LiveChat/Styles/fonts/Roboto-Bold-webfont.eot new file mode 100644 index 0000000..b73776e Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Bold-webfont.eot differ diff --git a/LiveChat/Styles/fonts/Roboto-Bold-webfont.svg b/LiveChat/Styles/fonts/Roboto-Bold-webfont.svg new file mode 100644 index 0000000..47e9b8c --- /dev/null +++ b/LiveChat/Styles/fonts/Roboto-Bold-webfont.svg @@ -0,0 +1,593 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LiveChat/Styles/fonts/Roboto-Bold-webfont.ttf b/LiveChat/Styles/fonts/Roboto-Bold-webfont.ttf new file mode 100644 index 0000000..1da7276 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Bold-webfont.ttf differ diff --git a/LiveChat/Styles/fonts/Roboto-Bold-webfont.woff b/LiveChat/Styles/fonts/Roboto-Bold-webfont.woff new file mode 100644 index 0000000..0c69948 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Bold-webfont.woff differ diff --git a/LiveChat/Styles/fonts/Roboto-Light-webfont.eot b/LiveChat/Styles/fonts/Roboto-Light-webfont.eot new file mode 100644 index 0000000..072cdc4 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Light-webfont.eot differ diff --git a/LiveChat/Styles/fonts/Roboto-Light-webfont.svg b/LiveChat/Styles/fonts/Roboto-Light-webfont.svg new file mode 100644 index 0000000..e6b31ca --- /dev/null +++ b/LiveChat/Styles/fonts/Roboto-Light-webfont.svg @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LiveChat/Styles/fonts/Roboto-Light-webfont.ttf b/LiveChat/Styles/fonts/Roboto-Light-webfont.ttf new file mode 100644 index 0000000..3b2fea0 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Light-webfont.ttf differ diff --git a/LiveChat/Styles/fonts/Roboto-Light-webfont.woff b/LiveChat/Styles/fonts/Roboto-Light-webfont.woff new file mode 100644 index 0000000..cc534a3 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Light-webfont.woff differ diff --git a/LiveChat/Styles/fonts/Roboto-Medium-webfont.eot b/LiveChat/Styles/fonts/Roboto-Medium-webfont.eot new file mode 100644 index 0000000..f9ad995 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Medium-webfont.eot differ diff --git a/LiveChat/Styles/fonts/Roboto-Medium-webfont.svg b/LiveChat/Styles/fonts/Roboto-Medium-webfont.svg new file mode 100644 index 0000000..2791eac --- /dev/null +++ b/LiveChat/Styles/fonts/Roboto-Medium-webfont.svg @@ -0,0 +1,593 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LiveChat/Styles/fonts/Roboto-Medium-webfont.ttf b/LiveChat/Styles/fonts/Roboto-Medium-webfont.ttf new file mode 100644 index 0000000..8aa64d8 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Medium-webfont.ttf differ diff --git a/LiveChat/Styles/fonts/Roboto-Medium-webfont.woff b/LiveChat/Styles/fonts/Roboto-Medium-webfont.woff new file mode 100644 index 0000000..cd810ef Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Medium-webfont.woff differ diff --git a/LiveChat/Styles/fonts/Roboto-Regular-webfont.eot b/LiveChat/Styles/fonts/Roboto-Regular-webfont.eot new file mode 100644 index 0000000..9b5e8e4 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Regular-webfont.eot differ diff --git a/LiveChat/Styles/fonts/Roboto-Regular-webfont.svg b/LiveChat/Styles/fonts/Roboto-Regular-webfont.svg new file mode 100644 index 0000000..d0379bf --- /dev/null +++ b/LiveChat/Styles/fonts/Roboto-Regular-webfont.svg @@ -0,0 +1,621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LiveChat/Styles/fonts/Roboto-Regular-webfont.ttf b/LiveChat/Styles/fonts/Roboto-Regular-webfont.ttf new file mode 100644 index 0000000..44dd78d Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Regular-webfont.ttf differ diff --git a/LiveChat/Styles/fonts/Roboto-Regular-webfont.woff b/LiveChat/Styles/fonts/Roboto-Regular-webfont.woff new file mode 100644 index 0000000..bfa05d5 Binary files /dev/null and b/LiveChat/Styles/fonts/Roboto-Regular-webfont.woff differ diff --git a/LiveChat/Styles/fonts/glyphicons-halflings-regular.eot b/LiveChat/Styles/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..4a4ca86 Binary files /dev/null and b/LiveChat/Styles/fonts/glyphicons-halflings-regular.eot differ diff --git a/LiveChat/Styles/fonts/glyphicons-halflings-regular.svg b/LiveChat/Styles/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..a022dd9 --- /dev/null +++ b/LiveChat/Styles/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LiveChat/Styles/fonts/glyphicons-halflings-regular.ttf b/LiveChat/Styles/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..67fa00b Binary files /dev/null and b/LiveChat/Styles/fonts/glyphicons-halflings-regular.ttf differ diff --git a/LiveChat/Styles/fonts/glyphicons-halflings-regular.woff b/LiveChat/Styles/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..8c54182 Binary files /dev/null and b/LiveChat/Styles/fonts/glyphicons-halflings-regular.woff differ diff --git a/LiveChat/Styles/fonts/glyphicons-halflings-regular.woff2 b/LiveChat/Styles/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000..8c54182 Binary files /dev/null and b/LiveChat/Styles/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/LiveChat/Styles/images/agent-avatar.png b/LiveChat/Styles/images/agent-avatar.png new file mode 100644 index 0000000..516712b Binary files /dev/null and b/LiveChat/Styles/images/agent-avatar.png differ diff --git a/LiveChat/Styles/images/browsers.png b/LiveChat/Styles/images/browsers.png new file mode 100644 index 0000000..2b96e52 Binary files /dev/null and b/LiveChat/Styles/images/browsers.png differ diff --git a/LiveChat/Styles/images/flags/ad.png b/LiveChat/Styles/images/flags/ad.png new file mode 100644 index 0000000..c58bc93 Binary files /dev/null and b/LiveChat/Styles/images/flags/ad.png differ diff --git a/LiveChat/Styles/images/flags/ae.png b/LiveChat/Styles/images/flags/ae.png new file mode 100644 index 0000000..088ef8e Binary files /dev/null and b/LiveChat/Styles/images/flags/ae.png differ diff --git a/LiveChat/Styles/images/flags/af.png b/LiveChat/Styles/images/flags/af.png new file mode 100644 index 0000000..995b351 Binary files /dev/null and b/LiveChat/Styles/images/flags/af.png differ diff --git a/LiveChat/Styles/images/flags/ag.png b/LiveChat/Styles/images/flags/ag.png new file mode 100644 index 0000000..5f8b4f6 Binary files /dev/null and b/LiveChat/Styles/images/flags/ag.png differ diff --git a/LiveChat/Styles/images/flags/al.png b/LiveChat/Styles/images/flags/al.png new file mode 100644 index 0000000..2e516ec Binary files /dev/null and b/LiveChat/Styles/images/flags/al.png differ diff --git a/LiveChat/Styles/images/flags/am.png b/LiveChat/Styles/images/flags/am.png new file mode 100644 index 0000000..d529a99 Binary files /dev/null and b/LiveChat/Styles/images/flags/am.png differ diff --git a/LiveChat/Styles/images/flags/ao.png b/LiveChat/Styles/images/flags/ao.png new file mode 100644 index 0000000..4cdfb0e Binary files /dev/null and b/LiveChat/Styles/images/flags/ao.png differ diff --git a/LiveChat/Styles/images/flags/ar.png b/LiveChat/Styles/images/flags/ar.png new file mode 100644 index 0000000..b31ec92 Binary files /dev/null and b/LiveChat/Styles/images/flags/ar.png differ diff --git a/LiveChat/Styles/images/flags/at.png b/LiveChat/Styles/images/flags/at.png new file mode 100644 index 0000000..993b903 Binary files /dev/null and b/LiveChat/Styles/images/flags/at.png differ diff --git a/LiveChat/Styles/images/flags/au.png b/LiveChat/Styles/images/flags/au.png new file mode 100644 index 0000000..ef20b66 Binary files /dev/null and b/LiveChat/Styles/images/flags/au.png differ diff --git a/LiveChat/Styles/images/flags/az.png b/LiveChat/Styles/images/flags/az.png new file mode 100644 index 0000000..3fb7ccb Binary files /dev/null and b/LiveChat/Styles/images/flags/az.png differ diff --git a/LiveChat/Styles/images/flags/ba.png b/LiveChat/Styles/images/flags/ba.png new file mode 100644 index 0000000..fa4d609 Binary files /dev/null and b/LiveChat/Styles/images/flags/ba.png differ diff --git a/LiveChat/Styles/images/flags/bb.png b/LiveChat/Styles/images/flags/bb.png new file mode 100644 index 0000000..5e87a9e Binary files /dev/null and b/LiveChat/Styles/images/flags/bb.png differ diff --git a/LiveChat/Styles/images/flags/bd.png b/LiveChat/Styles/images/flags/bd.png new file mode 100644 index 0000000..c55d3d7 Binary files /dev/null and b/LiveChat/Styles/images/flags/bd.png differ diff --git a/LiveChat/Styles/images/flags/be.png b/LiveChat/Styles/images/flags/be.png new file mode 100644 index 0000000..449446a Binary files /dev/null and b/LiveChat/Styles/images/flags/be.png differ diff --git a/LiveChat/Styles/images/flags/bf.png b/LiveChat/Styles/images/flags/bf.png new file mode 100644 index 0000000..f3a7288 Binary files /dev/null and b/LiveChat/Styles/images/flags/bf.png differ diff --git a/LiveChat/Styles/images/flags/bg.png b/LiveChat/Styles/images/flags/bg.png new file mode 100644 index 0000000..ec03d4f Binary files /dev/null and b/LiveChat/Styles/images/flags/bg.png differ diff --git a/LiveChat/Styles/images/flags/bh.png b/LiveChat/Styles/images/flags/bh.png new file mode 100644 index 0000000..61bad9b Binary files /dev/null and b/LiveChat/Styles/images/flags/bh.png differ diff --git a/LiveChat/Styles/images/flags/bi.png b/LiveChat/Styles/images/flags/bi.png new file mode 100644 index 0000000..d82b894 Binary files /dev/null and b/LiveChat/Styles/images/flags/bi.png differ diff --git a/LiveChat/Styles/images/flags/bj.png b/LiveChat/Styles/images/flags/bj.png new file mode 100644 index 0000000..220c8e7 Binary files /dev/null and b/LiveChat/Styles/images/flags/bj.png differ diff --git a/LiveChat/Styles/images/flags/bn.png b/LiveChat/Styles/images/flags/bn.png new file mode 100644 index 0000000..944a7be Binary files /dev/null and b/LiveChat/Styles/images/flags/bn.png differ diff --git a/LiveChat/Styles/images/flags/bo.png b/LiveChat/Styles/images/flags/bo.png new file mode 100644 index 0000000..aec2cc6 Binary files /dev/null and b/LiveChat/Styles/images/flags/bo.png differ diff --git a/LiveChat/Styles/images/flags/br.png b/LiveChat/Styles/images/flags/br.png new file mode 100644 index 0000000..b54f27d Binary files /dev/null and b/LiveChat/Styles/images/flags/br.png differ diff --git a/LiveChat/Styles/images/flags/bs.png b/LiveChat/Styles/images/flags/bs.png new file mode 100644 index 0000000..43db8c1 Binary files /dev/null and b/LiveChat/Styles/images/flags/bs.png differ diff --git a/LiveChat/Styles/images/flags/bt.png b/LiveChat/Styles/images/flags/bt.png new file mode 100644 index 0000000..dfd0d6a Binary files /dev/null and b/LiveChat/Styles/images/flags/bt.png differ diff --git a/LiveChat/Styles/images/flags/bw.png b/LiveChat/Styles/images/flags/bw.png new file mode 100644 index 0000000..0a74b72 Binary files /dev/null and b/LiveChat/Styles/images/flags/bw.png differ diff --git a/LiveChat/Styles/images/flags/by.png b/LiveChat/Styles/images/flags/by.png new file mode 100644 index 0000000..1c9f546 Binary files /dev/null and b/LiveChat/Styles/images/flags/by.png differ diff --git a/LiveChat/Styles/images/flags/bz.png b/LiveChat/Styles/images/flags/bz.png new file mode 100644 index 0000000..ef37f6d Binary files /dev/null and b/LiveChat/Styles/images/flags/bz.png differ diff --git a/LiveChat/Styles/images/flags/ca.png b/LiveChat/Styles/images/flags/ca.png new file mode 100644 index 0000000..524f815 Binary files /dev/null and b/LiveChat/Styles/images/flags/ca.png differ diff --git a/LiveChat/Styles/images/flags/cd.png b/LiveChat/Styles/images/flags/cd.png new file mode 100644 index 0000000..a96eccf Binary files /dev/null and b/LiveChat/Styles/images/flags/cd.png differ diff --git a/LiveChat/Styles/images/flags/cf.png b/LiveChat/Styles/images/flags/cf.png new file mode 100644 index 0000000..e203020 Binary files /dev/null and b/LiveChat/Styles/images/flags/cf.png differ diff --git a/LiveChat/Styles/images/flags/cg.png b/LiveChat/Styles/images/flags/cg.png new file mode 100644 index 0000000..7afcfe0 Binary files /dev/null and b/LiveChat/Styles/images/flags/cg.png differ diff --git a/LiveChat/Styles/images/flags/ch.png b/LiveChat/Styles/images/flags/ch.png new file mode 100644 index 0000000..bd447d2 Binary files /dev/null and b/LiveChat/Styles/images/flags/ch.png differ diff --git a/LiveChat/Styles/images/flags/ci.png b/LiveChat/Styles/images/flags/ci.png new file mode 100644 index 0000000..14fceff Binary files /dev/null and b/LiveChat/Styles/images/flags/ci.png differ diff --git a/LiveChat/Styles/images/flags/cl.png b/LiveChat/Styles/images/flags/cl.png new file mode 100644 index 0000000..741c34b Binary files /dev/null and b/LiveChat/Styles/images/flags/cl.png differ diff --git a/LiveChat/Styles/images/flags/cm.png b/LiveChat/Styles/images/flags/cm.png new file mode 100644 index 0000000..e2a308b Binary files /dev/null and b/LiveChat/Styles/images/flags/cm.png differ diff --git a/LiveChat/Styles/images/flags/cn.png b/LiveChat/Styles/images/flags/cn.png new file mode 100644 index 0000000..7474dde Binary files /dev/null and b/LiveChat/Styles/images/flags/cn.png differ diff --git a/LiveChat/Styles/images/flags/co.png b/LiveChat/Styles/images/flags/co.png new file mode 100644 index 0000000..477177b Binary files /dev/null and b/LiveChat/Styles/images/flags/co.png differ diff --git a/LiveChat/Styles/images/flags/cr.png b/LiveChat/Styles/images/flags/cr.png new file mode 100644 index 0000000..62cc81a Binary files /dev/null and b/LiveChat/Styles/images/flags/cr.png differ diff --git a/LiveChat/Styles/images/flags/cu.png b/LiveChat/Styles/images/flags/cu.png new file mode 100644 index 0000000..4ada582 Binary files /dev/null and b/LiveChat/Styles/images/flags/cu.png differ diff --git a/LiveChat/Styles/images/flags/cv.png b/LiveChat/Styles/images/flags/cv.png new file mode 100644 index 0000000..e45bfdb Binary files /dev/null and b/LiveChat/Styles/images/flags/cv.png differ diff --git a/LiveChat/Styles/images/flags/cy.png b/LiveChat/Styles/images/flags/cy.png new file mode 100644 index 0000000..e909ebc Binary files /dev/null and b/LiveChat/Styles/images/flags/cy.png differ diff --git a/LiveChat/Styles/images/flags/cz.png b/LiveChat/Styles/images/flags/cz.png new file mode 100644 index 0000000..acfac56 Binary files /dev/null and b/LiveChat/Styles/images/flags/cz.png differ diff --git a/LiveChat/Styles/images/flags/de.png b/LiveChat/Styles/images/flags/de.png new file mode 100644 index 0000000..2dbd9b0 Binary files /dev/null and b/LiveChat/Styles/images/flags/de.png differ diff --git a/LiveChat/Styles/images/flags/dj.png b/LiveChat/Styles/images/flags/dj.png new file mode 100644 index 0000000..147636a Binary files /dev/null and b/LiveChat/Styles/images/flags/dj.png differ diff --git a/LiveChat/Styles/images/flags/dk.png b/LiveChat/Styles/images/flags/dk.png new file mode 100644 index 0000000..65d6b35 Binary files /dev/null and b/LiveChat/Styles/images/flags/dk.png differ diff --git a/LiveChat/Styles/images/flags/dm.png b/LiveChat/Styles/images/flags/dm.png new file mode 100644 index 0000000..04a92e1 Binary files /dev/null and b/LiveChat/Styles/images/flags/dm.png differ diff --git a/LiveChat/Styles/images/flags/do.png b/LiveChat/Styles/images/flags/do.png new file mode 100644 index 0000000..12e017e Binary files /dev/null and b/LiveChat/Styles/images/flags/do.png differ diff --git a/LiveChat/Styles/images/flags/dz.png b/LiveChat/Styles/images/flags/dz.png new file mode 100644 index 0000000..4670a0e Binary files /dev/null and b/LiveChat/Styles/images/flags/dz.png differ diff --git a/LiveChat/Styles/images/flags/ec.png b/LiveChat/Styles/images/flags/ec.png new file mode 100644 index 0000000..9289152 Binary files /dev/null and b/LiveChat/Styles/images/flags/ec.png differ diff --git a/LiveChat/Styles/images/flags/ee.png b/LiveChat/Styles/images/flags/ee.png new file mode 100644 index 0000000..1067640 Binary files /dev/null and b/LiveChat/Styles/images/flags/ee.png differ diff --git a/LiveChat/Styles/images/flags/eg.png b/LiveChat/Styles/images/flags/eg.png new file mode 100644 index 0000000..238d535 Binary files /dev/null and b/LiveChat/Styles/images/flags/eg.png differ diff --git a/LiveChat/Styles/images/flags/eh.png b/LiveChat/Styles/images/flags/eh.png new file mode 100644 index 0000000..b8cf7ef Binary files /dev/null and b/LiveChat/Styles/images/flags/eh.png differ diff --git a/LiveChat/Styles/images/flags/er.png b/LiveChat/Styles/images/flags/er.png new file mode 100644 index 0000000..546b1b9 Binary files /dev/null and b/LiveChat/Styles/images/flags/er.png differ diff --git a/LiveChat/Styles/images/flags/es.png b/LiveChat/Styles/images/flags/es.png new file mode 100644 index 0000000..a8ad334 Binary files /dev/null and b/LiveChat/Styles/images/flags/es.png differ diff --git a/LiveChat/Styles/images/flags/et.png b/LiveChat/Styles/images/flags/et.png new file mode 100644 index 0000000..e807c21 Binary files /dev/null and b/LiveChat/Styles/images/flags/et.png differ diff --git a/LiveChat/Styles/images/flags/fi.png b/LiveChat/Styles/images/flags/fi.png new file mode 100644 index 0000000..1ad1797 Binary files /dev/null and b/LiveChat/Styles/images/flags/fi.png differ diff --git a/LiveChat/Styles/images/flags/fj.png b/LiveChat/Styles/images/flags/fj.png new file mode 100644 index 0000000..6bf7371 Binary files /dev/null and b/LiveChat/Styles/images/flags/fj.png differ diff --git a/LiveChat/Styles/images/flags/fm.png b/LiveChat/Styles/images/flags/fm.png new file mode 100644 index 0000000..32d5b83 Binary files /dev/null and b/LiveChat/Styles/images/flags/fm.png differ diff --git a/LiveChat/Styles/images/flags/fr.png b/LiveChat/Styles/images/flags/fr.png new file mode 100644 index 0000000..a768476 Binary files /dev/null and b/LiveChat/Styles/images/flags/fr.png differ diff --git a/LiveChat/Styles/images/flags/ga.png b/LiveChat/Styles/images/flags/ga.png new file mode 100644 index 0000000..32c68bf Binary files /dev/null and b/LiveChat/Styles/images/flags/ga.png differ diff --git a/LiveChat/Styles/images/flags/gb.png b/LiveChat/Styles/images/flags/gb.png new file mode 100644 index 0000000..3b6668e Binary files /dev/null and b/LiveChat/Styles/images/flags/gb.png differ diff --git a/LiveChat/Styles/images/flags/gd.png b/LiveChat/Styles/images/flags/gd.png new file mode 100644 index 0000000..9a68c48 Binary files /dev/null and b/LiveChat/Styles/images/flags/gd.png differ diff --git a/LiveChat/Styles/images/flags/ge.png b/LiveChat/Styles/images/flags/ge.png new file mode 100644 index 0000000..108e367 Binary files /dev/null and b/LiveChat/Styles/images/flags/ge.png differ diff --git a/LiveChat/Styles/images/flags/gh.png b/LiveChat/Styles/images/flags/gh.png new file mode 100644 index 0000000..c2bf9d0 Binary files /dev/null and b/LiveChat/Styles/images/flags/gh.png differ diff --git a/LiveChat/Styles/images/flags/gm.png b/LiveChat/Styles/images/flags/gm.png new file mode 100644 index 0000000..b929a80 Binary files /dev/null and b/LiveChat/Styles/images/flags/gm.png differ diff --git a/LiveChat/Styles/images/flags/gn.png b/LiveChat/Styles/images/flags/gn.png new file mode 100644 index 0000000..be43ceb Binary files /dev/null and b/LiveChat/Styles/images/flags/gn.png differ diff --git a/LiveChat/Styles/images/flags/gq.png b/LiveChat/Styles/images/flags/gq.png new file mode 100644 index 0000000..db9415a Binary files /dev/null and b/LiveChat/Styles/images/flags/gq.png differ diff --git a/LiveChat/Styles/images/flags/gr.png b/LiveChat/Styles/images/flags/gr.png new file mode 100644 index 0000000..0944411 Binary files /dev/null and b/LiveChat/Styles/images/flags/gr.png differ diff --git a/LiveChat/Styles/images/flags/gt.png b/LiveChat/Styles/images/flags/gt.png new file mode 100644 index 0000000..76c5db7 Binary files /dev/null and b/LiveChat/Styles/images/flags/gt.png differ diff --git a/LiveChat/Styles/images/flags/gw.png b/LiveChat/Styles/images/flags/gw.png new file mode 100644 index 0000000..06dc510 Binary files /dev/null and b/LiveChat/Styles/images/flags/gw.png differ diff --git a/LiveChat/Styles/images/flags/gy.png b/LiveChat/Styles/images/flags/gy.png new file mode 100644 index 0000000..4f9b232 Binary files /dev/null and b/LiveChat/Styles/images/flags/gy.png differ diff --git a/LiveChat/Styles/images/flags/hn.png b/LiveChat/Styles/images/flags/hn.png new file mode 100644 index 0000000..b1a9f5f Binary files /dev/null and b/LiveChat/Styles/images/flags/hn.png differ diff --git a/LiveChat/Styles/images/flags/hr.png b/LiveChat/Styles/images/flags/hr.png new file mode 100644 index 0000000..6820513 Binary files /dev/null and b/LiveChat/Styles/images/flags/hr.png differ diff --git a/LiveChat/Styles/images/flags/ht.png b/LiveChat/Styles/images/flags/ht.png new file mode 100644 index 0000000..ba76abd Binary files /dev/null and b/LiveChat/Styles/images/flags/ht.png differ diff --git a/LiveChat/Styles/images/flags/hu.png b/LiveChat/Styles/images/flags/hu.png new file mode 100644 index 0000000..eeee4ca Binary files /dev/null and b/LiveChat/Styles/images/flags/hu.png differ diff --git a/LiveChat/Styles/images/flags/id.png b/LiveChat/Styles/images/flags/id.png new file mode 100644 index 0000000..e96bc74 Binary files /dev/null and b/LiveChat/Styles/images/flags/id.png differ diff --git a/LiveChat/Styles/images/flags/ie.png b/LiveChat/Styles/images/flags/ie.png new file mode 100644 index 0000000..52e2ad4 Binary files /dev/null and b/LiveChat/Styles/images/flags/ie.png differ diff --git a/LiveChat/Styles/images/flags/il.png b/LiveChat/Styles/images/flags/il.png new file mode 100644 index 0000000..c85c9d3 Binary files /dev/null and b/LiveChat/Styles/images/flags/il.png differ diff --git a/LiveChat/Styles/images/flags/in.png b/LiveChat/Styles/images/flags/in.png new file mode 100644 index 0000000..be5acd3 Binary files /dev/null and b/LiveChat/Styles/images/flags/in.png differ diff --git a/LiveChat/Styles/images/flags/iq.png b/LiveChat/Styles/images/flags/iq.png new file mode 100644 index 0000000..f370c9a Binary files /dev/null and b/LiveChat/Styles/images/flags/iq.png differ diff --git a/LiveChat/Styles/images/flags/ir.png b/LiveChat/Styles/images/flags/ir.png new file mode 100644 index 0000000..7f647fa Binary files /dev/null and b/LiveChat/Styles/images/flags/ir.png differ diff --git a/LiveChat/Styles/images/flags/is.png b/LiveChat/Styles/images/flags/is.png new file mode 100644 index 0000000..74c9e03 Binary files /dev/null and b/LiveChat/Styles/images/flags/is.png differ diff --git a/LiveChat/Styles/images/flags/it.png b/LiveChat/Styles/images/flags/it.png new file mode 100644 index 0000000..d62e50b Binary files /dev/null and b/LiveChat/Styles/images/flags/it.png differ diff --git a/LiveChat/Styles/images/flags/jm.png b/LiveChat/Styles/images/flags/jm.png new file mode 100644 index 0000000..a960d3d Binary files /dev/null and b/LiveChat/Styles/images/flags/jm.png differ diff --git a/LiveChat/Styles/images/flags/jo.png b/LiveChat/Styles/images/flags/jo.png new file mode 100644 index 0000000..e8b743a Binary files /dev/null and b/LiveChat/Styles/images/flags/jo.png differ diff --git a/LiveChat/Styles/images/flags/jp.png b/LiveChat/Styles/images/flags/jp.png new file mode 100644 index 0000000..fd1ce05 Binary files /dev/null and b/LiveChat/Styles/images/flags/jp.png differ diff --git a/LiveChat/Styles/images/flags/ke.png b/LiveChat/Styles/images/flags/ke.png new file mode 100644 index 0000000..dbf559f Binary files /dev/null and b/LiveChat/Styles/images/flags/ke.png differ diff --git a/LiveChat/Styles/images/flags/kg.png b/LiveChat/Styles/images/flags/kg.png new file mode 100644 index 0000000..c0fe3e5 Binary files /dev/null and b/LiveChat/Styles/images/flags/kg.png differ diff --git a/LiveChat/Styles/images/flags/kh.png b/LiveChat/Styles/images/flags/kh.png new file mode 100644 index 0000000..b9340f7 Binary files /dev/null and b/LiveChat/Styles/images/flags/kh.png differ diff --git a/LiveChat/Styles/images/flags/ki.png b/LiveChat/Styles/images/flags/ki.png new file mode 100644 index 0000000..6b718d1 Binary files /dev/null and b/LiveChat/Styles/images/flags/ki.png differ diff --git a/LiveChat/Styles/images/flags/km.png b/LiveChat/Styles/images/flags/km.png new file mode 100644 index 0000000..dbbd8f4 Binary files /dev/null and b/LiveChat/Styles/images/flags/km.png differ diff --git a/LiveChat/Styles/images/flags/kn.png b/LiveChat/Styles/images/flags/kn.png new file mode 100644 index 0000000..028bef5 Binary files /dev/null and b/LiveChat/Styles/images/flags/kn.png differ diff --git a/LiveChat/Styles/images/flags/kp.png b/LiveChat/Styles/images/flags/kp.png new file mode 100644 index 0000000..3fee379 Binary files /dev/null and b/LiveChat/Styles/images/flags/kp.png differ diff --git a/LiveChat/Styles/images/flags/kr.png b/LiveChat/Styles/images/flags/kr.png new file mode 100644 index 0000000..d0022a2 Binary files /dev/null and b/LiveChat/Styles/images/flags/kr.png differ diff --git a/LiveChat/Styles/images/flags/ks.png b/LiveChat/Styles/images/flags/ks.png new file mode 100644 index 0000000..e1824f1 Binary files /dev/null and b/LiveChat/Styles/images/flags/ks.png differ diff --git a/LiveChat/Styles/images/flags/kw.png b/LiveChat/Styles/images/flags/kw.png new file mode 100644 index 0000000..7f701d5 Binary files /dev/null and b/LiveChat/Styles/images/flags/kw.png differ diff --git a/LiveChat/Styles/images/flags/kz.png b/LiveChat/Styles/images/flags/kz.png new file mode 100644 index 0000000..1c23ee1 Binary files /dev/null and b/LiveChat/Styles/images/flags/kz.png differ diff --git a/LiveChat/Styles/images/flags/la.png b/LiveChat/Styles/images/flags/la.png new file mode 100644 index 0000000..9758884 Binary files /dev/null and b/LiveChat/Styles/images/flags/la.png differ diff --git a/LiveChat/Styles/images/flags/lb.png b/LiveChat/Styles/images/flags/lb.png new file mode 100644 index 0000000..80b3256 Binary files /dev/null and b/LiveChat/Styles/images/flags/lb.png differ diff --git a/LiveChat/Styles/images/flags/lc.png b/LiveChat/Styles/images/flags/lc.png new file mode 100644 index 0000000..dc2de27 Binary files /dev/null and b/LiveChat/Styles/images/flags/lc.png differ diff --git a/LiveChat/Styles/images/flags/li.png b/LiveChat/Styles/images/flags/li.png new file mode 100644 index 0000000..c635a63 Binary files /dev/null and b/LiveChat/Styles/images/flags/li.png differ diff --git a/LiveChat/Styles/images/flags/lk.png b/LiveChat/Styles/images/flags/lk.png new file mode 100644 index 0000000..12e6a00 Binary files /dev/null and b/LiveChat/Styles/images/flags/lk.png differ diff --git a/LiveChat/Styles/images/flags/lr.png b/LiveChat/Styles/images/flags/lr.png new file mode 100644 index 0000000..0b998ab Binary files /dev/null and b/LiveChat/Styles/images/flags/lr.png differ diff --git a/LiveChat/Styles/images/flags/ls.png b/LiveChat/Styles/images/flags/ls.png new file mode 100644 index 0000000..ba9ed2d Binary files /dev/null and b/LiveChat/Styles/images/flags/ls.png differ diff --git a/LiveChat/Styles/images/flags/lt.png b/LiveChat/Styles/images/flags/lt.png new file mode 100644 index 0000000..257930e Binary files /dev/null and b/LiveChat/Styles/images/flags/lt.png differ diff --git a/LiveChat/Styles/images/flags/lu.png b/LiveChat/Styles/images/flags/lu.png new file mode 100644 index 0000000..64b5dd6 Binary files /dev/null and b/LiveChat/Styles/images/flags/lu.png differ diff --git a/LiveChat/Styles/images/flags/lv.png b/LiveChat/Styles/images/flags/lv.png new file mode 100644 index 0000000..fb8345e Binary files /dev/null and b/LiveChat/Styles/images/flags/lv.png differ diff --git a/LiveChat/Styles/images/flags/ly.png b/LiveChat/Styles/images/flags/ly.png new file mode 100644 index 0000000..b90fc93 Binary files /dev/null and b/LiveChat/Styles/images/flags/ly.png differ diff --git a/LiveChat/Styles/images/flags/ma.png b/LiveChat/Styles/images/flags/ma.png new file mode 100644 index 0000000..8e62535 Binary files /dev/null and b/LiveChat/Styles/images/flags/ma.png differ diff --git a/LiveChat/Styles/images/flags/mc.png b/LiveChat/Styles/images/flags/mc.png new file mode 100644 index 0000000..194a09e Binary files /dev/null and b/LiveChat/Styles/images/flags/mc.png differ diff --git a/LiveChat/Styles/images/flags/md.png b/LiveChat/Styles/images/flags/md.png new file mode 100644 index 0000000..0071401 Binary files /dev/null and b/LiveChat/Styles/images/flags/md.png differ diff --git a/LiveChat/Styles/images/flags/me.png b/LiveChat/Styles/images/flags/me.png new file mode 100644 index 0000000..0952236 Binary files /dev/null and b/LiveChat/Styles/images/flags/me.png differ diff --git a/LiveChat/Styles/images/flags/mg.png b/LiveChat/Styles/images/flags/mg.png new file mode 100644 index 0000000..4b4b065 Binary files /dev/null and b/LiveChat/Styles/images/flags/mg.png differ diff --git a/LiveChat/Styles/images/flags/mh.png b/LiveChat/Styles/images/flags/mh.png new file mode 100644 index 0000000..3e7a4b5 Binary files /dev/null and b/LiveChat/Styles/images/flags/mh.png differ diff --git a/LiveChat/Styles/images/flags/mk.png b/LiveChat/Styles/images/flags/mk.png new file mode 100644 index 0000000..4cb42a7 Binary files /dev/null and b/LiveChat/Styles/images/flags/mk.png differ diff --git a/LiveChat/Styles/images/flags/ml.png b/LiveChat/Styles/images/flags/ml.png new file mode 100644 index 0000000..182848a Binary files /dev/null and b/LiveChat/Styles/images/flags/ml.png differ diff --git a/LiveChat/Styles/images/flags/mm.png b/LiveChat/Styles/images/flags/mm.png new file mode 100644 index 0000000..f486f85 Binary files /dev/null and b/LiveChat/Styles/images/flags/mm.png differ diff --git a/LiveChat/Styles/images/flags/mn.png b/LiveChat/Styles/images/flags/mn.png new file mode 100644 index 0000000..dd0bb39 Binary files /dev/null and b/LiveChat/Styles/images/flags/mn.png differ diff --git a/LiveChat/Styles/images/flags/mr.png b/LiveChat/Styles/images/flags/mr.png new file mode 100644 index 0000000..caf0365 Binary files /dev/null and b/LiveChat/Styles/images/flags/mr.png differ diff --git a/LiveChat/Styles/images/flags/mt.png b/LiveChat/Styles/images/flags/mt.png new file mode 100644 index 0000000..b4d686e Binary files /dev/null and b/LiveChat/Styles/images/flags/mt.png differ diff --git a/LiveChat/Styles/images/flags/mu.png b/LiveChat/Styles/images/flags/mu.png new file mode 100644 index 0000000..03f524f Binary files /dev/null and b/LiveChat/Styles/images/flags/mu.png differ diff --git a/LiveChat/Styles/images/flags/mv.png b/LiveChat/Styles/images/flags/mv.png new file mode 100644 index 0000000..ab4aae4 Binary files /dev/null and b/LiveChat/Styles/images/flags/mv.png differ diff --git a/LiveChat/Styles/images/flags/mw.png b/LiveChat/Styles/images/flags/mw.png new file mode 100644 index 0000000..bf38ff9 Binary files /dev/null and b/LiveChat/Styles/images/flags/mw.png differ diff --git a/LiveChat/Styles/images/flags/mx.png b/LiveChat/Styles/images/flags/mx.png new file mode 100644 index 0000000..783148b Binary files /dev/null and b/LiveChat/Styles/images/flags/mx.png differ diff --git a/LiveChat/Styles/images/flags/my.png b/LiveChat/Styles/images/flags/my.png new file mode 100644 index 0000000..5a9ae41 Binary files /dev/null and b/LiveChat/Styles/images/flags/my.png differ diff --git a/LiveChat/Styles/images/flags/mz.png b/LiveChat/Styles/images/flags/mz.png new file mode 100644 index 0000000..0e4c983 Binary files /dev/null and b/LiveChat/Styles/images/flags/mz.png differ diff --git a/LiveChat/Styles/images/flags/na.png b/LiveChat/Styles/images/flags/na.png new file mode 100644 index 0000000..620937b Binary files /dev/null and b/LiveChat/Styles/images/flags/na.png differ diff --git a/LiveChat/Styles/images/flags/ne.png b/LiveChat/Styles/images/flags/ne.png new file mode 100644 index 0000000..0762231 Binary files /dev/null and b/LiveChat/Styles/images/flags/ne.png differ diff --git a/LiveChat/Styles/images/flags/ng.png b/LiveChat/Styles/images/flags/ng.png new file mode 100644 index 0000000..ba56e9e Binary files /dev/null and b/LiveChat/Styles/images/flags/ng.png differ diff --git a/LiveChat/Styles/images/flags/ni.png b/LiveChat/Styles/images/flags/ni.png new file mode 100644 index 0000000..9b6dbf5 Binary files /dev/null and b/LiveChat/Styles/images/flags/ni.png differ diff --git a/LiveChat/Styles/images/flags/nl.png b/LiveChat/Styles/images/flags/nl.png new file mode 100644 index 0000000..aeb72b6 Binary files /dev/null and b/LiveChat/Styles/images/flags/nl.png differ diff --git a/LiveChat/Styles/images/flags/no.png b/LiveChat/Styles/images/flags/no.png new file mode 100644 index 0000000..e14f90f Binary files /dev/null and b/LiveChat/Styles/images/flags/no.png differ diff --git a/LiveChat/Styles/images/flags/np.png b/LiveChat/Styles/images/flags/np.png new file mode 100644 index 0000000..fd0cd6e Binary files /dev/null and b/LiveChat/Styles/images/flags/np.png differ diff --git a/LiveChat/Styles/images/flags/nr.png b/LiveChat/Styles/images/flags/nr.png new file mode 100644 index 0000000..7214086 Binary files /dev/null and b/LiveChat/Styles/images/flags/nr.png differ diff --git a/LiveChat/Styles/images/flags/nz.png b/LiveChat/Styles/images/flags/nz.png new file mode 100644 index 0000000..1f25035 Binary files /dev/null and b/LiveChat/Styles/images/flags/nz.png differ diff --git a/LiveChat/Styles/images/flags/om.png b/LiveChat/Styles/images/flags/om.png new file mode 100644 index 0000000..05c99d9 Binary files /dev/null and b/LiveChat/Styles/images/flags/om.png differ diff --git a/LiveChat/Styles/images/flags/pa.png b/LiveChat/Styles/images/flags/pa.png new file mode 100644 index 0000000..96d4c8e Binary files /dev/null and b/LiveChat/Styles/images/flags/pa.png differ diff --git a/LiveChat/Styles/images/flags/pe.png b/LiveChat/Styles/images/flags/pe.png new file mode 100644 index 0000000..e4d623e Binary files /dev/null and b/LiveChat/Styles/images/flags/pe.png differ diff --git a/LiveChat/Styles/images/flags/pg.png b/LiveChat/Styles/images/flags/pg.png new file mode 100644 index 0000000..5011a16 Binary files /dev/null and b/LiveChat/Styles/images/flags/pg.png differ diff --git a/LiveChat/Styles/images/flags/ph.png b/LiveChat/Styles/images/flags/ph.png new file mode 100644 index 0000000..41ddff2 Binary files /dev/null and b/LiveChat/Styles/images/flags/ph.png differ diff --git a/LiveChat/Styles/images/flags/pk.png b/LiveChat/Styles/images/flags/pk.png new file mode 100644 index 0000000..76020fe Binary files /dev/null and b/LiveChat/Styles/images/flags/pk.png differ diff --git a/LiveChat/Styles/images/flags/pl.png b/LiveChat/Styles/images/flags/pl.png new file mode 100644 index 0000000..d4db002 Binary files /dev/null and b/LiveChat/Styles/images/flags/pl.png differ diff --git a/LiveChat/Styles/images/flags/pt.png b/LiveChat/Styles/images/flags/pt.png new file mode 100644 index 0000000..e0619bc Binary files /dev/null and b/LiveChat/Styles/images/flags/pt.png differ diff --git a/LiveChat/Styles/images/flags/pw.png b/LiveChat/Styles/images/flags/pw.png new file mode 100644 index 0000000..be101ba Binary files /dev/null and b/LiveChat/Styles/images/flags/pw.png differ diff --git a/LiveChat/Styles/images/flags/py.png b/LiveChat/Styles/images/flags/py.png new file mode 100644 index 0000000..b2e2d5c Binary files /dev/null and b/LiveChat/Styles/images/flags/py.png differ diff --git a/LiveChat/Styles/images/flags/qa.png b/LiveChat/Styles/images/flags/qa.png new file mode 100644 index 0000000..0e615fe Binary files /dev/null and b/LiveChat/Styles/images/flags/qa.png differ diff --git a/LiveChat/Styles/images/flags/ro.png b/LiveChat/Styles/images/flags/ro.png new file mode 100644 index 0000000..57f34f3 Binary files /dev/null and b/LiveChat/Styles/images/flags/ro.png differ diff --git a/LiveChat/Styles/images/flags/rs.png b/LiveChat/Styles/images/flags/rs.png new file mode 100644 index 0000000..7273ea7 Binary files /dev/null and b/LiveChat/Styles/images/flags/rs.png differ diff --git a/LiveChat/Styles/images/flags/ru.png b/LiveChat/Styles/images/flags/ru.png new file mode 100644 index 0000000..79d2101 Binary files /dev/null and b/LiveChat/Styles/images/flags/ru.png differ diff --git a/LiveChat/Styles/images/flags/rw.png b/LiveChat/Styles/images/flags/rw.png new file mode 100644 index 0000000..5b859ea Binary files /dev/null and b/LiveChat/Styles/images/flags/rw.png differ diff --git a/LiveChat/Styles/images/flags/sa.png b/LiveChat/Styles/images/flags/sa.png new file mode 100644 index 0000000..0df5b92 Binary files /dev/null and b/LiveChat/Styles/images/flags/sa.png differ diff --git a/LiveChat/Styles/images/flags/sb.png b/LiveChat/Styles/images/flags/sb.png new file mode 100644 index 0000000..832f7ce Binary files /dev/null and b/LiveChat/Styles/images/flags/sb.png differ diff --git a/LiveChat/Styles/images/flags/sc.png b/LiveChat/Styles/images/flags/sc.png new file mode 100644 index 0000000..a497589 Binary files /dev/null and b/LiveChat/Styles/images/flags/sc.png differ diff --git a/LiveChat/Styles/images/flags/sd.png b/LiveChat/Styles/images/flags/sd.png new file mode 100644 index 0000000..386f3e8 Binary files /dev/null and b/LiveChat/Styles/images/flags/sd.png differ diff --git a/LiveChat/Styles/images/flags/se.png b/LiveChat/Styles/images/flags/se.png new file mode 100644 index 0000000..9e12578 Binary files /dev/null and b/LiveChat/Styles/images/flags/se.png differ diff --git a/LiveChat/Styles/images/flags/sg.png b/LiveChat/Styles/images/flags/sg.png new file mode 100644 index 0000000..7e89814 Binary files /dev/null and b/LiveChat/Styles/images/flags/sg.png differ diff --git a/LiveChat/Styles/images/flags/si.png b/LiveChat/Styles/images/flags/si.png new file mode 100644 index 0000000..3692b66 Binary files /dev/null and b/LiveChat/Styles/images/flags/si.png differ diff --git a/LiveChat/Styles/images/flags/sk.png b/LiveChat/Styles/images/flags/sk.png new file mode 100644 index 0000000..8a73d64 Binary files /dev/null and b/LiveChat/Styles/images/flags/sk.png differ diff --git a/LiveChat/Styles/images/flags/sl.png b/LiveChat/Styles/images/flags/sl.png new file mode 100644 index 0000000..b68450d Binary files /dev/null and b/LiveChat/Styles/images/flags/sl.png differ diff --git a/LiveChat/Styles/images/flags/sm.png b/LiveChat/Styles/images/flags/sm.png new file mode 100644 index 0000000..43f1965 Binary files /dev/null and b/LiveChat/Styles/images/flags/sm.png differ diff --git a/LiveChat/Styles/images/flags/sn.png b/LiveChat/Styles/images/flags/sn.png new file mode 100644 index 0000000..fcd0244 Binary files /dev/null and b/LiveChat/Styles/images/flags/sn.png differ diff --git a/LiveChat/Styles/images/flags/so.png b/LiveChat/Styles/images/flags/so.png new file mode 100644 index 0000000..819490b Binary files /dev/null and b/LiveChat/Styles/images/flags/so.png differ diff --git a/LiveChat/Styles/images/flags/sr.png b/LiveChat/Styles/images/flags/sr.png new file mode 100644 index 0000000..9ac4337 Binary files /dev/null and b/LiveChat/Styles/images/flags/sr.png differ diff --git a/LiveChat/Styles/images/flags/st.png b/LiveChat/Styles/images/flags/st.png new file mode 100644 index 0000000..b4edccb Binary files /dev/null and b/LiveChat/Styles/images/flags/st.png differ diff --git a/LiveChat/Styles/images/flags/sv.png b/LiveChat/Styles/images/flags/sv.png new file mode 100644 index 0000000..7fe790c Binary files /dev/null and b/LiveChat/Styles/images/flags/sv.png differ diff --git a/LiveChat/Styles/images/flags/sy.png b/LiveChat/Styles/images/flags/sy.png new file mode 100644 index 0000000..c78f9d5 Binary files /dev/null and b/LiveChat/Styles/images/flags/sy.png differ diff --git a/LiveChat/Styles/images/flags/sz.png b/LiveChat/Styles/images/flags/sz.png new file mode 100644 index 0000000..6550515 Binary files /dev/null and b/LiveChat/Styles/images/flags/sz.png differ diff --git a/LiveChat/Styles/images/flags/td.png b/LiveChat/Styles/images/flags/td.png new file mode 100644 index 0000000..c0c76da Binary files /dev/null and b/LiveChat/Styles/images/flags/td.png differ diff --git a/LiveChat/Styles/images/flags/tg.png b/LiveChat/Styles/images/flags/tg.png new file mode 100644 index 0000000..31f1a00 Binary files /dev/null and b/LiveChat/Styles/images/flags/tg.png differ diff --git a/LiveChat/Styles/images/flags/th.png b/LiveChat/Styles/images/flags/th.png new file mode 100644 index 0000000..5cf74c9 Binary files /dev/null and b/LiveChat/Styles/images/flags/th.png differ diff --git a/LiveChat/Styles/images/flags/tj.png b/LiveChat/Styles/images/flags/tj.png new file mode 100644 index 0000000..1d83e4c Binary files /dev/null and b/LiveChat/Styles/images/flags/tj.png differ diff --git a/LiveChat/Styles/images/flags/tl.png b/LiveChat/Styles/images/flags/tl.png new file mode 100644 index 0000000..c646f33 Binary files /dev/null and b/LiveChat/Styles/images/flags/tl.png differ diff --git a/LiveChat/Styles/images/flags/tm.png b/LiveChat/Styles/images/flags/tm.png new file mode 100644 index 0000000..5dd8fb9 Binary files /dev/null and b/LiveChat/Styles/images/flags/tm.png differ diff --git a/LiveChat/Styles/images/flags/tn.png b/LiveChat/Styles/images/flags/tn.png new file mode 100644 index 0000000..09ce235 Binary files /dev/null and b/LiveChat/Styles/images/flags/tn.png differ diff --git a/LiveChat/Styles/images/flags/to.png b/LiveChat/Styles/images/flags/to.png new file mode 100644 index 0000000..34b5aa1 Binary files /dev/null and b/LiveChat/Styles/images/flags/to.png differ diff --git a/LiveChat/Styles/images/flags/tr.png b/LiveChat/Styles/images/flags/tr.png new file mode 100644 index 0000000..a67740a Binary files /dev/null and b/LiveChat/Styles/images/flags/tr.png differ diff --git a/LiveChat/Styles/images/flags/tt.png b/LiveChat/Styles/images/flags/tt.png new file mode 100644 index 0000000..61ee0b0 Binary files /dev/null and b/LiveChat/Styles/images/flags/tt.png differ diff --git a/LiveChat/Styles/images/flags/tv.png b/LiveChat/Styles/images/flags/tv.png new file mode 100644 index 0000000..16f8616 Binary files /dev/null and b/LiveChat/Styles/images/flags/tv.png differ diff --git a/LiveChat/Styles/images/flags/tw.png b/LiveChat/Styles/images/flags/tw.png new file mode 100644 index 0000000..88cc0df Binary files /dev/null and b/LiveChat/Styles/images/flags/tw.png differ diff --git a/LiveChat/Styles/images/flags/tz.png b/LiveChat/Styles/images/flags/tz.png new file mode 100644 index 0000000..94ca541 Binary files /dev/null and b/LiveChat/Styles/images/flags/tz.png differ diff --git a/LiveChat/Styles/images/flags/ua.png b/LiveChat/Styles/images/flags/ua.png new file mode 100644 index 0000000..80301f4 Binary files /dev/null and b/LiveChat/Styles/images/flags/ua.png differ diff --git a/LiveChat/Styles/images/flags/ug.png b/LiveChat/Styles/images/flags/ug.png new file mode 100644 index 0000000..fec8a45 Binary files /dev/null and b/LiveChat/Styles/images/flags/ug.png differ diff --git a/LiveChat/Styles/images/flags/us.png b/LiveChat/Styles/images/flags/us.png new file mode 100644 index 0000000..07ddf4e Binary files /dev/null and b/LiveChat/Styles/images/flags/us.png differ diff --git a/LiveChat/Styles/images/flags/uy.png b/LiveChat/Styles/images/flags/uy.png new file mode 100644 index 0000000..d49a4f1 Binary files /dev/null and b/LiveChat/Styles/images/flags/uy.png differ diff --git a/LiveChat/Styles/images/flags/uz.png b/LiveChat/Styles/images/flags/uz.png new file mode 100644 index 0000000..37688d8 Binary files /dev/null and b/LiveChat/Styles/images/flags/uz.png differ diff --git a/LiveChat/Styles/images/flags/va.png b/LiveChat/Styles/images/flags/va.png new file mode 100644 index 0000000..9938009 Binary files /dev/null and b/LiveChat/Styles/images/flags/va.png differ diff --git a/LiveChat/Styles/images/flags/vc.png b/LiveChat/Styles/images/flags/vc.png new file mode 100644 index 0000000..55018b1 Binary files /dev/null and b/LiveChat/Styles/images/flags/vc.png differ diff --git a/LiveChat/Styles/images/flags/ve.png b/LiveChat/Styles/images/flags/ve.png new file mode 100644 index 0000000..4c8b135 Binary files /dev/null and b/LiveChat/Styles/images/flags/ve.png differ diff --git a/LiveChat/Styles/images/flags/vn.png b/LiveChat/Styles/images/flags/vn.png new file mode 100644 index 0000000..e9edf37 Binary files /dev/null and b/LiveChat/Styles/images/flags/vn.png differ diff --git a/LiveChat/Styles/images/flags/vu.png b/LiveChat/Styles/images/flags/vu.png new file mode 100644 index 0000000..b221447 Binary files /dev/null and b/LiveChat/Styles/images/flags/vu.png differ diff --git a/LiveChat/Styles/images/flags/ws.png b/LiveChat/Styles/images/flags/ws.png new file mode 100644 index 0000000..b44c452 Binary files /dev/null and b/LiveChat/Styles/images/flags/ws.png differ diff --git a/LiveChat/Styles/images/flags/ye.png b/LiveChat/Styles/images/flags/ye.png new file mode 100644 index 0000000..61a0a56 Binary files /dev/null and b/LiveChat/Styles/images/flags/ye.png differ diff --git a/LiveChat/Styles/images/flags/za.png b/LiveChat/Styles/images/flags/za.png new file mode 100644 index 0000000..b6ac53e Binary files /dev/null and b/LiveChat/Styles/images/flags/za.png differ diff --git a/LiveChat/Styles/images/flags/zm.png b/LiveChat/Styles/images/flags/zm.png new file mode 100644 index 0000000..a8b5749 Binary files /dev/null and b/LiveChat/Styles/images/flags/zm.png differ diff --git a/LiveChat/Styles/images/flags/zw.png b/LiveChat/Styles/images/flags/zw.png new file mode 100644 index 0000000..004cd2a Binary files /dev/null and b/LiveChat/Styles/images/flags/zw.png differ diff --git a/LiveChat/Styles/images/os.png b/LiveChat/Styles/images/os.png new file mode 100644 index 0000000..1a44f44 Binary files /dev/null and b/LiveChat/Styles/images/os.png differ diff --git a/LiveChat/Styles/images/visitor-avatar.png b/LiveChat/Styles/images/visitor-avatar.png new file mode 100644 index 0000000..471cf08 Binary files /dev/null and b/LiveChat/Styles/images/visitor-avatar.png differ diff --git a/LiveChat/Styles/img/icons/ellipsis.png b/LiveChat/Styles/img/icons/ellipsis.png new file mode 100644 index 0000000..b6b2b9f Binary files /dev/null and b/LiveChat/Styles/img/icons/ellipsis.png differ diff --git a/LiveChat/Styles/img/icons/ellipsis@2x.png b/LiveChat/Styles/img/icons/ellipsis@2x.png new file mode 100644 index 0000000..76912af Binary files /dev/null and b/LiveChat/Styles/img/icons/ellipsis@2x.png differ diff --git a/LiveChat/Styles/img/icons/menu-2.png b/LiveChat/Styles/img/icons/menu-2.png new file mode 100644 index 0000000..444e3d4 Binary files /dev/null and b/LiveChat/Styles/img/icons/menu-2.png differ diff --git a/LiveChat/Styles/img/icons/menu-2@2x.png b/LiveChat/Styles/img/icons/menu-2@2x.png new file mode 100644 index 0000000..3d99c64 Binary files /dev/null and b/LiveChat/Styles/img/icons/menu-2@2x.png differ diff --git a/LiveChat/Styles/img/icons/message.png b/LiveChat/Styles/img/icons/message.png new file mode 100644 index 0000000..c2cf72b Binary files /dev/null and b/LiveChat/Styles/img/icons/message.png differ diff --git a/LiveChat/Styles/img/icons/message@2x.png b/LiveChat/Styles/img/icons/message@2x.png new file mode 100644 index 0000000..b138588 Binary files /dev/null and b/LiveChat/Styles/img/icons/message@2x.png differ diff --git a/LiveChat/Styles/img/icons/notification.png b/LiveChat/Styles/img/icons/notification.png new file mode 100644 index 0000000..32ab032 Binary files /dev/null and b/LiveChat/Styles/img/icons/notification.png differ diff --git a/LiveChat/Styles/img/icons/notification@2x.png b/LiveChat/Styles/img/icons/notification@2x.png new file mode 100644 index 0000000..3bccae8 Binary files /dev/null and b/LiveChat/Styles/img/icons/notification@2x.png differ diff --git a/LiveChat/Styles/img/icons/search-2.png b/LiveChat/Styles/img/icons/search-2.png new file mode 100644 index 0000000..e4273bf Binary files /dev/null and b/LiveChat/Styles/img/icons/search-2.png differ diff --git a/LiveChat/Styles/img/icons/search.png b/LiveChat/Styles/img/icons/search.png new file mode 100644 index 0000000..c3f7be3 Binary files /dev/null and b/LiveChat/Styles/img/icons/search.png differ diff --git a/LiveChat/Styles/img/icons/search@2x.png b/LiveChat/Styles/img/icons/search@2x.png new file mode 100644 index 0000000..c6b37f2 Binary files /dev/null and b/LiveChat/Styles/img/icons/search@2x.png differ diff --git a/LiveChat/Styles/img/icons/task.png b/LiveChat/Styles/img/icons/task.png new file mode 100644 index 0000000..4f96fb8 Binary files /dev/null and b/LiveChat/Styles/img/icons/task.png differ diff --git a/LiveChat/Styles/img/icons/task@2x.png b/LiveChat/Styles/img/icons/task@2x.png new file mode 100644 index 0000000..9eb4466 Binary files /dev/null and b/LiveChat/Styles/img/icons/task@2x.png differ diff --git a/LiveChat/Styles/img/notifications.png b/LiveChat/Styles/img/notifications.png new file mode 100644 index 0000000..9e69b4e Binary files /dev/null and b/LiveChat/Styles/img/notifications.png differ diff --git a/LiveChat/Styles/img/profile-menu.png b/LiveChat/Styles/img/profile-menu.png new file mode 100644 index 0000000..66f1205 Binary files /dev/null and b/LiveChat/Styles/img/profile-menu.png differ diff --git a/LiveChat/Styles/img/select.png b/LiveChat/Styles/img/select.png new file mode 100644 index 0000000..4294185 Binary files /dev/null and b/LiveChat/Styles/img/select.png differ diff --git a/LiveChat/Styles/livechat-agent.css b/LiveChat/Styles/livechat-agent.css new file mode 100644 index 0000000..d9bbcad --- /dev/null +++ b/LiveChat/Styles/livechat-agent.css @@ -0,0 +1,750 @@ +@keyframes bouncy_left { + 0% { + margin-left: 0; + } + + 7% { + margin-left: 0; + } + + 10.25% { + margin-left: -18px; + } + + 13.5% { + margin-left: 0; + } + + 16% { + margin-left: -9px; + } + + 18.5% { + margin-left: 0; + } + + 19.75% { + margin-left: -4px; + } + + 21% { + margin-left: 0; + } + + 21.5% { + margin-left: -2px; + } + + 22% { + margin-left: 0; + } + + 100% { + margin-left: 0; + } +} + +.livechat-serve-requests { + -webkit-animation: bouncy_left 8s linear 0s 3 normal; + -moz-animation: bouncy_left 8s linear 0s 3 normal; + -ms-animation: bouncy_left 8s linear 0s 3 normal; + -o-animation: bouncy_left 8s linear 0s 3 normal; + animation: bouncy_left 8s linear 0s 3 normal; + background: #f78e3f none repeat scroll 0 0; + border: 1px solid #804500; + border-radius: 0 3px 3px 0; + bottom: 3px; + color: #fff; + cursor: pointer; + display: none; + font-weight: 700; + height: 30px; + left: 0; + line-height: 28px; + position: fixed; + text-align: center; + width: 200px; + z-index: 9999; +} + +.display-block { + display: block !important; +} + +.mydnn-livechats { + background: rgba(36, 36, 36, 0.56) none repeat scroll 0 0; + font-family: Helvetica Neue,Helvetica; + height: 100%; + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 999999; +} + +.livechat-window { + height: calc(100% - 100px); + margin: 50px auto 0; + max-width: 1000px; + min-height: 500px; + width: 100%; +} + + .livechat-window.window-min { + animation: 400ms linear 0s normal forwards 1 running minimize; + } + + .livechat-window.window-max { + animation: 400ms linear 0s normal forwards 1 running maximize; + } + + .livechat-window.window-hidden { + display: none; + } + +.window-titlebar { + background: #333 none repeat scroll 0 0; + border-radius: 5px 5px 0 0; + box-sizing: border-box; + height: 40px; + padding: 10px; + width: 100%; +} + + .window-titlebar .visitor-avatar { + background: #eee none repeat scroll 0 0; + border-radius: 4px; + display: inline-block; + float: left; + height: 22px; + margin: -2px 5px 0 0; + overflow: hidden; + padding: 0; + width: 22px; + } + + .window-titlebar .visitor-avatar img { + height: 100%; + max-width: 30px; + } + + .window-titlebar .visitor-displayname { + color: #fff; + display: inline-block; + float: left; + font-size: 14px; + font-weight: bold; + margin: 0 5px; + max-width: 300px; + overflow: hidden; + padding: 0; + text-overflow: ellipsis; + text-transform: uppercase; + white-space: nowrap; + } + + .window-titlebar .icon-info { + display: inline-block; + float: left; + height: 16px; + margin: 3px; + width: 16px; + } + + .window-titlebar .visitor-country { + width: 20px; + } + + .window-titlebar .visitor-os { + background-image: url("images/os.png"); + background-position: -110px 0; + } + + .window-titlebar .visitor-os.Windows { + background-position: 0 0; + } + + .window-titlebar .visitor-os.Android { + background-position: -63px 0; + } + + .window-titlebar .visitor-os.iOS { + background-position: -45px 0; + } + + .window-titlebar .visitor-os.Linux { + background-position: -31px 0; + } + + .window-titlebar .visitor-os.Mac { + background-position: -15px 0; + } + + .window-titlebar .visitor-browser { + background-image: url("images/browsers.png"); + background-position: -47px 0; + } + + .window-titlebar .visitor-browser.Chrome { + background-position: 0 0; + } + + .window-titlebar .visitor-browser.Firefox { + background-position: -16px 0; + } + + .window-titlebar .visitor-browser.Opera { + background-position: -31px 0; + } + + .window-titlebar .visitor-browser.IE, .window-titlebar .visitor-browser.Edge { + background-position: -64px 0; + } + + .window-titlebar .visitor-browser.Safari { + background-position: -79px 0; + } + + .window-titlebar .window-button { + background: #666666 none repeat scroll 0 0; + border: 1px solid #222; + border-radius: 50%; + box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.2) inset; + color: #fff; + cursor: pointer; + display: inline-block; + float: right; + font-size: 14px; + font-weight: 700; + height: 22px; + line-height: 18px; + margin: 0 0 0 2px; + text-align: center; + width: 22px; + } + + .window-titlebar .window-button:hover { + background: #888888 none repeat scroll 0 0; + } + + .window-titlebar .livechat-action { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #686868, #5f5f5f) repeat scroll 0 0; + border: 1px solid #222; + border-radius: 3px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05), 0 1px rgba(255, 255, 255, 0.1) inset; + float: right; + font-size: 12px; + height: 23px; + line-height: normal; + margin: -1px 5px 0; + padding: 2px 0 0 3px; + position: relative; + width: 110px; + } + + .window-titlebar .livechat-action:hover { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #787878, #6f6f6f) repeat scroll 0 0; + } + + .window-titlebar .livechat-action.cust-sel::before { + color: #fff; + top: 1px; + } + + .window-titlebar .livechat-action select { + -webkit-appearance: none; + -moz-appearance: none; + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + border: medium none; + box-shadow: none; + color: #fff; + cursor: pointer; + padding: 0; + width: 100%; + } + +.livechat-body { + background: #f0f0f0 none repeat scroll 0 0; + height: calc(100% - 50px); +} + +.livechat-tabs { + display: list-item; + float: left; + margin: 0; + padding: 10px; + width: 50%; +} + + .livechat-tabs > li { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + border-color: #d9d9d9; + border-image: none; + border-style: solid; + border-width: 1px 1px 1px 0; + box-shadow: 1px 0 rgba(255, 255, 255, 1) inset, 0 1px 0 rgba(0, 0, 0, 0.05); + color: #666666; + cursor: pointer; + display: inline-block; + float: left; + font-size: 11px; + font-weight: bold; + line-height: 22px; + padding: 0 12px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + } + + .livechat-tabs > li.active { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #dfdfdf, #d7d7d7) repeat scroll 0 0; + border-top: 1px solid #bbb; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) inset, 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 0 rgba(255, 255, 255, 0.5); + color: #666; + cursor: default; + } + + .livechat-tabs > li:first-child { + border-left: 1px solid #d9d9d9; + border-radius: 3px 0 0 3px; + } + + .livechat-tabs > li:last-child { + border-radius: 0 3px 3px 0; + } + +.livechat-side { + box-sizing: border-box; + float: right; + height: 100%; + padding: 12px 10px; + width: 300px; +} + + .livechat-side .visitor-avatar { + background: #314f7f none repeat scroll 0 0; + border-radius: 5px; + display: inline-block; + float: left; + height: 50px; + margin: -2px 5px 0 0; + overflow: hidden; + padding: 0; + width: 50px; + } + + .livechat-side .visitor-avatar img { + height: 100%; + max-width: 60px; + } + + .livechat-side .visitor-displayname { + color: #333333; + display: inline-block; + font-size: 18px; + line-height: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 220px; + } + + .livechat-side .visitor-email { + color: #576263; + display: inline-block; + font-size: 12px; + margin-top: 2px; + text-overflow: ellipsis; + } + + .livechat-side .split { + border-top: 1px solid #e5e5e5; + box-shadow: 0 1px rgba(255, 255, 255, 0.65) inset; + padding: 10px 0; + } + + .livechat-side .statistics { + display: table; + margin: 15px 0 0; + padding: 15px 0 0; + text-transform: uppercase; + width: 100%; + } + + .livechat-side .statistics.split > li { + background: #fafafa none repeat scroll 0 0; + border: 1px solid #e5e5e5; + border-radius: 0; + color: #888; + float: left; + font-size: 10px; + list-style: outside none none; + margin: 0; + padding: 10px; + width: 33%; + } + + .livechat-side .statistics.split > li:first-child { + border-left: 1px solid #e5e5e5; + border-radius: 3px 0 0 3px; + border-right: medium none; + } + + .livechat-side .statistics.split > li:last-child { + border-left: medium none; + border-radius: 0 3px 3px 0; + width: 34%; + } + + .livechat-side .statistics.split > li .val { + color: #222; + display: block; + font-size: 15px; + font-weight: bold; + text-transform: none; + } + + .livechat-side .sideinfo { + background: #fafafa none repeat scroll 0 0; + border: 1px solid #e5e5e5; + box-sizing: border-box; + font-size: 12px; + margin-top: 10px; + padding: 10px; + width: 100%; + } + + .livechat-side .sideinfo > h5 { + color: #888; + font-size: 10px; + margin: 10px 0 3px; + } + + .livechat-side .sideinfo > h5:first-child { + margin-top: 0; + } + + .livechat-side .sideinfo .val { + color: #222; + font-size: 12px; + } + +.livechat-content { + background: #fff none repeat scroll 0 0; + border: 1px solid #dfdfdf; + box-sizing: border-box; + float: left; + height: calc(100% - 20px); + margin: 10px 0 10px 10px; + padding: 0; + position: relative; + width: calc(100% - 310px); +} + + .livechat-content .google-translate { + border-bottom: 1px solid #dfdfdf; + box-sizing: border-box; + display: none; + padding: 10px; + width: 100%; + } + + .livechat-content .google-translate > h3 { + float: left; + font-size: 12px; + line-height: 18px; + margin: 5px 8px 0 0; + } + + .livechat-content .google-translate .languages { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + border: 1px solid #d8d8d8; + border-radius: 3px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05), 0 1px rgba(255, 255, 255, 0.75) inset; + float: left; + font-size: 12px; + height: 25px; + line-height: normal; + margin: -1px 5px 0; + padding: 3px 0 0 3px; + position: relative; + width: 110px; + } + + .livechat-content .google-translate .languages:hover { + opacity: 0.8; + } + + .livechat-content .google-translate .languages select { + -moz-appearance: none; + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + border: medium none; + color: #666666; + cursor: pointer; + width: 100%; + } + + .livechat-content .google-translate .btn-translate { + background: #4d9fd2 none repeat scroll 0 0; + border: 1px solid #4382a8; + border-radius: 3px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05), 0 1px rgba(255, 255, 255, 0.25) inset; + color: #fff; + cursor: pointer; + fill: #666666; + float: left; + font-size: 11px; + font-weight: bold; + margin-left: 8px; + outline-style: none; + padding: 4px 10px 2px; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + } + + .livechat-content .google-translate .btn-translate.btn-dismiss { + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #efefef) repeat scroll 0 0; + border: 1px solid #d8d8d8; + color: #666666; + } + + .livechat-content .google-translate .btn-translate:hover { + opacity: 0.8; + } + +.livechat-messages { + box-sizing: border-box; + height: calc(100% - 120px); + list-style: outside none none; + margin: 0; + overflow-x: hidden; + overflow-y: auto; + padding: 0 10px; + width: 100%; +} + + .livechat-messages .message-notify { + border-bottom: 1px dashed silver; + box-sizing: border-box; + color: gray; + margin-bottom: 10px; + padding: 5px; + text-align: center; + } + + .livechat-messages .message { + border-bottom: 1px dotted silver; + margin: 2px 0 10px; + padding-bottom: 5px; + } + + .livechat-messages .message:last-child { + border: medium none; + } + + .livechat-messages .message.system-message { + text-align: center; + } + + .livechat-messages .message.system-message p { + color: #a5a5a5; + font-style: italic; + margin: 0; + } + + .livechat-messages .message .sender-displayname { + color: #222; + display: block; + font-weight: bold; + margin-bottom: 3px; + } + + .livechat-messages .message > p { + color: #222; + display: block; + font-weight: normal; + line-height: normal; + margin: 0; + } + +.visitor-istyping { + bottom: 125px; + color: #a3a0a0; + font-style: italic; + position: absolute; + text-align: center; + width: 100%; +} + +.message-editor { + border-top: 1px solid #dfdfdf; + position: relative; + height: 120px; + width: 100%; +} + + .message-editor .start-chat-wrapper { + background: rgba(20, 20, 20, 0.44) none repeat scroll 0 0; + color: #fff; + font-size: 20px; + font-style: italic; + height: 100%; + left: 0; + line-height: 50px; + position: absolute; + text-align: center; + text-shadow: 0 0 2px #040404; + top: 0; + width: 100%; + } + + .message-editor textarea { + background: #fff none repeat scroll 0 0; + border-color: -moz-use-text-color; + border-style: none; + border-width: medium; + box-shadow: none; + box-sizing: border-box; + height: 120px; + padding: 10px; + resize: none; + width: 100%; + } + + .message-editor textarea:disabled { + background: #eeeded none repeat scroll 0 0; + } + +.livechat-buttons { + bottom: 0; + left: 150px; + position: fixed; + width: calc(100% - 150px); + z-index: 999999; +} + + .livechat-buttons .livechat-button { + background: #333333 none repeat scroll 0 0; + border: 1px solid #232628; + border-radius: 3px 3px 0 0; + cursor: pointer; + float: left; + height: 30px; + margin: 5px 7px 0 0; + padding: 5px 5px 15px; + position: relative; + transition: padding 0.15s ease-in-out 0s,margin 0.15s ease-in-out 0s; + width: 170px; + } + + .livechat-buttons .livechat-button:hover { + background: #f78e3f none repeat scroll 0 0; + border: solid 1px #804500; + } + + .livechat-buttons .livechat-button.active { + background: #222222 none repeat scroll 0 0; + margin-top: -2px; + padding-bottom: 30px; + } + + .livechat-buttons .livechat-button.visitor-isoffline { + background: #b8b1b1 none repeat scroll 0 0; + border: 1px solid #9f9f9f; + opacity: 0.7; + } + + .livechat-buttons .livechat-button .visitor-avatar { + background: #eee none repeat scroll 0 0; + border-radius: 4px; + display: inline-block; + float: left; + height: 22px; + margin: -2px 5px 0 0; + overflow: hidden; + padding: 0; + width: 22px; + } + + .livechat-buttons .livechat-button .visitor-avatar img { + height: 100%; + max-width: 30px; + } + + .livechat-buttons .livechat-button .visitor-displayname { + color: #fff; + display: inline-block; + float: left; + font-size: 12px; + font-weight: bold; + line-height: 20px; + margin: 0 3px; + max-width: 300px; + overflow: hidden; + padding: 0; + text-overflow: ellipsis; + white-space: nowrap; + width: 120px; + } + + .livechat-buttons .livechat-button .btn { + background: #666666 none repeat scroll 0 0; + border: 1px solid #222; + border-radius: 50%; + box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.2) inset; + color: #fff; + display: inline-block; + font-size: 11px; + font-weight: 700; + height: 25px; + line-height: 13px; + padding: 5px; + position: absolute; + right: 2px; + text-align: center; + top: 2px; + width: 25px; + } + + .livechat-buttons .livechat-button .btn-close { + font-size: 13px; + z-index: 999; + } + + .livechat-buttons .livechat-button:hover .btn-close { + z-index: 1001; + } + + .livechat-buttons .livechat-button .unread-messages { + z-index: 1000; + } + +@keyframes minimize { + 0% { + transform: scale3d(1,1,1); + } + + 50% { + opacity: 0.5; + } + + 100% { + transform: scale3d(0.5,0.5,0); + opacity: 0; + transform-origin: bottom; + } +} + +@keyframes maximize { + 0% { + opacity: 0; + transform: scale3d(0.5,0.5,0); + transform-origin: bottom; + } + + 50% { + opacity: 0.5; + } + + 100% { + opacity: 1; + transform: scale3d(1,1,1); + } +} diff --git a/LiveChat/Styles/material-design-iconic-font.min.css b/LiveChat/Styles/material-design-iconic-font.min.css new file mode 100644 index 0000000..f624891 --- /dev/null +++ b/LiveChat/Styles/material-design-iconic-font.min.css @@ -0,0 +1,5 @@ +/*! + * Material Design Iconic Font 1.0.1 by Sergey Kupletsky (@zavoloklom) - http://zavoloklom.github.io/material-design-iconic-font/ + * License - https://github.com/zavoloklom/material-design-iconic-font/blob/gh-pages/License.md (Attribution-ShareAlike 4.0 International license) + */ +@font-face{font-family:'Material Design Iconic Font';src:url(fonts/Material-Design-Iconic-Font.eot?v=1.0.1);src:url(fonts/Material-Design-Iconic-Font.eot?#iefix&v=1.0.1) format('embedded-opentype'),url(fonts/Material-Design-Iconic-Font.woff?v=1.0.1) format('woff'),url(fonts/Material-Design-Iconic-Font.ttf?v=1.0.1) format('truetype'),url(fonts/Material-Design-Iconic-Font.svg?v=1.0.1#Material-Design-Iconic-Font) format('svg');font-weight:400;font-style:normal}[class*=" md-"],[class^=md-]{display:inline-block;font:normal normal normal 14px/1 'Material Design Iconic Font';font-size:inherit;speak:none;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.md{line-height:inherit;vertical-align:bottom}.md-lg{font-size:1.5em;line-height:.5em;vertical-align:-35%}.md-2x{font-size:2em}.md-3x{font-size:3em}.md-4x{font-size:4em}.md-5x{font-size:5em}.md-border{padding:.2em .25em .15em;border:.08em solid gray;border-radius:.1em}.md-border-circle{padding:.2em .25em .15em;border:.08em solid gray;border-radius:50%}[class*=" md-"].pull-left,[class^=md-].pull-left{float:left;margin-right:.3em}[class*=" md-"].pull-right,[class^=md-].pull-right{float:right;margin-left:.3em}.md-spin{-webkit-animation:md-spin 1.5s infinite linear;animation:md-spin 1.5s infinite linear}.md-spin-reverse{-webkit-animation:md-spin-reverse 1.5s infinite linear;animation:md-spin-reverse 1.5s infinite linear}@-webkit-keyframes md-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes md-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes md-spin-reverse{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(-359deg);transform:rotate(-359deg)}}@keyframes md-spin-reverse{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(-359deg);transform:rotate(-359deg)}}.md-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.md-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.md-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.md-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.md-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .md-flip-horizontal,:root .md-flip-vertical,:root .md-rotate-180,:root .md-rotate-270,:root .md-rotate-90{filter:none}.md-3d-rotation:before{content:"\f000"}.md-accessibility:before{content:"\f001"}.md-account-balance:before{content:"\f002"}.md-account-balance-wallet:before{content:"\f003"}.md-account-box:before{content:"\f004"}.md-account-child:before{content:"\f005"}.md-account-circle:before{content:"\f006"}.md-add-shopping-cart:before{content:"\f007"}.md-alarm:before{content:"\f008"}.md-alarm-add:before{content:"\f009"}.md-alarm-off:before{content:"\f00a"}.md-alarm-on:before{content:"\f00b"}.md-android:before{content:"\f00c"}.md-announcement:before{content:"\f00d"}.md-aspect-ratio:before{content:"\f00e"}.md-assessment:before{content:"\f00f"}.md-assignment:before{content:"\f010"}.md-assignment-ind:before{content:"\f011"}.md-assignment-late:before{content:"\f012"}.md-assignment-return:before{content:"\f013"}.md-assignment-returned:before{content:"\f014"}.md-assignment-turned-in:before{content:"\f015"}.md-autorenew:before{content:"\f016"}.md-backup:before{content:"\f017"}.md-book:before{content:"\f018"}.md-bookmark:before{content:"\f019"}.md-bookmark-outline:before{content:"\f01a"}.md-bug-report:before{content:"\f01b"}.md-cached:before{content:"\f01c"}.md-class:before{content:"\f01d"}.md-credit-card:before{content:"\f01e"}.md-dashboard:before{content:"\f01f"}.md-delete:before{content:"\f020"}.md-description:before{content:"\f021"}.md-dns:before{content:"\f022"}.md-done:before{content:"\f023"}.md-done-all:before{content:"\f024"}.md-event:before{content:"\f025"}.md-exit-to-app:before{content:"\f026"}.md-explore:before{content:"\f027"}.md-extension:before{content:"\f028"}.md-face-unlock:before{content:"\f029"}.md-favorite:before{content:"\f02a"}.md-favorite-outline:before{content:"\f02b"}.md-find-in-page:before{content:"\f02c"}.md-find-replace:before{content:"\f02d"}.md-flip-to-back:before{content:"\f02e"}.md-flip-to-front:before{content:"\f02f"}.md-get-app:before{content:"\f030"}.md-grade:before{content:"\f031"}.md-group-work:before{content:"\f032"}.md-help:before{content:"\f033"}.md-highlight-remove:before{content:"\f034"}.md-history:before{content:"\f035"}.md-home:before{content:"\f036"}.md-https:before{content:"\f037"}.md-info:before{content:"\f038"}.md-info-outline:before{content:"\f039"}.md-input:before{content:"\f03a"}.md-invert-colors:before{content:"\f03b"}.md-label:before{content:"\f03c"}.md-label-outline:before{content:"\f03d"}.md-language:before{content:"\f03e"}.md-launch:before{content:"\f03f"}.md-list:before{content:"\f040"}.md-lock:before{content:"\f041"}.md-lock-open:before{content:"\f042"}.md-lock-outline:before{content:"\f043"}.md-loyalty:before{content:"\f044"}.md-markunread-mailbox:before{content:"\f045"}.md-note-add:before{content:"\f046"}.md-open-in-browser:before{content:"\f047"}.md-open-in-new:before{content:"\f048"}.md-open-with:before{content:"\f049"}.md-pageview:before{content:"\f04a"}.md-payment:before{content:"\f04b"}.md-perm-camera-mic:before{content:"\f04c"}.md-perm-contact-cal:before{content:"\f04d"}.md-perm-data-setting:before{content:"\f04e"}.md-perm-device-info:before{content:"\f04f"}.md-perm-identity:before{content:"\f050"}.md-perm-media:before{content:"\f051"}.md-perm-phone-msg:before{content:"\f052"}.md-perm-scan-wifi:before{content:"\f053"}.md-picture-in-picture:before{content:"\f054"}.md-polymer:before{content:"\f055"}.md-print:before{content:"\f056"}.md-query-builder:before{content:"\f057"}.md-question-answer:before{content:"\f058"}.md-receipt:before{content:"\f059"}.md-redeem:before{content:"\f05a"}.md-report-problem:before{content:"\f05b"}.md-restore:before{content:"\f05c"}.md-room:before{content:"\f05d"}.md-schedule:before{content:"\f05e"}.md-search:before{content:"\f05f"}.md-settings:before{content:"\f060"}.md-settings-applications:before{content:"\f061"}.md-settings-backup-restore:before{content:"\f062"}.md-settings-bluetooth:before{content:"\f063"}.md-settings-cell:before{content:"\f064"}.md-settings-display:before{content:"\f065"}.md-settings-ethernet:before{content:"\f066"}.md-settings-input-antenna:before{content:"\f067"}.md-settings-input-component:before{content:"\f068"}.md-settings-input-composite:before{content:"\f069"}.md-settings-input-hdmi:before{content:"\f06a"}.md-settings-input-svideo:before{content:"\f06b"}.md-settings-overscan:before{content:"\f06c"}.md-settings-phone:before{content:"\f06d"}.md-settings-power:before{content:"\f06e"}.md-settings-remote:before{content:"\f06f"}.md-settings-voice:before{content:"\f070"}.md-shop:before{content:"\f071"}.md-shopping-basket:before{content:"\f072"}.md-shopping-cart:before{content:"\f073"}.md-shop-two:before{content:"\f074"}.md-speaker-notes:before{content:"\f075"}.md-spellcheck:before{content:"\f076"}.md-star-rate:before{content:"\f077"}.md-stars:before{content:"\f078"}.md-store:before{content:"\f079"}.md-subject:before{content:"\f07a"}.md-swap-horiz:before{content:"\f07b"}.md-swap-vert:before{content:"\f07c"}.md-swap-vert-circle:before{content:"\f07d"}.md-system-update-tv:before{content:"\f07e"}.md-tab:before{content:"\f07f"}.md-tab-unselected:before{content:"\f080"}.md-theaters:before{content:"\f081"}.md-thumb-down:before{content:"\f082"}.md-thumbs-up-down:before{content:"\f083"}.md-thumb-up:before{content:"\f084"}.md-toc:before{content:"\f085"}.md-today:before{content:"\f086"}.md-track-changes:before{content:"\f087"}.md-translate:before{content:"\f088"}.md-trending-down:before{content:"\f089"}.md-trending-neutral:before{content:"\f08a"}.md-trending-up:before{content:"\f08b"}.md-turned-in:before{content:"\f08c"}.md-turned-in-not:before{content:"\f08d"}.md-verified-user:before{content:"\f08e"}.md-view-agenda:before{content:"\f08f"}.md-view-array:before{content:"\f090"}.md-view-carousel:before{content:"\f091"}.md-view-column:before{content:"\f092"}.md-view-day:before{content:"\f093"}.md-view-headline:before{content:"\f094"}.md-view-list:before{content:"\f095"}.md-view-module:before{content:"\f096"}.md-view-quilt:before{content:"\f097"}.md-view-stream:before{content:"\f098"}.md-view-week:before{content:"\f099"}.md-visibility:before{content:"\f09a"}.md-visibility-off:before{content:"\f09b"}.md-wallet-giftcard:before{content:"\f09c"}.md-wallet-membership:before{content:"\f09d"}.md-wallet-travel:before{content:"\f09e"}.md-work:before{content:"\f09f"}.md-error:before{content:"\f0a0"}.md-warning:before{content:"\f0a1"}.md-album:before{content:"\f0a2"}.md-av-timer:before{content:"\f0a3"}.md-closed-caption:before{content:"\f0a4"}.md-equalizer:before{content:"\f0a5"}.md-explicit:before{content:"\f0a6"}.md-fast-forward:before{content:"\f0a7"}.md-fast-rewind:before{content:"\f0a8"}.md-games:before{content:"\f0a9"}.md-hearing:before{content:"\f0aa"}.md-high-quality:before{content:"\f0ab"}.md-loop:before{content:"\f0ac"}.md-mic:before{content:"\f0ad"}.md-mic-none:before{content:"\f0ae"}.md-mic-off:before{content:"\f0af"}.md-movie:before{content:"\f0b0"}.md-my-library-add:before{content:"\f0b1"}.md-my-library-books:before{content:"\f0b2"}.md-my-library-music:before{content:"\f0b3"}.md-new-releases:before{content:"\f0b4"}.md-not-interested:before{content:"\f0b5"}.md-pause:before{content:"\f0b6"}.md-pause-circle-fill:before{content:"\f0b7"}.md-pause-circle-outline:before{content:"\f0b8"}.md-play-arrow:before{content:"\f0b9"}.md-play-circle-fill:before{content:"\f0ba"}.md-play-circle-outline:before{content:"\f0bb"}.md-playlist-add:before{content:"\f0bc"}.md-play-shopping-bag:before{content:"\f0bd"}.md-queue:before{content:"\f0be"}.md-queue-music:before{content:"\f0bf"}.md-radio:before{content:"\f0c0"}.md-recent-actors:before{content:"\f0c1"}.md-repeat:before{content:"\f0c2"}.md-repeat-one:before{content:"\f0c3"}.md-replay:before{content:"\f0c4"}.md-shuffle:before{content:"\f0c5"}.md-skip-next:before{content:"\f0c6"}.md-skip-previous:before{content:"\f0c7"}.md-snooze:before{content:"\f0c8"}.md-stop:before{content:"\f0c9"}.md-subtitles:before{content:"\f0ca"}.md-surround-sound:before{content:"\f0cb"}.md-videocam:before{content:"\f0cc"}.md-videocam-off:before{content:"\f0cd"}.md-video-collection:before{content:"\f0ce"}.md-volume-down:before{content:"\f0cf"}.md-volume-mute:before{content:"\f0d0"}.md-volume-off:before{content:"\f0d1"}.md-volume-up:before{content:"\f0d2"}.md-web:before{content:"\f0d3"}.md-business:before{content:"\f0d4"}.md-call:before{content:"\f0d5"}.md-call-end:before{content:"\f0d6"}.md-call-made:before{content:"\f0d7"}.md-call-merge:before{content:"\f0d8"}.md-call-missed:before{content:"\f0d9"}.md-call-received:before{content:"\f0da"}.md-call-split:before{content:"\f0db"}.md-chat:before{content:"\f0dc"}.md-clear-all:before{content:"\f0dd"}.md-comment:before{content:"\f0de"}.md-contacts:before{content:"\f0df"}.md-dialer-sip:before{content:"\f0e0"}.md-dialpad:before{content:"\f0e1"}.md-dnd-on:before{content:"\f0e2"}.md-email:before{content:"\f0e3"}.md-forum:before{content:"\f0e4"}.md-import-export:before{content:"\f0e5"}.md-invert-colors-off:before{content:"\f0e6"}.md-invert-colors-on:before{content:"\f0e7"}.md-live-help:before{content:"\f0e8"}.md-location-off:before{content:"\f0e9"}.md-location-on:before{content:"\f0ea"}.md-message:before{content:"\f0eb"}.md-messenger:before{content:"\f0ec"}.md-no-sim:before{content:"\f0ed"}.md-phone:before{content:"\f0ee"}.md-portable-wifi-off:before{content:"\f0ef"}.md-quick-contacts-dialer:before{content:"\f0f0"}.md-quick-contacts-mail:before{content:"\f0f1"}.md-ring-volume:before{content:"\f0f2"}.md-stay-current-landscape:before{content:"\f0f3"}.md-stay-current-portrait:before{content:"\f0f4"}.md-stay-primary-landscape:before{content:"\f0f5"}.md-stay-primary-portrait:before{content:"\f0f6"}.md-swap-calls:before{content:"\f0f7"}.md-textsms:before{content:"\f0f8"}.md-voicemail:before{content:"\f0f9"}.md-vpn-key:before{content:"\f0fa"}.md-add:before{content:"\f0fb"}.md-add-box:before{content:"\f0fc"}.md-add-circle:before{content:"\f0fd"}.md-add-circle-outline:before{content:"\f0fe"}.md-archive:before{content:"\f0ff"}.md-backspace:before{content:"\f100"}.md-block:before{content:"\f101"}.md-clear:before{content:"\f102"}.md-content-copy:before{content:"\f103"}.md-content-cut:before{content:"\f104"}.md-content-paste:before{content:"\f105"}.md-create:before{content:"\f106"}.md-drafts:before{content:"\f107"}.md-filter-list:before{content:"\f108"}.md-flag:before{content:"\f109"}.md-forward:before{content:"\f10a"}.md-gesture:before{content:"\f10b"}.md-inbox:before{content:"\f10c"}.md-link:before{content:"\f10d"}.md-mail:before{content:"\f10e"}.md-markunread:before{content:"\f10f"}.md-redo:before{content:"\f110"}.md-remove:before{content:"\f111"}.md-remove-circle:before{content:"\f112"}.md-remove-circle-outline:before{content:"\f113"}.md-reply:before{content:"\f114"}.md-reply-all:before{content:"\f115"}.md-report:before{content:"\f116"}.md-save:before{content:"\f117"}.md-select-all:before{content:"\f118"}.md-send:before{content:"\f119"}.md-sort:before{content:"\f11a"}.md-text-format:before{content:"\f11b"}.md-undo:before{content:"\f11c"}.md-access-alarm:before{content:"\f11d"}.md-access-alarms:before{content:"\f11e"}.md-access-time:before{content:"\f11f"}.md-add-alarm:before{content:"\f120"}.md-airplanemode-off:before{content:"\f121"}.md-airplanemode-on:before{content:"\f122"}.md-battery-20:before{content:"\f123"}.md-battery-30:before{content:"\f124"}.md-battery-50:before{content:"\f125"}.md-battery-60:before{content:"\f126"}.md-battery-80:before{content:"\f127"}.md-battery-90:before{content:"\f128"}.md-battery-alert:before{content:"\f129"}.md-battery-charging-20:before{content:"\f12a"}.md-battery-charging-30:before{content:"\f12b"}.md-battery-charging-50:before{content:"\f12c"}.md-battery-charging-60:before{content:"\f12d"}.md-battery-charging-80:before{content:"\f12e"}.md-battery-charging-90:before{content:"\f12f"}.md-battery-charging-full:before{content:"\f130"}.md-battery-full:before{content:"\f131"}.md-battery-std:before{content:"\f132"}.md-battery-unknown:before{content:"\f133"}.md-bluetooth:before{content:"\f134"}.md-bluetooth-connected:before{content:"\f135"}.md-bluetooth-disabled:before{content:"\f136"}.md-bluetooth-searching:before{content:"\f137"}.md-brightness-auto:before{content:"\f138"}.md-brightness-high:before{content:"\f139"}.md-brightness-low:before{content:"\f13a"}.md-brightness-medium:before{content:"\f13b"}.md-data-usage:before{content:"\f13c"}.md-developer-mode:before{content:"\f13d"}.md-devices:before{content:"\f13e"}.md-dvr:before{content:"\f13f"}.md-gps-fixed:before{content:"\f140"}.md-gps-not-fixed:before{content:"\f141"}.md-gps-off:before{content:"\f142"}.md-location-disabled:before{content:"\f143"}.md-location-searching:before{content:"\f144"}.md-multitrack-audio:before{content:"\f145"}.md-network-cell:before{content:"\f146"}.md-network-wifi:before{content:"\f147"}.md-nfc:before{content:"\f148"}.md-now-wallpaper:before{content:"\f149"}.md-now-widgets:before{content:"\f14a"}.md-screen-lock-landscape:before{content:"\f14b"}.md-screen-lock-portrait:before{content:"\f14c"}.md-screen-lock-rotation:before{content:"\f14d"}.md-screen-rotation:before{content:"\f14e"}.md-sd-storage:before{content:"\f14f"}.md-settings-system-daydream:before{content:"\f150"}.md-signal-cellular-0-bar:before{content:"\f151"}.md-signal-cellular-1-bar:before{content:"\f152"}.md-signal-cellular-2-bar:before{content:"\f153"}.md-signal-cellular-3-bar:before{content:"\f154"}.md-signal-cellular-4-bar:before{content:"\f155"}.md-signal-cellular-connected-no-internet-0-bar:before{content:"\f156"}.md-signal-cellular-connected-no-internet-1-bar:before{content:"\f157"}.md-signal-cellular-connected-no-internet-2-bar:before{content:"\f158"}.md-signal-cellular-connected-no-internet-3-bar:before{content:"\f159"}.md-signal-cellular-connected-no-internet-4-bar:before{content:"\f15a"}.md-signal-cellular-no-sim:before{content:"\f15b"}.md-signal-cellular-null:before{content:"\f15c"}.md-signal-cellular-off:before{content:"\f15d"}.md-signal-wifi-0-bar:before{content:"\f15e"}.md-signal-wifi-1-bar:before{content:"\f15f"}.md-signal-wifi-2-bar:before{content:"\f160"}.md-signal-wifi-3-bar:before{content:"\f161"}.md-signal-wifi-4-bar:before{content:"\f162"}.md-signal-wifi-off:before{content:"\f163"}.md-storage:before{content:"\f164"}.md-usb:before{content:"\f165"}.md-wifi-lock:before{content:"\f166"}.md-wifi-tethering:before{content:"\f167"}.md-attach-file:before{content:"\f168"}.md-attach-money:before{content:"\f169"}.md-border-all:before{content:"\f16a"}.md-border-bottom:before{content:"\f16b"}.md-border-clear:before{content:"\f16c"}.md-border-color:before{content:"\f16d"}.md-border-horizontal:before{content:"\f16e"}.md-border-inner:before{content:"\f16f"}.md-border-left:before{content:"\f170"}.md-border-outer:before{content:"\f171"}.md-border-right:before{content:"\f172"}.md-border-style:before{content:"\f173"}.md-border-top:before{content:"\f174"}.md-border-vertical:before{content:"\f175"}.md-format-align-center:before{content:"\f176"}.md-format-align-justify:before{content:"\f177"}.md-format-align-left:before{content:"\f178"}.md-format-align-right:before{content:"\f179"}.md-format-bold:before{content:"\f17a"}.md-format-clear:before{content:"\f17b"}.md-format-color-fill:before{content:"\f17c"}.md-format-color-reset:before{content:"\f17d"}.md-format-color-text:before{content:"\f17e"}.md-format-indent-decrease:before{content:"\f17f"}.md-format-indent-increase:before{content:"\f180"}.md-format-italic:before{content:"\f181"}.md-format-line-spacing:before{content:"\f182"}.md-format-list-bulleted:before{content:"\f183"}.md-format-list-numbered:before{content:"\f184"}.md-format-paint:before{content:"\f185"}.md-format-quote:before{content:"\f186"}.md-format-size:before{content:"\f187"}.md-format-strikethrough:before{content:"\f188"}.md-format-textdirection-l-to-r:before{content:"\f189"}.md-format-textdirection-r-to-l:before{content:"\f18a"}.md-format-underline:before{content:"\f18b"}.md-functions:before{content:"\f18c"}.md-insert-chart:before{content:"\f18d"}.md-insert-comment:before{content:"\f18e"}.md-insert-drive-file:before{content:"\f18f"}.md-insert-emoticon:before{content:"\f190"}.md-insert-invitation:before{content:"\f191"}.md-insert-link:before{content:"\f192"}.md-insert-photo:before{content:"\f193"}.md-merge-type:before{content:"\f194"}.md-mode-comment:before{content:"\f195"}.md-mode-edit:before{content:"\f196"}.md-publish:before{content:"\f197"}.md-vertical-align-bottom:before{content:"\f198"}.md-vertical-align-center:before{content:"\f199"}.md-vertical-align-top:before{content:"\f19a"}.md-wrap-text:before{content:"\f19b"}.md-attachment:before{content:"\f19c"}.md-cloud:before{content:"\f19d"}.md-cloud-circle:before{content:"\f19e"}.md-cloud-done:before{content:"\f19f"}.md-cloud-download:before{content:"\f1a0"}.md-cloud-off:before{content:"\f1a1"}.md-cloud-queue:before{content:"\f1a2"}.md-cloud-upload:before{content:"\f1a3"}.md-file-download:before{content:"\f1a4"}.md-file-upload:before{content:"\f1a5"}.md-folder:before{content:"\f1a6"}.md-folder-open:before{content:"\f1a7"}.md-folder-shared:before{content:"\f1a8"}.md-cast:before{content:"\f1a9"}.md-cast-connected:before{content:"\f1aa"}.md-computer:before{content:"\f1ab"}.md-desktop-mac:before{content:"\f1ac"}.md-desktop-windows:before{content:"\f1ad"}.md-dock:before{content:"\f1ae"}.md-gamepad:before{content:"\f1af"}.md-headset:before{content:"\f1b0"}.md-headset-mic:before{content:"\f1b1"}.md-keyboard:before{content:"\f1b2"}.md-keyboard-alt:before{content:"\f1b3"}.md-keyboard-arrow-down:before{content:"\f1b4"}.md-keyboard-arrow-left:before{content:"\f1b5"}.md-keyboard-arrow-right:before{content:"\f1b6"}.md-keyboard-arrow-up:before{content:"\f1b7"}.md-keyboard-backspace:before{content:"\f1b8"}.md-keyboard-capslock:before{content:"\f1b9"}.md-keyboard-control:before{content:"\f1ba"}.md-keyboard-hide:before{content:"\f1bb"}.md-keyboard-return:before{content:"\f1bc"}.md-keyboard-tab:before{content:"\f1bd"}.md-keyboard-voice:before{content:"\f1be"}.md-laptop:before{content:"\f1bf"}.md-laptop-chromebook:before{content:"\f1c0"}.md-laptop-mac:before{content:"\f1c1"}.md-laptop-windows:before{content:"\f1c2"}.md-memory:before{content:"\f1c3"}.md-mouse:before{content:"\f1c4"}.md-phone-android:before{content:"\f1c5"}.md-phone-iphone:before{content:"\f1c6"}.md-phonelink:before{content:"\f1c7"}.md-phonelink-off:before{content:"\f1c8"}.md-security:before{content:"\f1c9"}.md-sim-card:before{content:"\f1ca"}.md-smartphone:before{content:"\f1cb"}.md-speaker:before{content:"\f1cc"}.md-tablet:before{content:"\f1cd"}.md-tablet-android:before{content:"\f1ce"}.md-tablet-mac:before{content:"\f1cf"}.md-tv:before{content:"\f1d0"}.md-watch:before{content:"\f1d1"}.md-add-to-photos:before{content:"\f1d2"}.md-adjust:before{content:"\f1d3"}.md-assistant-photo:before{content:"\f1d4"}.md-audiotrack:before{content:"\f1d5"}.md-blur-circular:before{content:"\f1d6"}.md-blur-linear:before{content:"\f1d7"}.md-blur-off:before{content:"\f1d8"}.md-blur-on:before{content:"\f1d9"}.md-brightness-1:before{content:"\f1da"}.md-brightness-2:before{content:"\f1db"}.md-brightness-3:before{content:"\f1dc"}.md-brightness-4:before{content:"\f1dd"}.md-brightness-5:before{content:"\f1de"}.md-brightness-6:before{content:"\f1df"}.md-brightness-7:before{content:"\f1e0"}.md-brush:before{content:"\f1e1"}.md-camera:before{content:"\f1e2"}.md-camera-alt:before{content:"\f1e3"}.md-camera-front:before{content:"\f1e4"}.md-camera-rear:before{content:"\f1e5"}.md-camera-roll:before{content:"\f1e6"}.md-center-focus-strong:before{content:"\f1e7"}.md-center-focus-weak:before{content:"\f1e8"}.md-collections:before{content:"\f1e9"}.md-colorize:before{content:"\f1ea"}.md-color-lens:before{content:"\f1eb"}.md-compare:before{content:"\f1ec"}.md-control-point:before{content:"\f1ed"}.md-control-point-duplicate:before{content:"\f1ee"}.md-crop:before{content:"\f1ef"}.md-crop-3-2:before{content:"\f1f0"}.md-crop-5-4:before{content:"\f1f1"}.md-crop-7-5:before{content:"\f1f2"}.md-crop-16-9:before{content:"\f1f3"}.md-crop-din:before{content:"\f1f4"}.md-crop-free:before{content:"\f1f5"}.md-crop-landscape:before{content:"\f1f6"}.md-crop-original:before{content:"\f1f7"}.md-crop-portrait:before{content:"\f1f8"}.md-crop-square:before{content:"\f1f9"}.md-dehaze:before{content:"\f1fa"}.md-details:before{content:"\f1fb"}.md-edit:before{content:"\f1fc"}.md-exposure:before{content:"\f1fd"}.md-exposure-minus-1:before{content:"\f1fe"}.md-exposure-minus-2:before{content:"\f1ff"}.md-exposure-zero:before{content:"\f200"}.md-exposure-plus-1:before{content:"\f201"}.md-exposure-plus-2:before{content:"\f202"}.md-filter:before{content:"\f203"}.md-filter-1:before{content:"\f204"}.md-filter-2:before{content:"\f205"}.md-filter-3:before{content:"\f206"}.md-filter-4:before{content:"\f207"}.md-filter-5:before{content:"\f208"}.md-filter-6:before{content:"\f209"}.md-filter-7:before{content:"\f20a"}.md-filter-8:before{content:"\f20b"}.md-filter-9:before{content:"\f20c"}.md-filter-9-plus:before{content:"\f20d"}.md-filter-b-and-w:before{content:"\f20e"}.md-filter-center-focus:before{content:"\f20f"}.md-filter-drama:before{content:"\f210"}.md-filter-frames:before{content:"\f211"}.md-filter-hdr:before{content:"\f212"}.md-filter-none:before{content:"\f213"}.md-filter-tilt-shift:before{content:"\f214"}.md-filter-vintage:before{content:"\f215"}.md-flare:before{content:"\f216"}.md-flash-auto:before{content:"\f217"}.md-flash-off:before{content:"\f218"}.md-flash-on:before{content:"\f219"}.md-flip:before{content:"\f21a"}.md-gradient:before{content:"\f21b"}.md-grain:before{content:"\f21c"}.md-grid-off:before{content:"\f21d"}.md-grid-on:before{content:"\f21e"}.md-hdr-off:before{content:"\f21f"}.md-hdr-on:before{content:"\f220"}.md-hdr-strong:before{content:"\f221"}.md-hdr-weak:before{content:"\f222"}.md-healing:before{content:"\f223"}.md-image:before{content:"\f224"}.md-image-aspect-ratio:before{content:"\f225"}.md-iso:before{content:"\f226"}.md-landscape:before{content:"\f227"}.md-leak-add:before{content:"\f228"}.md-leak-remove:before{content:"\f229"}.md-lens:before{content:"\f22a"}.md-looks:before{content:"\f22b"}.md-looks-1:before{content:"\f22c"}.md-looks-2:before{content:"\f22d"}.md-looks-3:before{content:"\f22e"}.md-looks-4:before{content:"\f22f"}.md-looks-5:before{content:"\f230"}.md-looks-6:before{content:"\f231"}.md-loupe:before{content:"\f232"}.md-movie-creation:before{content:"\f233"}.md-nature:before{content:"\f234"}.md-nature-people:before{content:"\f235"}.md-navigate-before:before{content:"\f236"}.md-navigate-next:before{content:"\f237"}.md-palette:before{content:"\f238"}.md-panorama:before{content:"\f239"}.md-panorama-fisheye:before{content:"\f23a"}.md-panorama-horizontal:before{content:"\f23b"}.md-panorama-vertical:before{content:"\f23c"}.md-panorama-wide-angle:before{content:"\f23d"}.md-photo:before{content:"\f23e"}.md-photo-album:before{content:"\f23f"}.md-photo-camera:before{content:"\f240"}.md-photo-library:before{content:"\f241"}.md-portrait:before{content:"\f242"}.md-remove-red-eye:before{content:"\f243"}.md-rotate-left:before{content:"\f244"}.md-rotate-right:before{content:"\f245"}.md-slideshow:before{content:"\f246"}.md-straighten:before{content:"\f247"}.md-style:before{content:"\f248"}.md-switch-camera:before{content:"\f249"}.md-switch-video:before{content:"\f24a"}.md-tag-faces:before{content:"\f24b"}.md-texture:before{content:"\f24c"}.md-timelapse:before{content:"\f24d"}.md-timer:before{content:"\f24e"}.md-timer-3:before{content:"\f24f"}.md-timer-10:before{content:"\f250"}.md-timer-auto:before{content:"\f251"}.md-timer-off:before{content:"\f252"}.md-tonality:before{content:"\f253"}.md-transform:before{content:"\f254"}.md-tune:before{content:"\f255"}.md-wb-auto:before{content:"\f256"}.md-wb-cloudy:before{content:"\f257"}.md-wb-incandescent:before{content:"\f258"}.md-wb-irradescent:before{content:"\f259"}.md-wb-sunny:before{content:"\f25a"}.md-beenhere:before{content:"\f25b"}.md-directions:before{content:"\f25c"}.md-directions-bike:before{content:"\f25d"}.md-directions-bus:before{content:"\f25e"}.md-directions-car:before{content:"\f25f"}.md-directions-ferry:before{content:"\f260"}.md-directions-subway:before{content:"\f261"}.md-directions-train:before{content:"\f262"}.md-directions-transit:before{content:"\f263"}.md-directions-walk:before{content:"\f264"}.md-flight:before{content:"\f265"}.md-hotel:before{content:"\f266"}.md-layers:before{content:"\f267"}.md-layers-clear:before{content:"\f268"}.md-local-airport:before{content:"\f269"}.md-local-atm:before{content:"\f26a"}.md-local-attraction:before{content:"\f26b"}.md-local-bar:before{content:"\f26c"}.md-local-cafe:before{content:"\f26d"}.md-local-car-wash:before{content:"\f26e"}.md-local-convenience-store:before{content:"\f26f"}.md-local-drink:before{content:"\f270"}.md-local-florist:before{content:"\f271"}.md-local-gas-station:before{content:"\f272"}.md-local-grocery-store:before{content:"\f273"}.md-local-hospital:before{content:"\f274"}.md-local-hotel:before{content:"\f275"}.md-local-laundry-service:before{content:"\f276"}.md-local-library:before{content:"\f277"}.md-local-mall:before{content:"\f278"}.md-local-movies:before{content:"\f279"}.md-local-offer:before{content:"\f27a"}.md-local-parking:before{content:"\f27b"}.md-local-pharmacy:before{content:"\f27c"}.md-local-phone:before{content:"\f27d"}.md-local-pizza:before{content:"\f27e"}.md-local-play:before{content:"\f27f"}.md-local-post-office:before{content:"\f280"}.md-local-print-shop:before{content:"\f281"}.md-local-restaurant:before{content:"\f282"}.md-local-see:before{content:"\f283"}.md-local-shipping:before{content:"\f284"}.md-local-taxi:before{content:"\f285"}.md-location-history:before{content:"\f286"}.md-map:before{content:"\f287"}.md-my-location:before{content:"\f288"}.md-navigation:before{content:"\f289"}.md-pin-drop:before{content:"\f28a"}.md-place:before{content:"\f28b"}.md-rate-review:before{content:"\f28c"}.md-restaurant-menu:before{content:"\f28d"}.md-satellite:before{content:"\f28e"}.md-store-mall-directory:before{content:"\f28f"}.md-terrain:before{content:"\f290"}.md-traffic:before{content:"\f291"}.md-apps:before{content:"\f292"}.md-cancel:before{content:"\f293"}.md-arrow-drop-down-circle:before{content:"\f294"}.md-arrow-drop-down:before{content:"\f295"}.md-arrow-drop-up:before{content:"\f296"}.md-arrow-back:before{content:"\f297"}.md-arrow-forward:before{content:"\f298"}.md-check:before{content:"\f299"}.md-close:before{content:"\f29a"}.md-chevron-left:before{content:"\f29b"}.md-chevron-right:before{content:"\f29c"}.md-expand-less:before{content:"\f29d"}.md-expand-more:before{content:"\f29e"}.md-fullscreen:before{content:"\f29f"}.md-fullscreen-exit:before{content:"\f2a0"}.md-menu:before{content:"\f2a1"}.md-more-horiz:before{content:"\f2a2"}.md-more-vert:before{content:"\f2a3"}.md-refresh:before{content:"\f2a4"}.md-unfold-less:before{content:"\f2a5"}.md-unfold-more:before{content:"\f2a6"}.md-adb:before{content:"\f2a7"}.md-bluetooth-audio:before{content:"\f2a8"}.md-disc-full:before{content:"\f2a9"}.md-dnd-forwardslash:before{content:"\f2aa"}.md-do-not-disturb:before{content:"\f2ab"}.md-drive-eta:before{content:"\f2ac"}.md-event-available:before{content:"\f2ad"}.md-event-busy:before{content:"\f2ae"}.md-event-note:before{content:"\f2af"}.md-folder-special:before{content:"\f2b0"}.md-mms:before{content:"\f2b1"}.md-more:before{content:"\f2b2"}.md-network-locked:before{content:"\f2b3"}.md-phone-bluetooth-speaker:before{content:"\f2b4"}.md-phone-forwarded:before{content:"\f2b5"}.md-phone-in-talk:before{content:"\f2b6"}.md-phone-locked:before{content:"\f2b7"}.md-phone-missed:before{content:"\f2b8"}.md-phone-paused:before{content:"\f2b9"}.md-play-download:before{content:"\f2ba"}.md-play-install:before{content:"\f2bb"}.md-sd-card:before{content:"\f2bc"}.md-sim-card-alert:before{content:"\f2bd"}.md-sms:before{content:"\f2be"}.md-sms-failed:before{content:"\f2bf"}.md-sync:before{content:"\f2c0"}.md-sync-disabled:before{content:"\f2c1"}.md-sync-problem:before{content:"\f2c2"}.md-system-update:before{content:"\f2c3"}.md-tap-and-play:before{content:"\f2c4"}.md-time-to-leave:before{content:"\f2c5"}.md-vibration:before{content:"\f2c6"}.md-voice-chat:before{content:"\f2c7"}.md-vpn-lock:before{content:"\f2c8"}.md-cake:before{content:"\f2c9"}.md-domain:before{content:"\f2ca"}.md-location-city:before{content:"\f2cb"}.md-mood:before{content:"\f2cc"}.md-notifications-none:before{content:"\f2cd"}.md-notifications:before{content:"\f2ce"}.md-notifications-off:before{content:"\f2cf"}.md-notifications-on:before{content:"\f2d0"}.md-notifications-paused:before{content:"\f2d1"}.md-pages:before{content:"\f2d2"}.md-party-mode:before{content:"\f2d3"}.md-group:before{content:"\f2d4"}.md-group-add:before{content:"\f2d5"}.md-people:before{content:"\f2d6"}.md-people-outline:before{content:"\f2d7"}.md-person:before{content:"\f2d8"}.md-person-add:before{content:"\f2d9"}.md-person-outline:before{content:"\f2da"}.md-plus-one:before{content:"\f2db"}.md-poll:before{content:"\f2dc"}.md-public:before{content:"\f2dd"}.md-school:before{content:"\f2de"}.md-share:before{content:"\f2df"}.md-whatshot:before{content:"\f2e0"}.md-check-box:before{content:"\f2e1"}.md-check-box-outline-blank:before{content:"\f2e2"}.md-radio-button-off:before{content:"\f2e3"}.md-radio-button-on:before{content:"\f2e4"}.md-star:before{content:"\f2e5"}.md-star-half:before{content:"\f2e6"}.md-star-outline:before{content:"\f2e7"} \ No newline at end of file diff --git a/LiveChat/Styles/socicon.min.css b/LiveChat/Styles/socicon.min.css new file mode 100644 index 0000000..0fbc428 --- /dev/null +++ b/LiveChat/Styles/socicon.min.css @@ -0,0 +1 @@ +@font-face{font-family:socicon;src:url(fonts/socicon-webfont.eot);src:url(fonts/socicon-webfont.eot?#iefix) format('embedded-opentype'),url(fonts/socicon-webfont.woff) format('woff'),url(fonts/socicon-webfont.ttf) format('truetype'),url(fonts/socicon-webfont.svg#sociconregular) format('svg');font-weight:400;font-style:normal;text-transform:initial}.socicon{display:inline-block;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased}.socicon:empty{width:1em}.socicon-twitter:before{content:"a"}.socicon-facebook:before{content:"b"}.socicon-google:before{content:"c"}.socicon-pinterest:before{content:"d"}.socicon-foursquare:before{content:"e"}.socicon-yahoo:before{content:"f"}.socicon-skype:before{content:"g"}.socicon-yelp:before{content:"h"}.socicon-feedburner:before{content:"i"}.socicon-linkedin:before{content:"j"}.socicon-viadeo:before{content:"k"}.socicon-xing:before{content:"l"}.socicon-myspace:before{content:"m"}.socicon-soundcloud:before{content:"n"}.socicon-spotify:before{content:"o"}.socicon-grooveshark:before{content:"p"}.socicon-lastfm:before{content:"q"}.socicon-youtube:before{content:"r"}.socicon-vimeo:before{content:"s"}.socicon-dailymotion:before{content:"t"}.socicon-vine:before{content:"u"}.socicon-flickr:before{content:"v"}.socicon-500px:before{content:"w"}.socicon-instagram:before{content:"x"}.socicon-wordpress:before{content:"y"}.socicon-tumblr:before{content:"z"}.socicon-blogger:before{content:"A"}.socicon-technorati:before{content:"B"}.socicon-reddit:before{content:"C"}.socicon-dribbble:before{content:"D"}.socicon-stumbleupon:before{content:"E"}.socicon-digg:before{content:"F"}.socicon-envato:before{content:"G"}.socicon-behance:before{content:"H"}.socicon-delicious:before{content:"I"}.socicon-deviantart:before{content:"J"}.socicon-forrst:before{content:"K"}.socicon-playstore:before{content:"L"}.socicon-zerply:before{content:"M"}.socicon-wikipedia:before{content:"N"}.socicon-apple:before{content:"O"}.socicon-flattr:before{content:"P"}.socicon-github:before{content:"Q"}.socicon-chimein:before{content:"R"}.socicon-friendfeed:before{content:"S"}.socicon-newsvine:before{content:"T"}.socicon-identica:before{content:"U"}.socicon-bebo:before{content:"V"}.socicon-zynga:before{content:"W"}.socicon-steam:before{content:"X"}.socicon-xbox:before{content:"Y"}.socicon-windows:before{content:"Z"}.socicon-outlook:before{content:"1"}.socicon-coderwall:before{content:"2"}.socicon-tripadvisor:before{content:"3"}.socicon-appnet:before{content:"4"}.socicon-goodreads:before{content:"5"}.socicon-tripit:before{content:"6"}.socicon-lanyrd:before{content:"7"}.socicon-slideshare:before{content:"8"}.socicon-buffer:before{content:"9"}.socicon-rss:before{content:","}.socicon-vkontakte:before{content:";"}.socicon-disqus:before{content:":"}.socicon-houzz:before{content:"+"}.socicon-mail:before{content:"@"}.socicon-patreon:before{content:"="}.socicon-paypal:before{content:"-"}.socicon-playstation:before{content:"^"}.socicon-smugmug:before{content:"¬"}.socicon-swarm:before{content:"$"}.socicon-triplej:before{content:"*"}.socicon-yammer:before{content:"&"}.socicon-stackoverflow:before{content:"("}.socicon-drupal:before{content:"#"}.socicon-odnoklassniki:before{content:"."}.socicon-android:before{content:"_"}.socicon-meetup:before{content:"]"}.socicon-persona:before{content:")"} \ No newline at end of file diff --git a/LiveChat/Styles/style.css b/LiveChat/Styles/style.css new file mode 100644 index 0000000..ec4f238 --- /dev/null +++ b/LiveChat/Styles/style.css @@ -0,0 +1,16978 @@ +/* + * Load Main Bootstrap LESS files + */ + +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} + + audio:not([controls]) { + display: none; + height: 0; + } + +[hidden], +template { + display: none; +} + +a { + background-color: transparent; +} + + a:active, + a:hover { + outline: 0; + } + +abbr[title] { + border-bottom: 1px dotted; +} + +b, +strong { + font-weight: bold; +} + +dfn { + font-style: italic; +} + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +mark { + background: #ff0; + color: #000; +} + +small { + font-size: 80%; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + border: 0; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 1em 40px; +} + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +pre { + overflow: auto; +} + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} + +button { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} + + button[disabled], + html input[disabled] { + cursor: default; + } + + button::-moz-focus-inner, + input::-moz-focus-inner { + border: 0; + padding: 0; + } + +input { + line-height: normal; +} + + input[type="checkbox"], + input[type="radio"] { + box-sizing: border-box; + padding: 0; + } + + input[type="number"]::-webkit-inner-spin-button, + input[type="number"]::-webkit-outer-spin-button { + height: auto; + } + + input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + } + + input[type="search"]::-webkit-search-cancel-button, + input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; + } + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +legend { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; +} + +optgroup { + font-weight: bold; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} + +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ + +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + select { + background: #fff !important; + } + + .navbar { + display: none; + } + + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + } + + .table td, + .table th { + background-color: #fff !important; + } + + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} + +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('fonts/glyphicons-halflings-regular.eot'); + src: url('fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('fonts/glyphicons-halflings-regular.woff') format('woff'), url('fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} + +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.glyphicon-asterisk:before { + content: "\2a"; +} + +.glyphicon-plus:before { + content: "\2b"; +} + +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} + +.glyphicon-minus:before { + content: "\2212"; +} + +.glyphicon-cloud:before { + content: "\2601"; +} + +.glyphicon-envelope:before { + content: "\2709"; +} + +.glyphicon-pencil:before { + content: "\270f"; +} + +.glyphicon-glass:before { + content: "\e001"; +} + +.glyphicon-music:before { + content: "\e002"; +} + +.glyphicon-search:before { + content: "\e003"; +} + +.glyphicon-heart:before { + content: "\e005"; +} + +.glyphicon-star:before { + content: "\e006"; +} + +.glyphicon-star-empty:before { + content: "\e007"; +} + +.glyphicon-user:before { + content: "\e008"; +} + +.glyphicon-film:before { + content: "\e009"; +} + +.glyphicon-th-large:before { + content: "\e010"; +} + +.glyphicon-th:before { + content: "\e011"; +} + +.glyphicon-th-list:before { + content: "\e012"; +} + +.glyphicon-ok:before { + content: "\e013"; +} + +.glyphicon-remove:before { + content: "\e014"; +} + +.glyphicon-zoom-in:before { + content: "\e015"; +} + +.glyphicon-zoom-out:before { + content: "\e016"; +} + +.glyphicon-off:before { + content: "\e017"; +} + +.glyphicon-signal:before { + content: "\e018"; +} + +.glyphicon-cog:before { + content: "\e019"; +} + +.glyphicon-trash:before { + content: "\e020"; +} + +.glyphicon-home:before { + content: "\e021"; +} + +.glyphicon-file:before { + content: "\e022"; +} + +.glyphicon-time:before { + content: "\e023"; +} + +.glyphicon-road:before { + content: "\e024"; +} + +.glyphicon-download-alt:before { + content: "\e025"; +} + +.glyphicon-download:before { + content: "\e026"; +} + +.glyphicon-upload:before { + content: "\e027"; +} + +.glyphicon-inbox:before { + content: "\e028"; +} + +.glyphicon-play-circle:before { + content: "\e029"; +} + +.glyphicon-repeat:before { + content: "\e030"; +} + +.glyphicon-refresh:before { + content: "\e031"; +} + +.glyphicon-list-alt:before { + content: "\e032"; +} + +.glyphicon-lock:before { + content: "\e033"; +} + +.glyphicon-flag:before { + content: "\e034"; +} + +.glyphicon-headphones:before { + content: "\e035"; +} + +.glyphicon-volume-off:before { + content: "\e036"; +} + +.glyphicon-volume-down:before { + content: "\e037"; +} + +.glyphicon-volume-up:before { + content: "\e038"; +} + +.glyphicon-qrcode:before { + content: "\e039"; +} + +.glyphicon-barcode:before { + content: "\e040"; +} + +.glyphicon-tag:before { + content: "\e041"; +} + +.glyphicon-tags:before { + content: "\e042"; +} + +.glyphicon-book:before { + content: "\e043"; +} + +.glyphicon-bookmark:before { + content: "\e044"; +} + +.glyphicon-print:before { + content: "\e045"; +} + +.glyphicon-camera:before { + content: "\e046"; +} + +.glyphicon-font:before { + content: "\e047"; +} + +.glyphicon-bold:before { + content: "\e048"; +} + +.glyphicon-italic:before { + content: "\e049"; +} + +.glyphicon-text-height:before { + content: "\e050"; +} + +.glyphicon-text-width:before { + content: "\e051"; +} + +.glyphicon-align-left:before { + content: "\e052"; +} + +.glyphicon-align-center:before { + content: "\e053"; +} + +.glyphicon-align-right:before { + content: "\e054"; +} + +.glyphicon-align-justify:before { + content: "\e055"; +} + +.glyphicon-list:before { + content: "\e056"; +} + +.glyphicon-indent-left:before { + content: "\e057"; +} + +.glyphicon-indent-right:before { + content: "\e058"; +} + +.glyphicon-facetime-video:before { + content: "\e059"; +} + +.glyphicon-picture:before { + content: "\e060"; +} + +.glyphicon-map-marker:before { + content: "\e062"; +} + +.glyphicon-adjust:before { + content: "\e063"; +} + +.glyphicon-tint:before { + content: "\e064"; +} + +.glyphicon-edit:before { + content: "\e065"; +} + +.glyphicon-share:before { + content: "\e066"; +} + +.glyphicon-check:before { + content: "\e067"; +} + +.glyphicon-move:before { + content: "\e068"; +} + +.glyphicon-step-backward:before { + content: "\e069"; +} + +.glyphicon-fast-backward:before { + content: "\e070"; +} + +.glyphicon-backward:before { + content: "\e071"; +} + +.glyphicon-play:before { + content: "\e072"; +} + +.glyphicon-pause:before { + content: "\e073"; +} + +.glyphicon-stop:before { + content: "\e074"; +} + +.glyphicon-forward:before { + content: "\e075"; +} + +.glyphicon-fast-forward:before { + content: "\e076"; +} + +.glyphicon-step-forward:before { + content: "\e077"; +} + +.glyphicon-eject:before { + content: "\e078"; +} + +.glyphicon-chevron-left:before { + content: "\e079"; +} + +.glyphicon-chevron-right:before { + content: "\e080"; +} + +.glyphicon-plus-sign:before { + content: "\e081"; +} + +.glyphicon-minus-sign:before { + content: "\e082"; +} + +.glyphicon-remove-sign:before { + content: "\e083"; +} + +.glyphicon-ok-sign:before { + content: "\e084"; +} + +.glyphicon-question-sign:before { + content: "\e085"; +} + +.glyphicon-info-sign:before { + content: "\e086"; +} + +.glyphicon-screenshot:before { + content: "\e087"; +} + +.glyphicon-remove-circle:before { + content: "\e088"; +} + +.glyphicon-ok-circle:before { + content: "\e089"; +} + +.glyphicon-ban-circle:before { + content: "\e090"; +} + +.glyphicon-arrow-left:before { + content: "\e091"; +} + +.glyphicon-arrow-right:before { + content: "\e092"; +} + +.glyphicon-arrow-up:before { + content: "\e093"; +} + +.glyphicon-arrow-down:before { + content: "\e094"; +} + +.glyphicon-share-alt:before { + content: "\e095"; +} + +.glyphicon-resize-full:before { + content: "\e096"; +} + +.glyphicon-resize-small:before { + content: "\e097"; +} + +.glyphicon-exclamation-sign:before { + content: "\e101"; +} + +.glyphicon-gift:before { + content: "\e102"; +} + +.glyphicon-leaf:before { + content: "\e103"; +} + +.glyphicon-fire:before { + content: "\e104"; +} + +.glyphicon-eye-open:before { + content: "\e105"; +} + +.glyphicon-eye-close:before { + content: "\e106"; +} + +.glyphicon-warning-sign:before { + content: "\e107"; +} + +.glyphicon-plane:before { + content: "\e108"; +} + +.glyphicon-calendar:before { + content: "\e109"; +} + +.glyphicon-random:before { + content: "\e110"; +} + +.glyphicon-comment:before { + content: "\e111"; +} + +.glyphicon-magnet:before { + content: "\e112"; +} + +.glyphicon-chevron-up:before { + content: "\e113"; +} + +.glyphicon-chevron-down:before { + content: "\e114"; +} + +.glyphicon-retweet:before { + content: "\e115"; +} + +.glyphicon-shopping-cart:before { + content: "\e116"; +} + +.glyphicon-folder-close:before { + content: "\e117"; +} + +.glyphicon-folder-open:before { + content: "\e118"; +} + +.glyphicon-resize-vertical:before { + content: "\e119"; +} + +.glyphicon-resize-horizontal:before { + content: "\e120"; +} + +.glyphicon-hdd:before { + content: "\e121"; +} + +.glyphicon-bullhorn:before { + content: "\e122"; +} + +.glyphicon-bell:before { + content: "\e123"; +} + +.glyphicon-certificate:before { + content: "\e124"; +} + +.glyphicon-thumbs-up:before { + content: "\e125"; +} + +.glyphicon-thumbs-down:before { + content: "\e126"; +} + +.glyphicon-hand-right:before { + content: "\e127"; +} + +.glyphicon-hand-left:before { + content: "\e128"; +} + +.glyphicon-hand-up:before { + content: "\e129"; +} + +.glyphicon-hand-down:before { + content: "\e130"; +} + +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} + +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} + +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} + +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} + +.glyphicon-globe:before { + content: "\e135"; +} + +.glyphicon-wrench:before { + content: "\e136"; +} + +.glyphicon-tasks:before { + content: "\e137"; +} + +.glyphicon-filter:before { + content: "\e138"; +} + +.glyphicon-briefcase:before { + content: "\e139"; +} + +.glyphicon-fullscreen:before { + content: "\e140"; +} + +.glyphicon-dashboard:before { + content: "\e141"; +} + +.glyphicon-paperclip:before { + content: "\e142"; +} + +.glyphicon-heart-empty:before { + content: "\e143"; +} + +.glyphicon-link:before { + content: "\e144"; +} + +.glyphicon-phone:before { + content: "\e145"; +} + +.glyphicon-pushpin:before { + content: "\e146"; +} + +.glyphicon-usd:before { + content: "\e148"; +} + +.glyphicon-gbp:before { + content: "\e149"; +} + +.glyphicon-sort:before { + content: "\e150"; +} + +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} + +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} + +.glyphicon-sort-by-order:before { + content: "\e153"; +} + +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} + +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} + +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} + +.glyphicon-unchecked:before { + content: "\e157"; +} + +.glyphicon-expand:before { + content: "\e158"; +} + +.glyphicon-collapse-down:before { + content: "\e159"; +} + +.glyphicon-collapse-up:before { + content: "\e160"; +} + +.glyphicon-log-in:before { + content: "\e161"; +} + +.glyphicon-flash:before { + content: "\e162"; +} + +.glyphicon-log-out:before { + content: "\e163"; +} + +.glyphicon-new-window:before { + content: "\e164"; +} + +.glyphicon-record:before { + content: "\e165"; +} + +.glyphicon-save:before { + content: "\e166"; +} + +.glyphicon-open:before { + content: "\e167"; +} + +.glyphicon-saved:before { + content: "\e168"; +} + +.glyphicon-import:before { + content: "\e169"; +} + +.glyphicon-export:before { + content: "\e170"; +} + +.glyphicon-send:before { + content: "\e171"; +} + +.glyphicon-floppy-disk:before { + content: "\e172"; +} + +.glyphicon-floppy-saved:before { + content: "\e173"; +} + +.glyphicon-floppy-remove:before { + content: "\e174"; +} + +.glyphicon-floppy-save:before { + content: "\e175"; +} + +.glyphicon-floppy-open:before { + content: "\e176"; +} + +.glyphicon-credit-card:before { + content: "\e177"; +} + +.glyphicon-transfer:before { + content: "\e178"; +} + +.glyphicon-cutlery:before { + content: "\e179"; +} + +.glyphicon-header:before { + content: "\e180"; +} + +.glyphicon-compressed:before { + content: "\e181"; +} + +.glyphicon-earphone:before { + content: "\e182"; +} + +.glyphicon-phone-alt:before { + content: "\e183"; +} + +.glyphicon-tower:before { + content: "\e184"; +} + +.glyphicon-stats:before { + content: "\e185"; +} + +.glyphicon-sd-video:before { + content: "\e186"; +} + +.glyphicon-hd-video:before { + content: "\e187"; +} + +.glyphicon-subtitles:before { + content: "\e188"; +} + +.glyphicon-sound-stereo:before { + content: "\e189"; +} + +.glyphicon-sound-dolby:before { + content: "\e190"; +} + +.glyphicon-sound-5-1:before { + content: "\e191"; +} + +.glyphicon-sound-6-1:before { + content: "\e192"; +} + +.glyphicon-sound-7-1:before { + content: "\e193"; +} + +.glyphicon-copyright-mark:before { + content: "\e194"; +} + +.glyphicon-registration-mark:before { + content: "\e195"; +} + +.glyphicon-cloud-download:before { + content: "\e197"; +} + +.glyphicon-cloud-upload:before { + content: "\e198"; +} + +.glyphicon-tree-conifer:before { + content: "\e199"; +} + +.glyphicon-tree-deciduous:before { + content: "\e200"; +} + +.glyphicon-cd:before { + content: "\e201"; +} + +.glyphicon-save-file:before { + content: "\e202"; +} + +.glyphicon-open-file:before { + content: "\e203"; +} + +.glyphicon-level-up:before { + content: "\e204"; +} + +.glyphicon-copy:before { + content: "\e205"; +} + +.glyphicon-paste:before { + content: "\e206"; +} + +.glyphicon-alert:before { + content: "\e209"; +} + +.glyphicon-equalizer:before { + content: "\e210"; +} + +.glyphicon-king:before { + content: "\e211"; +} + +.glyphicon-queen:before { + content: "\e212"; +} + +.glyphicon-pawn:before { + content: "\e213"; +} + +.glyphicon-bishop:before { + content: "\e214"; +} + +.glyphicon-knight:before { + content: "\e215"; +} + +.glyphicon-baby-formula:before { + content: "\e216"; +} + +.glyphicon-tent:before { + content: "\26fa"; +} + +.glyphicon-blackboard:before { + content: "\e218"; +} + +.glyphicon-bed:before { + content: "\e219"; +} + +.glyphicon-apple:before { + content: "\f8ff"; +} + +.glyphicon-erase:before { + content: "\e221"; +} + +.glyphicon-hourglass:before { + content: "\231b"; +} + +.glyphicon-lamp:before { + content: "\e223"; +} + +.glyphicon-duplicate:before { + content: "\e224"; +} + +.glyphicon-piggy-bank:before { + content: "\e225"; +} + +.glyphicon-scissors:before { + content: "\e226"; +} + +.glyphicon-bitcoin:before { + content: "\e227"; +} + +.glyphicon-btc:before { + content: "\e227"; +} + +.glyphicon-xbt:before { + content: "\e227"; +} + +.glyphicon-yen:before { + content: "\00a5"; +} + +.glyphicon-jpy:before { + content: "\00a5"; +} + +.glyphicon-ruble:before { + content: "\20bd"; +} + +.glyphicon-rub:before { + content: "\20bd"; +} + +.glyphicon-scale:before { + content: "\e230"; +} + +.glyphicon-ice-lolly:before { + content: "\e231"; +} + +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} + +.glyphicon-education:before { + content: "\e233"; +} + +.glyphicon-option-horizontal:before { + content: "\e234"; +} + +.glyphicon-option-vertical:before { + content: "\e235"; +} + +.glyphicon-menu-hamburger:before { + content: "\e236"; +} + +.glyphicon-modal-window:before { + content: "\e237"; +} + +.glyphicon-oil:before { + content: "\e238"; +} + +.glyphicon-grain:before { + content: "\e239"; +} + +.glyphicon-sunglasses:before { + content: "\e240"; +} + +.glyphicon-text-size:before { + content: "\e241"; +} + +.glyphicon-text-color:before { + content: "\e242"; +} + +.glyphicon-text-background:before { + content: "\e243"; +} + +.glyphicon-object-align-top:before { + content: "\e244"; +} + +.glyphicon-object-align-bottom:before { + content: "\e245"; +} + +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} + +.glyphicon-object-align-left:before { + content: "\e247"; +} + +.glyphicon-object-align-vertical:before { + content: "\e248"; +} + +.glyphicon-object-align-right:before { + content: "\e249"; +} + +.glyphicon-triangle-right:before { + content: "\e250"; +} + +.glyphicon-triangle-left:before { + content: "\e251"; +} + +.glyphicon-triangle-bottom:before { + content: "\e252"; +} + +.glyphicon-triangle-top:before { + content: "\e253"; +} + +.glyphicon-console:before { + content: "\e254"; +} + +.glyphicon-superscript:before { + content: "\e255"; +} + +.glyphicon-subscript:before { + content: "\e256"; +} + +.glyphicon-menu-left:before { + content: "\e257"; +} + +.glyphicon-menu-right:before { + content: "\e258"; +} + +.glyphicon-menu-down:before { + content: "\e259"; +} + +.glyphicon-menu-up:before { + content: "\e260"; +} + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + + *:before, + *:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +body { + font-family: roboto; + font-size: 13px; + line-height: 1.42857143; + color: #5e5e5e; + background-color: #edecec !important; +} + +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +a { + color: #2196f3; + text-decoration: none; +} + + a:hover, + a:focus { + color: #0a6ebd; + text-decoration: none; + } + + a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + outline: none !important; + } + +figure { + margin: 0; +} + +img { + vertical-align: middle; +} + +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} + +.img-rounded { + border-radius: 2px; +} + +.img-thumbnail { + padding: 3px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #ededed; + border-radius: 2px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} + +.img-circle { + border-radius: 50%; +} + +hr { + margin-top: 18px; + margin-bottom: 18px; + border: 0; + border-top: 1px solid #eeeeee; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} + +[role="button"] { + cursor: pointer; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: #000000; +} + + h1 small, + h2 small, + h3 small, + h4 small, + h5 small, + h6 small, + .h1 small, + .h2 small, + .h3 small, + .h4 small, + .h5 small, + .h6 small, + h1 .small, + h2 .small, + h3 .small, + h4 .small, + h5 .small, + h6 .small, + .h1 .small, + .h2 .small, + .h3 .small, + .h4 .small, + .h5 .small, + .h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; + } + +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 18px; + margin-bottom: 9px; +} + + h1 small, + .h1 small, + h2 small, + .h2 small, + h3 small, + .h3 small, + h1 .small, + .h1 .small, + h2 .small, + .h2 .small, + h3 .small, + .h3 .small { + font-size: 65%; + } + +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 9px; + margin-bottom: 9px; +} + + h4 small, + .h4 small, + h5 small, + .h5 small, + h6 small, + .h6 small, + h4 .small, + .h4 .small, + h5 .small, + .h5 .small, + h6 .small, + .h6 .small { + font-size: 75%; + } + +h1, +.h1 { + font-size: 33px; +} + +h2, +.h2 { + font-size: 27px; +} + +h3, +.h3 { + font-size: 23px; +} + +h4, +.h4 { + font-size: 17px; +} + +h5, +.h5 { + font-size: 13px; +} + +h6, +.h6 { + font-size: 12px; +} + +p { + margin: 0 0 9px; +} + +.lead { + margin-bottom: 18px; + font-size: 14px; + font-weight: 300; + line-height: 1.4; +} + +@media (min-width: 768px) { + .lead { + font-size: 19.5px; + } +} + +small, +.small { + font-size: 92%; +} + +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +.text-justify { + text-align: justify; +} + +.text-nowrap { + white-space: nowrap; +} + +.text-lowercase { + text-transform: lowercase; +} + +.text-uppercase { + text-transform: uppercase; +} + +.text-capitalize { + text-transform: capitalize; +} + +.text-muted { + color: #777777; +} + +.text-primary { + color: #2196f3; +} + +a.text-primary:hover { + color: #0c7cd5; +} + +.text-success { + color: #4caf50; +} + +a.text-success:hover { + color: #3d8b40; +} + +.text-info { + color: #2196f3; +} + +a.text-info:hover { + color: #0c7cd5; +} + +.text-warning { + color: #ff9800; +} + +a.text-warning:hover { + color: #cc7a00; +} + +.text-danger { + color: #f44336; +} + +a.text-danger:hover { + color: #ea1c0d; +} + +.bg-primary { + color: #fff; + background-color: #2196f3; +} + +a.bg-primary:hover { + background-color: #0c7cd5; +} + +.bg-success { + background-color: #dff0d8; +} + +a.bg-success:hover { + background-color: #c1e2b3; +} + +.bg-info { + background-color: #d9edf7; +} + +a.bg-info:hover { + background-color: #afd9ee; +} + +.bg-warning { + background-color: #fcf8e3; +} + +a.bg-warning:hover { + background-color: #f7ecb5; +} + +.bg-danger { + background-color: #f2dede; +} + +a.bg-danger:hover { + background-color: #e4b9b9; +} + +.page-header { + padding-bottom: 8px; + margin: 36px 0 18px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + margin-top: 0; + margin-bottom: 9px; +} + + ul ul, + ol ul, + ul ol, + ol ol { + margin-bottom: 0; + } + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} + + .list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; + } + +dl { + margin-top: 0; + margin-bottom: 18px; +} + +dt, +dd { + line-height: 1.42857143; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 0; +} + +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .dl-horizontal dd { + margin-left: 180px; + } +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 9px 18px; + margin: 0 0 18px; + font-size: 16.25px; + border-left: 5px solid #eeeeee; +} + + blockquote p:last-child, + blockquote ul:last-child, + blockquote ol:last-child { + margin-bottom: 0; + } + + blockquote footer, + blockquote small, + blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777777; + } + + blockquote footer:before, + blockquote small:before, + blockquote .small:before { + content: '\2014 \00A0'; + } + + .blockquote-reverse, + blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; + } + + .blockquote-reverse footer:before, + blockquote.pull-right footer:before, + .blockquote-reverse small:before, + blockquote.pull-right small:before, + .blockquote-reverse .small:before, + blockquote.pull-right .small:before { + content: ''; + } + + .blockquote-reverse footer:after, + blockquote.pull-right footer:after, + .blockquote-reverse small:after, + blockquote.pull-right small:after, + .blockquote-reverse .small:after, + blockquote.pull-right .small:after { + content: '\00A0 \2014'; + } + +address { + margin-bottom: 18px; + font-style: normal; + line-height: 1.42857143; +} + +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} + +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 2px; +} + +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 2px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} + + kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; + } + +pre { + display: block; + padding: 8.5px; + margin: 0 0 9px; + font-size: 12px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 2px; +} + + pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; + } + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} + +@media (min-width: 768px) { + .container { + width: calc(100% - 30px); + } +} + +@media (min-width: 992px) { + .container { + width: calc(100% - 30px); + } +} + +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} + +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} + +.row { + margin-left: -15px; + margin-right: -15px; +} + +.col-xs-1, +.col-sm-1, +.col-md-1, +.col-lg-1, +.col-xs-2, +.col-sm-2, +.col-md-2, +.col-lg-2, +.col-xs-3, +.col-sm-3, +.col-md-3, +.col-lg-3, +.col-xs-4, +.col-sm-4, +.col-md-4, +.col-lg-4, +.col-xs-5, +.col-sm-5, +.col-md-5, +.col-lg-5, +.col-xs-6, +.col-sm-6, +.col-md-6, +.col-lg-6, +.col-xs-7, +.col-sm-7, +.col-md-7, +.col-lg-7, +.col-xs-8, +.col-sm-8, +.col-md-8, +.col-lg-8, +.col-xs-9, +.col-sm-9, +.col-md-9, +.col-lg-9, +.col-xs-10, +.col-sm-10, +.col-md-10, +.col-lg-10, +.col-xs-11, +.col-sm-11, +.col-md-11, +.col-lg-11, +.col-xs-12, +.col-sm-12, +.col-md-12, +.col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} + +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11, +.col-xs-12 { + float: left; +} + +.col-xs-12 { + width: 100%; +} + +.col-xs-11 { + width: 91.66666667%; +} + +.col-xs-10 { + width: 83.33333333%; +} + +.col-xs-9 { + width: 75%; +} + +.col-xs-8 { + width: 66.66666667%; +} + +.col-xs-7 { + width: 58.33333333%; +} + +.col-xs-6 { + width: 50%; +} + +.col-xs-5 { + width: 41.66666667%; +} + +.col-xs-4 { + width: 33.33333333%; +} + +.col-xs-3 { + width: 25%; +} + +.col-xs-2 { + width: 16.66666667%; +} + +.col-xs-1 { + width: 8.33333333%; +} + +.col-xs-pull-12 { + right: 100%; +} + +.col-xs-pull-11 { + right: 91.66666667%; +} + +.col-xs-pull-10 { + right: 83.33333333%; +} + +.col-xs-pull-9 { + right: 75%; +} + +.col-xs-pull-8 { + right: 66.66666667%; +} + +.col-xs-pull-7 { + right: 58.33333333%; +} + +.col-xs-pull-6 { + right: 50%; +} + +.col-xs-pull-5 { + right: 41.66666667%; +} + +.col-xs-pull-4 { + right: 33.33333333%; +} + +.col-xs-pull-3 { + right: 25%; +} + +.col-xs-pull-2 { + right: 16.66666667%; +} + +.col-xs-pull-1 { + right: 8.33333333%; +} + +.col-xs-pull-0 { + right: auto; +} + +.col-xs-push-12 { + left: 100%; +} + +.col-xs-push-11 { + left: 91.66666667%; +} + +.col-xs-push-10 { + left: 83.33333333%; +} + +.col-xs-push-9 { + left: 75%; +} + +.col-xs-push-8 { + left: 66.66666667%; +} + +.col-xs-push-7 { + left: 58.33333333%; +} + +.col-xs-push-6 { + left: 50%; +} + +.col-xs-push-5 { + left: 41.66666667%; +} + +.col-xs-push-4 { + left: 33.33333333%; +} + +.col-xs-push-3 { + left: 25%; +} + +.col-xs-push-2 { + left: 16.66666667%; +} + +.col-xs-push-1 { + left: 8.33333333%; +} + +.col-xs-push-0 { + left: auto; +} + +.col-xs-offset-12 { + margin-left: 100%; +} + +.col-xs-offset-11 { + margin-left: 91.66666667%; +} + +.col-xs-offset-10 { + margin-left: 83.33333333%; +} + +.col-xs-offset-9 { + margin-left: 75%; +} + +.col-xs-offset-8 { + margin-left: 66.66666667%; +} + +.col-xs-offset-7 { + margin-left: 58.33333333%; +} + +.col-xs-offset-6 { + margin-left: 50%; +} + +.col-xs-offset-5 { + margin-left: 41.66666667%; +} + +.col-xs-offset-4 { + margin-left: 33.33333333%; +} + +.col-xs-offset-3 { + margin-left: 25%; +} + +.col-xs-offset-2 { + margin-left: 16.66666667%; +} + +.col-xs-offset-1 { + margin-left: 8.33333333%; +} + +.col-xs-offset-0 { + margin-left: 0%; +} + +@media (min-width: 768px) { + .col-sm-1, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9, + .col-sm-10, + .col-sm-11, + .col-sm-12 { + float: left; + } + + .col-sm-12 { + width: 100%; + } + + .col-sm-11 { + width: 91.66666667%; + } + + .col-sm-10 { + width: 83.33333333%; + } + + .col-sm-9 { + width: 75%; + } + + .col-sm-8 { + width: 66.66666667%; + } + + .col-sm-7 { + width: 58.33333333%; + } + + .col-sm-6 { + width: 50%; + } + + .col-sm-5 { + width: 41.66666667%; + } + + .col-sm-4 { + width: 33.33333333%; + } + + .col-sm-3 { + width: 25%; + } + + .col-sm-2 { + width: 16.66666667%; + } + + .col-sm-1 { + width: 8.33333333%; + } + + .col-sm-pull-12 { + right: 100%; + } + + .col-sm-pull-11 { + right: 91.66666667%; + } + + .col-sm-pull-10 { + right: 83.33333333%; + } + + .col-sm-pull-9 { + right: 75%; + } + + .col-sm-pull-8 { + right: 66.66666667%; + } + + .col-sm-pull-7 { + right: 58.33333333%; + } + + .col-sm-pull-6 { + right: 50%; + } + + .col-sm-pull-5 { + right: 41.66666667%; + } + + .col-sm-pull-4 { + right: 33.33333333%; + } + + .col-sm-pull-3 { + right: 25%; + } + + .col-sm-pull-2 { + right: 16.66666667%; + } + + .col-sm-pull-1 { + right: 8.33333333%; + } + + .col-sm-pull-0 { + right: auto; + } + + .col-sm-push-12 { + left: 100%; + } + + .col-sm-push-11 { + left: 91.66666667%; + } + + .col-sm-push-10 { + left: 83.33333333%; + } + + .col-sm-push-9 { + left: 75%; + } + + .col-sm-push-8 { + left: 66.66666667%; + } + + .col-sm-push-7 { + left: 58.33333333%; + } + + .col-sm-push-6 { + left: 50%; + } + + .col-sm-push-5 { + left: 41.66666667%; + } + + .col-sm-push-4 { + left: 33.33333333%; + } + + .col-sm-push-3 { + left: 25%; + } + + .col-sm-push-2 { + left: 16.66666667%; + } + + .col-sm-push-1 { + left: 8.33333333%; + } + + .col-sm-push-0 { + left: auto; + } + + .col-sm-offset-12 { + margin-left: 100%; + } + + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + + .col-sm-offset-9 { + margin-left: 75%; + } + + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + + .col-sm-offset-6 { + margin-left: 50%; + } + + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + + .col-sm-offset-3 { + margin-left: 25%; + } + + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + + .col-sm-offset-0 { + margin-left: 0%; + } +} + +@media (min-width: 992px) { + .col-md-1, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-10, + .col-md-11, + .col-md-12 { + float: left; + } + + .col-md-12 { + width: 100%; + } + + .col-md-11 { + width: 91.66666667%; + } + + .col-md-10 { + width: 83.33333333%; + } + + .col-md-9 { + width: 75%; + } + + .col-md-8 { + width: 66.66666667%; + } + + .col-md-7 { + width: 58.33333333%; + } + + .col-md-6 { + width: 50%; + } + + .col-md-5 { + width: 41.66666667%; + } + + .col-md-4 { + width: 33.33333333%; + } + + .col-md-3 { + width: 25%; + } + + .col-md-2 { + width: 16.66666667%; + } + + .col-md-1 { + width: 8.33333333%; + } + + .col-md-pull-12 { + right: 100%; + } + + .col-md-pull-11 { + right: 91.66666667%; + } + + .col-md-pull-10 { + right: 83.33333333%; + } + + .col-md-pull-9 { + right: 75%; + } + + .col-md-pull-8 { + right: 66.66666667%; + } + + .col-md-pull-7 { + right: 58.33333333%; + } + + .col-md-pull-6 { + right: 50%; + } + + .col-md-pull-5 { + right: 41.66666667%; + } + + .col-md-pull-4 { + right: 33.33333333%; + } + + .col-md-pull-3 { + right: 25%; + } + + .col-md-pull-2 { + right: 16.66666667%; + } + + .col-md-pull-1 { + right: 8.33333333%; + } + + .col-md-pull-0 { + right: auto; + } + + .col-md-push-12 { + left: 100%; + } + + .col-md-push-11 { + left: 91.66666667%; + } + + .col-md-push-10 { + left: 83.33333333%; + } + + .col-md-push-9 { + left: 75%; + } + + .col-md-push-8 { + left: 66.66666667%; + } + + .col-md-push-7 { + left: 58.33333333%; + } + + .col-md-push-6 { + left: 50%; + } + + .col-md-push-5 { + left: 41.66666667%; + } + + .col-md-push-4 { + left: 33.33333333%; + } + + .col-md-push-3 { + left: 25%; + } + + .col-md-push-2 { + left: 16.66666667%; + } + + .col-md-push-1 { + left: 8.33333333%; + } + + .col-md-push-0 { + left: auto; + } + + .col-md-offset-12 { + margin-left: 100%; + } + + .col-md-offset-11 { + margin-left: 91.66666667%; + } + + .col-md-offset-10 { + margin-left: 83.33333333%; + } + + .col-md-offset-9 { + margin-left: 75%; + } + + .col-md-offset-8 { + margin-left: 66.66666667%; + } + + .col-md-offset-7 { + margin-left: 58.33333333%; + } + + .col-md-offset-6 { + margin-left: 50%; + } + + .col-md-offset-5 { + margin-left: 41.66666667%; + } + + .col-md-offset-4 { + margin-left: 33.33333333%; + } + + .col-md-offset-3 { + margin-left: 25%; + } + + .col-md-offset-2 { + margin-left: 16.66666667%; + } + + .col-md-offset-1 { + margin-left: 8.33333333%; + } + + .col-md-offset-0 { + margin-left: 0%; + } +} + +@media (min-width: 1200px) { + .col-lg-1, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9, + .col-lg-10, + .col-lg-11, + .col-lg-12 { + float: left; + } + + .col-lg-12 { + width: 100%; + } + + .col-lg-11 { + width: 91.66666667%; + } + + .col-lg-10 { + width: 83.33333333%; + } + + .col-lg-9 { + width: 75%; + } + + .col-lg-8 { + width: 66.66666667%; + } + + .col-lg-7 { + width: 58.33333333%; + } + + .col-lg-6 { + width: 50%; + } + + .col-lg-5 { + width: 41.66666667%; + } + + .col-lg-4 { + width: 33.33333333%; + } + + .col-lg-3 { + width: 25%; + } + + .col-lg-2 { + width: 16.66666667%; + } + + .col-lg-1 { + width: 8.33333333%; + } + + .col-lg-pull-12 { + right: 100%; + } + + .col-lg-pull-11 { + right: 91.66666667%; + } + + .col-lg-pull-10 { + right: 83.33333333%; + } + + .col-lg-pull-9 { + right: 75%; + } + + .col-lg-pull-8 { + right: 66.66666667%; + } + + .col-lg-pull-7 { + right: 58.33333333%; + } + + .col-lg-pull-6 { + right: 50%; + } + + .col-lg-pull-5 { + right: 41.66666667%; + } + + .col-lg-pull-4 { + right: 33.33333333%; + } + + .col-lg-pull-3 { + right: 25%; + } + + .col-lg-pull-2 { + right: 16.66666667%; + } + + .col-lg-pull-1 { + right: 8.33333333%; + } + + .col-lg-pull-0 { + right: auto; + } + + .col-lg-push-12 { + left: 100%; + } + + .col-lg-push-11 { + left: 91.66666667%; + } + + .col-lg-push-10 { + left: 83.33333333%; + } + + .col-lg-push-9 { + left: 75%; + } + + .col-lg-push-8 { + left: 66.66666667%; + } + + .col-lg-push-7 { + left: 58.33333333%; + } + + .col-lg-push-6 { + left: 50%; + } + + .col-lg-push-5 { + left: 41.66666667%; + } + + .col-lg-push-4 { + left: 33.33333333%; + } + + .col-lg-push-3 { + left: 25%; + } + + .col-lg-push-2 { + left: 16.66666667%; + } + + .col-lg-push-1 { + left: 8.33333333%; + } + + .col-lg-push-0 { + left: auto; + } + + .col-lg-offset-12 { + margin-left: 100%; + } + + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + + .col-lg-offset-9 { + margin-left: 75%; + } + + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + + .col-lg-offset-6 { + margin-left: 50%; + } + + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + + .col-lg-offset-3 { + margin-left: 25%; + } + + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + + .col-lg-offset-0 { + margin-left: 0%; + } +} + +table { + background-color: transparent; +} + +caption { + padding-top: 10px; + padding-bottom: 10px; + color: #777777; + text-align: left; +} + +th { + text-align: left; +} + +.table { + width: 100%; + max-width: 100%; + margin-bottom: 18px; +} + + .table > thead > tr > th, + .table > tbody > tr > th, + .table > tfoot > tr > th, + .table > thead > tr > td, + .table > tbody > tr > td, + .table > tfoot > tr > td { + padding: 10px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #f0f0f0; + } + + .table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #f0f0f0; + } + + .table > caption + thead > tr:first-child > th, + .table > colgroup + thead > tr:first-child > th, + .table > thead:first-child > tr:first-child > th, + .table > caption + thead > tr:first-child > td, + .table > colgroup + thead > tr:first-child > td, + .table > thead:first-child > tr:first-child > td { + border-top: 0; + } + + .table > tbody + tbody { + border-top: 2px solid #f0f0f0; + } + + .table .table { + background-color: #edecec; + } + +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 7px; +} + +.table-bordered { + border: 1px solid #f0f0f0; +} + + .table-bordered > thead > tr > th, + .table-bordered > tbody > tr > th, + .table-bordered > tfoot > tr > th, + .table-bordered > thead > tr > td, + .table-bordered > tbody > tr > td, + .table-bordered > tfoot > tr > td { + border: 1px solid #f0f0f0; + } + + .table-bordered > thead > tr > th, + .table-bordered > thead > tr > td { + border-bottom-width: 2px; + } + +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f4f4f4; +} + +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} + +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} + +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} + +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #fffcbe; +} + +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #fffba4; +} + +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} + +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} + +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} + +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} + +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} + +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} + +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} + +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} + +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} + +.table > tbody > tr:nth-of-type(2n+1) { + /*background-color: #f4f4f4;*/ +} + +table > tbody > tr.active{ + background-color: #f4f4f4; + cursor:pointer; +} + +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 13.5px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #f0f0f0; + } + + .table-responsive > .table { + margin-bottom: 0; + } + + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + + .table-responsive > .table-bordered { + border: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} + +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 18px; + font-size: 19.5px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} + +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} + +input[type="file"] { + display: block; +} + +input[type="range"] { + display: block; + width: 100%; +} + +select[multiple], +select[size] { + height: auto; +} + +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + outline: none !important; +} + +output { + display: block; + padding-top: 7px; + font-size: 13px; + line-height: 1.42857143; + color: #555555; +} + +.form-control { + display: block; + width: 100%; + height: 35px; + padding: 6px 12px; + font-size: 13px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #e0e0e0; + border-radius: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} + + .form-control:focus { + border-color: #b4b4b4; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(180, 180, 180, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(180, 180, 180, 0.6); + } + + .form-control::-moz-placeholder { + color: #999999; + opacity: 1; + } + + .form-control:-ms-input-placeholder { + color: #999999; + } + + .form-control::-webkit-input-placeholder { + color: #999999; + } + + .form-control[disabled], + .form-control[readonly], + fieldset[disabled] .form-control { + background-color: #eeeeee; + opacity: 1; + } + + .form-control[disabled], + fieldset[disabled] .form-control { + cursor: not-allowed; + } + +textarea.form-control { + height: auto; +} + +input[type="search"] { + -webkit-appearance: none; +} + +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 35px; + } + + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 40px; + } +} + +.form-group { + margin-bottom: 15px; +} + +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} + + .radio label, + .checkbox label { + min-height: 18px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; + } + + .radio input[type="radio"], + .radio-inline input[type="radio"], + .checkbox input[type="checkbox"], + .checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; + } + + .radio + .radio, + .checkbox + .checkbox { + margin-top: -5px; + } + +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} + + .radio-inline + .radio-inline, + .checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; + } + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} + +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} + +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} + +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; + min-height: 31px; +} + + .form-control-static.input-lg, + .form-control-static.input-sm { + padding-left: 0; + padding-right: 0; + } + +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} + +select.input-sm { + height: 30px; + line-height: 30px; +} + +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} + +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} + +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} + +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} + +.form-group-sm .form-control-static { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + min-height: 30px; +} + +.input-lg { + height: 40px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 0px; +} + +select.input-lg { + height: 40px; + line-height: 40px; +} + +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} + +.form-group-lg .form-control { + height: 40px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 0px; +} + +select.form-group-lg .form-control { + height: 40px; + line-height: 40px; +} + +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} + +.form-group-lg .form-control-static { + height: 40px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + min-height: 35px; +} + +.has-feedback { + position: relative; +} + + .has-feedback .form-control { + padding-right: 43.75px; + } + +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 35px; + height: 35px; + line-height: 35px; + text-align: center; + pointer-events: none; +} + +.input-lg + .form-control-feedback { + width: 40px; + height: 40px; + line-height: 40px; +} + +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} + +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #4caf50; +} + +.has-success .form-control { + border-color: #4caf50; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-success .form-control:focus { + border-color: #3d8b40; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #92cf94; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #92cf94; + } + +.has-success .input-group-addon { + color: #4caf50; + border-color: #4caf50; + background-color: #dff0d8; +} + +.has-success .form-control-feedback { + color: #4caf50; +} + +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #ff9800; +} + +.has-warning .form-control { + border-color: #ff9800; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-warning .form-control:focus { + border-color: #cc7a00; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffc166; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffc166; + } + +.has-warning .input-group-addon { + color: #ff9800; + border-color: #ff9800; + background-color: #fcf8e3; +} + +.has-warning .form-control-feedback { + color: #ff9800; +} + +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #f44336; +} + +.has-error .form-control { + border-color: #f44336; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-error .form-control:focus { + border-color: #ea1c0d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f99d97; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f99d97; + } + +.has-error .input-group-addon { + color: #f44336; + border-color: #f44336; + background-color: #f2dede; +} + +.has-error .form-control-feedback { + color: #f44336; +} + +.has-feedback label ~ .form-control-feedback { + top: 23px; +} + +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} + +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #9e9e9e; +} + +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .form-inline .form-control-static { + display: inline-block; + } + + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + + .form-inline .input-group > .form-control { + width: 100%; + } + + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} + +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} + +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 25px; +} + +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} + +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} + +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} + +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} + +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} + +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: 400; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 13px; + line-height: 1.42857143; + border-radius: 2px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + + .btn:focus, + .btn:active:focus, + .btn.active:focus, + .btn.focus, + .btn:active.focus, + .btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + outline: none !important; + } + + .btn:hover, + .btn:focus, + .btn.focus { + color: #333333; + text-decoration: none; + } + + .btn:active, + .btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + } + + .btn.disabled, + .btn[disabled], + fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + } + +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} + + .btn-default:hover, + .btn-default:focus, + .btn-default.focus, + .btn-default:active, + .btn-default.active, + .open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #e6e6e6; + border-color: #adadad; + } + + .btn-default:active, + .btn-default.active, + .open > .dropdown-toggle.btn-default { + background-image: none; + } + + .btn-default.disabled, + .btn-default[disabled], + fieldset[disabled] .btn-default, + .btn-default.disabled:hover, + .btn-default[disabled]:hover, + fieldset[disabled] .btn-default:hover, + .btn-default.disabled:focus, + .btn-default[disabled]:focus, + fieldset[disabled] .btn-default:focus, + .btn-default.disabled.focus, + .btn-default[disabled].focus, + fieldset[disabled] .btn-default.focus, + .btn-default.disabled:active, + .btn-default[disabled]:active, + fieldset[disabled] .btn-default:active, + .btn-default.disabled.active, + .btn-default[disabled].active, + fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; + } + + .btn-default .badge { + color: #ffffff; + background-color: #333333; + } + + .btn-default:hover, + .btn-default:focus, + .btn-default.focus, + .btn-default:active, + .open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #ffffff; + border-color: transparent; + } + + .btn-default:active, + .btn-default.active, + .open > .dropdown-toggle.btn-default { + background-image: none; + } + + .btn-default.disabled, + .btn-default[disabled], + fieldset[disabled] .btn-default, + .btn-default.disabled:hover, + .btn-default[disabled]:hover, + fieldset[disabled] .btn-default:hover, + .btn-default.disabled:focus, + .btn-default[disabled]:focus, + fieldset[disabled] .btn-default:focus, + .btn-default.disabled.focus, + .btn-default[disabled].focus, + fieldset[disabled] .btn-default.focus, + .btn-default.disabled:active, + .btn-default[disabled]:active, + fieldset[disabled] .btn-default:active { + background-color: #ffffff; + border-color: #cccccc; + } + + .btn-default .badge { + color: #ffffff; + background-color: #333333; + } + +.btn-primary { + color: #ffffff; + background-color: #2196f3; + border-color: #0d8aee; +} + + .btn-primary:hover, + .btn-primary:focus, + .btn-primary.focus, + .btn-primary:active, + .btn-primary.active, + .open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #0c7cd5; + border-color: #0a68b4; + } + + .btn-primary:active, + .btn-primary.active, + .open > .dropdown-toggle.btn-primary { + background-image: none; + } + + .btn-primary.disabled, + .btn-primary[disabled], + fieldset[disabled] .btn-primary, + .btn-primary.disabled:hover, + .btn-primary[disabled]:hover, + fieldset[disabled] .btn-primary:hover, + .btn-primary.disabled:focus, + .btn-primary[disabled]:focus, + fieldset[disabled] .btn-primary:focus, + .btn-primary.disabled.focus, + .btn-primary[disabled].focus, + fieldset[disabled] .btn-primary.focus, + .btn-primary.disabled:active, + .btn-primary[disabled]:active, + fieldset[disabled] .btn-primary:active, + .btn-primary.disabled.active, + .btn-primary[disabled].active, + fieldset[disabled] .btn-primary.active { + background-color: #2196f3; + border-color: #0d8aee; + } + + .btn-primary .badge { + color: #2196f3; + background-color: #ffffff; + } + + .btn-primary:hover, + .btn-primary:focus, + .btn-primary.focus, + .btn-primary:active, + .open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #2196f3; + border-color: transparent; + } + + .btn-primary:active, + .btn-primary.active, + .open > .dropdown-toggle.btn-primary { + background-image: none; + } + + .btn-primary.disabled, + .btn-primary[disabled], + fieldset[disabled] .btn-primary, + .btn-primary.disabled:hover, + .btn-primary[disabled]:hover, + fieldset[disabled] .btn-primary:hover, + .btn-primary.disabled:focus, + .btn-primary[disabled]:focus, + fieldset[disabled] .btn-primary:focus, + .btn-primary.disabled.focus, + .btn-primary[disabled].focus, + fieldset[disabled] .btn-primary.focus, + .btn-primary.disabled:active, + .btn-primary[disabled]:active, + fieldset[disabled] .btn-primary:active { + background-color: #2196f3; + border-color: #0d8aee; + } + + .btn-primary .badge { + color: #2196f3; + background-color: #ffffff; + } + +.btn-success { + color: #ffffff; + background-color: #4caf50; + border-color: #449d48; +} + + .btn-success:hover, + .btn-success:focus, + .btn-success.focus, + .btn-success:active, + .btn-success.active, + .open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #3d8b40; + border-color: #327334; + } + + .btn-success:active, + .btn-success.active, + .open > .dropdown-toggle.btn-success { + background-image: none; + } + + .btn-success.disabled, + .btn-success[disabled], + fieldset[disabled] .btn-success, + .btn-success.disabled:hover, + .btn-success[disabled]:hover, + fieldset[disabled] .btn-success:hover, + .btn-success.disabled:focus, + .btn-success[disabled]:focus, + fieldset[disabled] .btn-success:focus, + .btn-success.disabled.focus, + .btn-success[disabled].focus, + fieldset[disabled] .btn-success.focus, + .btn-success.disabled:active, + .btn-success[disabled]:active, + fieldset[disabled] .btn-success:active, + .btn-success.disabled.active, + .btn-success[disabled].active, + fieldset[disabled] .btn-success.active { + background-color: #4caf50; + border-color: #449d48; + } + + .btn-success .badge { + color: #4caf50; + background-color: #ffffff; + } + + .btn-success:hover, + .btn-success:focus, + .btn-success.focus, + .btn-success:active, + .open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #4caf50; + border-color: transparent; + } + + .btn-success:active, + .btn-success.active, + .open > .dropdown-toggle.btn-success { + background-image: none; + } + + .btn-success.disabled, + .btn-success[disabled], + fieldset[disabled] .btn-success, + .btn-success.disabled:hover, + .btn-success[disabled]:hover, + fieldset[disabled] .btn-success:hover, + .btn-success.disabled:focus, + .btn-success[disabled]:focus, + fieldset[disabled] .btn-success:focus, + .btn-success.disabled.focus, + .btn-success[disabled].focus, + fieldset[disabled] .btn-success.focus, + .btn-success.disabled:active, + .btn-success[disabled]:active, + fieldset[disabled] .btn-success:active { + background-color: #4caf50; + border-color: #449d48; + } + + .btn-success .badge { + color: #4caf50; + background-color: #ffffff; + } + +.btn-info { + color: #ffffff; + background-color: #00bcd4; + border-color: #00a5bb; +} + + .btn-info:hover, + .btn-info:focus, + .btn-info.focus, + .btn-info:active, + .btn-info.active, + .open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #008fa1; + border-color: #006f7d; + } + + .btn-info:active, + .btn-info.active, + .open > .dropdown-toggle.btn-info { + background-image: none; + } + + .btn-info.disabled, + .btn-info[disabled], + fieldset[disabled] .btn-info, + .btn-info.disabled:hover, + .btn-info[disabled]:hover, + fieldset[disabled] .btn-info:hover, + .btn-info.disabled:focus, + .btn-info[disabled]:focus, + fieldset[disabled] .btn-info:focus, + .btn-info.disabled.focus, + .btn-info[disabled].focus, + fieldset[disabled] .btn-info.focus, + .btn-info.disabled:active, + .btn-info[disabled]:active, + fieldset[disabled] .btn-info:active, + .btn-info.disabled.active, + .btn-info[disabled].active, + fieldset[disabled] .btn-info.active { + background-color: #00bcd4; + border-color: #00a5bb; + } + + .btn-info .badge { + color: #00bcd4; + background-color: #ffffff; + } + + .btn-info:hover, + .btn-info:focus, + .btn-info.focus, + .btn-info:active, + .open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #00bcd4; + border-color: transparent; + } + + .btn-info:active, + .btn-info.active, + .open > .dropdown-toggle.btn-info { + background-image: none; + } + + .btn-info.disabled, + .btn-info[disabled], + fieldset[disabled] .btn-info, + .btn-info.disabled:hover, + .btn-info[disabled]:hover, + fieldset[disabled] .btn-info:hover, + .btn-info.disabled:focus, + .btn-info[disabled]:focus, + fieldset[disabled] .btn-info:focus, + .btn-info.disabled.focus, + .btn-info[disabled].focus, + fieldset[disabled] .btn-info.focus, + .btn-info.disabled:active, + .btn-info[disabled]:active, + fieldset[disabled] .btn-info:active { + background-color: #00bcd4; + border-color: #00a5bb; + } + + .btn-info .badge { + color: #00bcd4; + background-color: #ffffff; + } + +.btn-warning { + color: #ffffff; + background-color: #ff9800; + border-color: #e68900; +} + + .btn-warning:hover, + .btn-warning:focus, + .btn-warning.focus, + .btn-warning:active, + .btn-warning.active, + .open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #cc7a00; + border-color: #a86400; + } + + .btn-warning:active, + .btn-warning.active, + .open > .dropdown-toggle.btn-warning { + background-image: none; + } + + .btn-warning.disabled, + .btn-warning[disabled], + fieldset[disabled] .btn-warning, + .btn-warning.disabled:hover, + .btn-warning[disabled]:hover, + fieldset[disabled] .btn-warning:hover, + .btn-warning.disabled:focus, + .btn-warning[disabled]:focus, + fieldset[disabled] .btn-warning:focus, + .btn-warning.disabled.focus, + .btn-warning[disabled].focus, + fieldset[disabled] .btn-warning.focus, + .btn-warning.disabled:active, + .btn-warning[disabled]:active, + fieldset[disabled] .btn-warning:active, + .btn-warning.disabled.active, + .btn-warning[disabled].active, + fieldset[disabled] .btn-warning.active { + background-color: #ff9800; + border-color: #e68900; + } + + .btn-warning .badge { + color: #ff9800; + background-color: #ffffff; + } + + .btn-warning:hover, + .btn-warning:focus, + .btn-warning.focus, + .btn-warning:active, + .open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ff9800; + border-color: transparent; + } + + .btn-warning:active, + .btn-warning.active, + .open > .dropdown-toggle.btn-warning { + background-image: none; + } + + .btn-warning.disabled, + .btn-warning[disabled], + fieldset[disabled] .btn-warning, + .btn-warning.disabled:hover, + .btn-warning[disabled]:hover, + fieldset[disabled] .btn-warning:hover, + .btn-warning.disabled:focus, + .btn-warning[disabled]:focus, + fieldset[disabled] .btn-warning:focus, + .btn-warning.disabled.focus, + .btn-warning[disabled].focus, + fieldset[disabled] .btn-warning.focus, + .btn-warning.disabled:active, + .btn-warning[disabled]:active, + fieldset[disabled] .btn-warning:active { + background-color: #ff9800; + border-color: #e68900; + } + + .btn-warning .badge { + color: #ff9800; + background-color: #ffffff; + } + +.btn-danger { + color: #ffffff; + background-color: #f44336; + border-color: #f32c1e; +} + + .btn-danger:hover, + .btn-danger:focus, + .btn-danger.focus, + .btn-danger:active, + .btn-danger.active, + .open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #ea1c0d; + border-color: #c8180b; + } + + .btn-danger:active, + .btn-danger.active, + .open > .dropdown-toggle.btn-danger { + background-image: none; + } + + .btn-danger.disabled, + .btn-danger[disabled], + fieldset[disabled] .btn-danger, + .btn-danger.disabled:hover, + .btn-danger[disabled]:hover, + fieldset[disabled] .btn-danger:hover, + .btn-danger.disabled:focus, + .btn-danger[disabled]:focus, + fieldset[disabled] .btn-danger:focus, + .btn-danger.disabled.focus, + .btn-danger[disabled].focus, + fieldset[disabled] .btn-danger.focus, + .btn-danger.disabled:active, + .btn-danger[disabled]:active, + fieldset[disabled] .btn-danger:active, + .btn-danger.disabled.active, + .btn-danger[disabled].active, + fieldset[disabled] .btn-danger.active { + background-color: #f44336; + border-color: #f32c1e; + } + + .btn-danger .badge { + color: #f44336; + background-color: #ffffff; + } + + .btn-danger:hover, + .btn-danger:focus, + .btn-danger.focus, + .btn-danger:active, + .open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #f44336; + border-color: transparent; + } + + .btn-danger:active, + .btn-danger.active, + .open > .dropdown-toggle.btn-danger { + background-image: none; + } + + .btn-danger.disabled, + .btn-danger[disabled], + fieldset[disabled] .btn-danger, + .btn-danger.disabled:hover, + .btn-danger[disabled]:hover, + fieldset[disabled] .btn-danger:hover, + .btn-danger.disabled:focus, + .btn-danger[disabled]:focus, + fieldset[disabled] .btn-danger:focus, + .btn-danger.disabled.focus, + .btn-danger[disabled].focus, + fieldset[disabled] .btn-danger.focus, + .btn-danger.disabled:active, + .btn-danger[disabled]:active, + fieldset[disabled] .btn-danger:active { + background-color: #f44336; + border-color: #f32c1e; + } + + .btn-danger .badge { + color: #f44336; + background-color: #ffffff; + } + +.btn-link { + color: #2196f3; + font-weight: normal; + border-radius: 0; +} + + .btn-link, + .btn-link:active, + .btn-link.active, + .btn-link[disabled], + fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; + } + + .btn-link, + .btn-link:hover, + .btn-link:focus, + .btn-link:active { + border-color: transparent; + } + + .btn-link:hover, + .btn-link:focus { + color: #0a6ebd; + text-decoration: none; + background-color: transparent; + } + + .btn-link[disabled]:hover, + fieldset[disabled] .btn-link:hover, + .btn-link[disabled]:focus, + fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; + } + +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 2px; +} + +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} + +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} + +.btn-block { + display: block; + width: 100%; +} + + .btn-block + .btn-block { + margin-top: 5px; + } + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + + .fade.in { + opacity: 1; + } + +.collapse { + display: none; +} + + .collapse.in { + display: block; + } + +tr.collapse.in { + display: table-row; +} + +tbody .collapse.in { + display: table-row-group; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + transition-timing-function: ease; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle:focus { + outline: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 9; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 13px; + text-align: left; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 2px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} + + .dropdown-menu.pull-right { + right: 0; + left: auto; + } + + .dropdown-menu .divider { + height: 1px; + margin: 8px 0; + overflow: hidden; + background-color: rgba(0, 0, 0, 0.08); + } + + .dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; + } + + .dropdown-menu > li > a:hover, + .dropdown-menu > li > a:focus { + text-decoration: none; + color: #333333; + background-color: rgba(0, 0, 0, 0.075); + } + + .dropdown-menu > .active > a, + .dropdown-menu > .active > a:hover, + .dropdown-menu > .active > a:focus { + color: #333333; + text-decoration: none; + outline: 0; + background-color: rgba(0, 0, 0, 0.075); + } + + .dropdown-menu > .disabled > a, + .dropdown-menu > .disabled > a:hover, + .dropdown-menu > .disabled > a:focus { + color: #e4e4e4; + } + + .dropdown-menu > .disabled > a:hover, + .dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; + } + +.open > .dropdown-menu { + display: block; +} + +.open > a { + outline: 0; +} + +.dropdown-menu-right { + left: auto; + right: 0; +} + +.dropdown-menu-left { + left: 0; + right: auto; +} + +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777777; + white-space: nowrap; +} + +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: -1; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} + +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} + + .btn-group > .btn, + .btn-group-vertical > .btn { + position: relative; + float: left; + } + + .btn-group > .btn:hover, + .btn-group-vertical > .btn:hover, + .btn-group > .btn:focus, + .btn-group-vertical > .btn:focus, + .btn-group > .btn:active, + .btn-group-vertical > .btn:active, + .btn-group > .btn.active, + .btn-group-vertical > .btn.active { + z-index: 2; + } + + .btn-group .btn + .btn, + .btn-group .btn + .btn-group, + .btn-group .btn-group + .btn, + .btn-group .btn-group + .btn-group { + margin-left: -1px; + } + +.btn-toolbar { + margin-left: -5px; +} + + .btn-toolbar .btn-group, + .btn-toolbar .input-group { + float: left; + } + + .btn-toolbar > .btn, + .btn-toolbar > .btn-group, + .btn-toolbar > .input-group { + margin-left: 5px; + } + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +.btn-group > .btn:first-child { + margin-left: 0; +} + + .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.btn-group > .btn-group { + float: left; +} + + .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; + } + + .btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, + .btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + .btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} + +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + + .btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; + } + +.btn .caret { + margin-left: 0; +} + +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} + +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} + +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} + + .btn-group-vertical > .btn-group > .btn { + float: none; + } + + .btn-group-vertical > .btn + .btn, + .btn-group-vertical > .btn + .btn-group, + .btn-group-vertical > .btn-group + .btn, + .btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; + } + + .btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; + } + + .btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 2px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + .btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 2px; + border-top-right-radius: 0; + border-top-left-radius: 0; + } + + .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; + } + + .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, + .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; + } + +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} + + .btn-group-justified > .btn, + .btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; + } + + .btn-group-justified > .btn-group .btn { + width: 100%; + } + + .btn-group-justified > .btn-group .dropdown-menu { + left: auto; + } + +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.input-group { + position: relative; + display: table; + border-collapse: separate; +} + + .input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; + } + + .input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; + } + +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 40px; + padding: 10px 16px; + font-size: 17px; + line-height: 1.3333333; + border-radius: 0px; +} + +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 40px; + line-height: 40px; +} + +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} + +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} + +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} + +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} + +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} + + .input-group-addon:not(:first-child):not(:last-child), + .input-group-btn:not(:first-child):not(:last-child), + .input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; + } + +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} + +.input-group-addon { + padding: 6px 12px; + font-size: 13px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: transparent; + border: 1px solid transparent; + border-radius: 2px; +} + + .input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 2px; + } + + .input-group-addon.input-lg { + padding: 10px 16px; + font-size: 17px; + border-radius: 2px; + } + + .input-group-addon input[type="radio"], + .input-group-addon input[type="checkbox"] { + margin-top: 0; + } + + .input-group .form-control:first-child, + .input-group-addon:first-child, + .input-group-btn:first-child > .btn, + .input-group-btn:first-child > .btn-group > .btn, + .input-group-btn:first-child > .dropdown-toggle, + .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), + .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + .input-group-addon:first-child { + border-right: 0; + } + + .input-group .form-control:last-child, + .input-group-addon:last-child, + .input-group-btn:last-child > .btn, + .input-group-btn:last-child > .btn-group > .btn, + .input-group-btn:last-child > .dropdown-toggle, + .input-group-btn:first-child > .btn:not(:first-child), + .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + + .input-group-addon:last-child { + border-left: 0; + } + +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} + + .input-group-btn > .btn { + position: relative; + } + + .input-group-btn > .btn + .btn { + margin-left: -1px; + } + + .input-group-btn > .btn:hover, + .input-group-btn > .btn:focus, + .input-group-btn > .btn:active { + z-index: 2; + } + + .input-group-btn:first-child > .btn, + .input-group-btn:first-child > .btn-group { + margin-right: -1px; + } + + .input-group-btn:last-child > .btn, + .input-group-btn:last-child > .btn-group { + margin-left: -1px; + } + +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} + + .nav > li { + position: relative; + display: block; + } + + .nav > li > a { + position: relative; + display: block; + padding: 10px 15px; + } + + .nav > li > a:hover, + .nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; + } + + .nav > li.disabled > a { + color: #777777; + } + + .nav > li.disabled > a:hover, + .nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; + } + + .nav .open > a, + .nav .open > a:hover, + .nav .open > a:focus { + background-color: #eeeeee; + border-color: #2196f3; + } + + .nav .nav-divider { + height: 1px; + margin: 8px 0; + overflow: hidden; + background-color: #e5e5e5; + } + + .nav > li > a > img { + max-width: none; + } + +.nav-tabs { + border-bottom: 1px solid #ffffff; +} + + .nav-tabs > li { + float: left; + margin-bottom: -1px; + } + + .nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 2px 2px 0 0; + } + + .nav-tabs > li > a:hover { + } + + .nav-tabs > li.active > a, + .nav-tabs > li.active > a:hover, + .nav-tabs > li.active > a:focus { + color: #555555; + background-color: transparent; + border: 1px solid #ffffff; + border-bottom-color: transparent; + cursor: default; + } + + .nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; + } + + .nav-tabs.nav-justified > li { + float: none; + } + + .nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; + } + + .nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; + } + +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} + +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 2px; +} + +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} + +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 2px 2px 0 0; + } + + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #edecec; + } +} + +.nav-pills > li { + float: left; +} + + .nav-pills > li > a { + border-radius: 2px; + } + + .nav-pills > li + li { + margin-left: 2px; + } + + .nav-pills > li.active > a, + .nav-pills > li.active > a:hover, + .nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #2196f3; + } + +.nav-stacked > li { + float: none; +} + + .nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; + } + +.nav-justified { + width: 100%; +} + + .nav-justified > li { + float: none; + } + + .nav-justified > li > a { + text-align: center; + margin-bottom: 5px; + } + + .nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; + } + +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-justified > li > a { + margin-bottom: 0; + } +} + +.nav-tabs-justified { + border-bottom: 0; +} + + .nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 2px; + } + + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; + } + +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 2px 2px 0 0; + } + + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #edecec; + } +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 18px; + border: 1px solid transparent; +} + +@media (min-width: 768px) { + .navbar { + border-radius: 2px; + } +} + +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} + +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} + + .navbar-collapse.in { + overflow-y: auto; + } + +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + + .navbar-collapse.in { + overflow-y: visible; + } + + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} + +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} + +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} + +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} + +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} + +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} + +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} + +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} + +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} + +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} + +.navbar-brand { + float: left; + padding: 16px 15px; + font-size: 17px; + line-height: 18px; + height: 50px; +} + + .navbar-brand:hover, + .navbar-brand:focus { + text-decoration: none; + } + + .navbar-brand > img { + display: block; + } + +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} + +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 2px; +} + + .navbar-toggle:focus { + outline: 0; + } + + .navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; + } + + .navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; + } + +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} + +.navbar-nav { + margin: 8px -15px; +} + + .navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 18px; + } + +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + + .navbar-nav .open .dropdown-menu > li > a { + line-height: 18px; + } + + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} + +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + + .navbar-nav > li { + float: left; + } + + .navbar-nav > li > a { + padding-top: 16px; + padding-bottom: 16px; + } +} + +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 7.5px; + margin-bottom: 7.5px; +} + +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .navbar-form .form-control-static { + display: inline-block; + } + + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + + .navbar-form .input-group > .form-control { + width: 100%; + } + + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} + +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} + +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} + +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 2px; + border-top-left-radius: 2px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.navbar-btn { + margin-top: 7.5px; + margin-bottom: 7.5px; +} + + .navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; + } + + .navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; + } + +.navbar-text { + margin-top: 16px; + margin-bottom: 16px; +} + +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} + +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + + .navbar-right { + float: right !important; + margin-right: -15px; + } + + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} + +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} + + .navbar-default .navbar-brand { + color: #777777; + } + + .navbar-default .navbar-brand:hover, + .navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; + } + + .navbar-default .navbar-text { + color: #777777; + } + + .navbar-default .navbar-nav > li > a { + color: #777777; + } + + .navbar-default .navbar-nav > li > a:hover, + .navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; + } + + .navbar-default .navbar-nav > .active > a, + .navbar-default .navbar-nav > .active > a:hover, + .navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + + .navbar-default .navbar-nav > .disabled > a, + .navbar-default .navbar-nav > .disabled > a:hover, + .navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } + + .navbar-default .navbar-toggle { + border-color: #dddddd; + } + + .navbar-default .navbar-toggle:hover, + .navbar-default .navbar-toggle:focus { + background-color: #dddddd; + } + + .navbar-default .navbar-toggle .icon-bar { + background-color: #888888; + } + + .navbar-default .navbar-collapse, + .navbar-default .navbar-form { + border-color: #e7e7e7; + } + + .navbar-default .navbar-nav > .open > a, + .navbar-default .navbar-nav > .open > a:hover, + .navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555555; + } + +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} + +.navbar-default .navbar-link { + color: #777777; +} + + .navbar-default .navbar-link:hover { + color: #333333; + } + +.navbar-default .btn-link { + color: #777777; +} + + .navbar-default .btn-link:hover, + .navbar-default .btn-link:focus { + color: #333333; + } + + .navbar-default .btn-link[disabled]:hover, + fieldset[disabled] .navbar-default .btn-link:hover, + .navbar-default .btn-link[disabled]:focus, + fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; + } + +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} + + .navbar-inverse .navbar-brand { + color: #9d9d9d; + } + + .navbar-inverse .navbar-brand:hover, + .navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; + } + + .navbar-inverse .navbar-text { + color: #9d9d9d; + } + + .navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; + } + + .navbar-inverse .navbar-nav > li > a:hover, + .navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; + } + + .navbar-inverse .navbar-nav > .active > a, + .navbar-inverse .navbar-nav > .active > a:hover, + .navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + + .navbar-inverse .navbar-nav > .disabled > a, + .navbar-inverse .navbar-nav > .disabled > a:hover, + .navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; + } + + .navbar-inverse .navbar-toggle { + border-color: #333333; + } + + .navbar-inverse .navbar-toggle:hover, + .navbar-inverse .navbar-toggle:focus { + background-color: #333333; + } + + .navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; + } + + .navbar-inverse .navbar-collapse, + .navbar-inverse .navbar-form { + border-color: #101010; + } + + .navbar-inverse .navbar-nav > .open > a, + .navbar-inverse .navbar-nav > .open > a:hover, + .navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; + } + +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} + +.navbar-inverse .navbar-link { + color: #9d9d9d; +} + + .navbar-inverse .navbar-link:hover { + color: #ffffff; + } + +.navbar-inverse .btn-link { + color: #9d9d9d; +} + + .navbar-inverse .btn-link:hover, + .navbar-inverse .btn-link:focus { + color: #ffffff; + } + + .navbar-inverse .btn-link[disabled]:hover, + fieldset[disabled] .navbar-inverse .btn-link:hover, + .navbar-inverse .btn-link[disabled]:focus, + fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444444; + } + +.breadcrumb { + padding: 8px 20px; + margin-bottom: 18px; + list-style: none; + background-color: transparent; + border-radius: 2px; +} + + .breadcrumb > li { + display: inline-block; + } + + .breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; + } + + .breadcrumb > .active { + color: #7c7c7c; + } + +.pagination { + display: inline-block; + padding-left: 0; + position:relative; + margin: 18px 0; + border-radius: 2px; +} + + .pagination > li { + display: inline; + } + + .pagination > li > a, + .pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #7e7e7e; + background-color: #e2e2e2; + background-image:none; + border: 1px solid #ffffff; + margin-left: -1px; + } + + .pagination > li:first-child > a, + .pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; + } + + .pagination > li:last-child > a, + .pagination > li:last-child > span { + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; + } + + .pagination > li > a:hover, + .pagination > li > span:hover, + .pagination > li > a:focus, + .pagination > li > span:focus { + color: #333333; + background-color: #d7d7d7; + border-color: #ffffff; + } + + .pagination > .active > a, + .pagination > .active > span, + .pagination > .active > a:hover, + .pagination > .active > span:hover, + .pagination > .active > a:focus, + .pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #00bcd4; + border-color: #ffffff; + cursor: default; + } + + .pagination > .disabled > span, + .pagination > .disabled > span:hover, + .pagination > .disabled > span:focus, + .pagination > .disabled > a, + .pagination > .disabled > a:hover, + .pagination > .disabled > a:focus { + color: #777777; + background-color: #e2e2e2; + border-color: #ffffff; + cursor: not-allowed; + } + +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 17px; +} + +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} + +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} + +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} + +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} + +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} + +.pager { + padding-left: 0; + margin: 18px 0; + list-style: none; + text-align: center; +} + + .pager li { + display: inline; + } + + .pager li > a, + .pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #e2e2e2; + border: 1px solid #ffffff; + border-radius: 15px; + } + + .pager li > a:hover, + .pager li > a:focus { + text-decoration: none; + background-color: #d7d7d7; + } + + .pager .next > a, + .pager .next > span { + float: right; + } + + .pager .previous > a, + .pager .previous > span { + float: left; + } + + .pager .disabled > a, + .pager .disabled > a:hover, + .pager .disabled > a:focus, + .pager .disabled > span { + color: #777777; + background-color: #e2e2e2; + cursor: not-allowed; + } + +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} + +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label:empty { + display: none; +} + +.btn .label { + position: relative; + top: -1px; +} + +.label-default { + background-color: #777777; +} + + .label-default[href]:hover, + .label-default[href]:focus { + background-color: #5e5e5e; + } + +.label-primary { + background-color: #2196f3; +} + + .label-primary[href]:hover, + .label-primary[href]:focus { + background-color: #0c7cd5; + } + +.label-success { + background-color: #4caf50; +} + + .label-success[href]:hover, + .label-success[href]:focus { + background-color: #3d8b40; + } + +.label-info { + background-color: #00bcd4; +} + + .label-info[href]:hover, + .label-info[href]:focus { + background-color: #008fa1; + } + +.label-warning { + background-color: #ff9800; +} + + .label-warning[href]:hover, + .label-warning[href]:focus { + background-color: #cc7a00; + } + +.label-danger { + background-color: #f44336; +} + + .label-danger[href]:hover, + .label-danger[href]:focus { + background-color: #ea1c0d; + } + +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: 400; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #2196f3; + border-radius: 2px; +} + + .badge:empty { + display: none; + } + +.btn .badge { + position: relative; + top: -1px; +} + +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} + +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #ffffff; + background-color: #2196f3; +} + +.list-group-item > .badge { + float: right; +} + + .list-group-item > .badge + .badge { + margin-right: 5px; + } + +.nav-pills > li > a > .badge { + margin-left: 3px; +} + +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #f7f7f7; +} + + .jumbotron h1, + .jumbotron .h1 { + color: inherit; + } + + .jumbotron p { + margin-bottom: 15px; + font-size: 20px; + font-weight: 200; + } + + .jumbotron > hr { + border-top-color: #dedede; + } + +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 2px; +} + +.jumbotron .container { + max-width: 100%; +} + +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + + .jumbotron h1, + .jumbotron .h1 { + font-size: 58.5px; + } +} + +.thumbnail { + display: block; + padding: 3px; + margin-bottom: 18px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #ededed; + border-radius: 2px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} + + .thumbnail > img, + .thumbnail a > img { + margin-left: auto; + margin-right: auto; + } + +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #2196f3; +} + +.thumbnail .caption { + padding: 9px; + color: #5e5e5e; +} + +.alert { + padding: 15px; + margin-bottom: 18px; + border: 1px solid transparent; + border-radius: 2px; +} + + .alert h4 { + margin-top: 0; + color: inherit; + } + + .alert .alert-link { + font-weight: bold; + } + + .alert > p, + .alert > ul { + margin-bottom: 0; + } + + .alert > p + p { + margin-top: 5px; + } + +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} + + .alert-dismissable .close, + .alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; + } + +.alert-success { + background-color: #dff0d8; + border-color: #dff0d8; + color: #4caf50; +} + + .alert-success hr { + border-top-color: #d0e9c6; + } + + .alert-success .alert-link { + color: #3d8b40; + } + +.alert-info { + background-color: #d9edf7; + border-color: #d9edf7; + color: #2196f3; +} + + .alert-info hr { + border-top-color: #c4e3f3; + } + + .alert-info .alert-link { + color: #0c7cd5; + } + +.alert-warning { + background-color: rgba(255, 193, 7, 0.7); + border-color: transparent; + color: #ffffff; +} + + .alert-warning hr { + border-top-color: #ffe2bd; + } + + .alert-warning .alert-link { + color: #cc7a00; + } + +.alert-danger { + background-color: rgba(244, 67, 54, 0.7); + border-color: transparent; + color: #ffffff; +} + + .alert-danger hr { + border-top-color: #ebcccc; + } + + .alert-danger .alert-link { + color: #ea1c0d; + } + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + + to { + background-position: 0 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + + to { + background-position: 0 0; + } +} + +.progress { + overflow: hidden; + height: 18px; + margin-bottom: 18px; + background-color: #f5f5f5; + border-radius: 2px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 18px; + color: #ffffff; + text-align: center; + background-color: #2196f3; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} + +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-bar-success { + background-color: #4caf50; +} + +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-info { + background-color: #00bcd4; +} + +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-warning { + background-color: #ff9800; +} + +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-danger { + background-color: #f44336; +} + +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.media { + margin-top: 15px; +} + + .media:first-child { + margin-top: 0; + } + +.media, +.media-body { + zoom: 1; + overflow: hidden; +} + +.media-body { + width: 10000px; +} + +.media-object { + display: block; +} + +.media-right, +.media > .pull-right { + padding-left: 10px; +} + +.media-left, +.media > .pull-left { + padding-right: 10px; +} + +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} + +.media-middle { + vertical-align: middle; +} + +.media-bottom { + vertical-align: bottom; +} + +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} + +.media-list { + padding-left: 0; + list-style: none; +} + +.list-group { + margin-bottom: 20px; + padding-left: 0; +} + +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #e9e9e9; +} + + .list-group-item:first-child { + border-top-right-radius: 2px; + border-top-left-radius: 2px; + } + + .list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; + } + +a.list-group-item { + color: #555555; +} + + a.list-group-item .list-group-item-heading { + color: #333333; + } + + a.list-group-item:hover, + a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; + } + +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #ffffff; + color: #b5b4b4; + cursor: not-allowed; +} + + .list-group-item.disabled .list-group-item-heading, + .list-group-item.disabled:hover .list-group-item-heading, + .list-group-item.disabled:focus .list-group-item-heading { + color: inherit; + } + + .list-group-item.disabled .list-group-item-text, + .list-group-item.disabled:hover .list-group-item-text, + .list-group-item.disabled:focus .list-group-item-text { + color: #b5b4b4; + } + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #000000; + background-color: #f5f5f5; + border-color: #e9e9e9; +} + + .list-group-item.active .list-group-item-heading, + .list-group-item.active:hover .list-group-item-heading, + .list-group-item.active:focus .list-group-item-heading, + .list-group-item.active .list-group-item-heading > small, + .list-group-item.active:hover .list-group-item-heading > small, + .list-group-item.active:focus .list-group-item-heading > small, + .list-group-item.active .list-group-item-heading > .small, + .list-group-item.active:hover .list-group-item-heading > .small, + .list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; + } + + .list-group-item.active .list-group-item-text, + .list-group-item.active:hover .list-group-item-text, + .list-group-item.active:focus .list-group-item-text { + color: #ffffff; + } + +.list-group-item-success { + color: #4caf50; + background-color: #dff0d8; +} + +a.list-group-item-success { + color: #4caf50; +} + + a.list-group-item-success .list-group-item-heading { + color: inherit; + } + + a.list-group-item-success:hover, + a.list-group-item-success:focus { + color: #4caf50; + background-color: #d0e9c6; + } + + a.list-group-item-success.active, + a.list-group-item-success.active:hover, + a.list-group-item-success.active:focus { + color: #fff; + background-color: #4caf50; + border-color: #4caf50; + } + +.list-group-item-info { + color: #2196f3; + background-color: #d9edf7; +} + +a.list-group-item-info { + color: #2196f3; +} + + a.list-group-item-info .list-group-item-heading { + color: inherit; + } + + a.list-group-item-info:hover, + a.list-group-item-info:focus { + color: #2196f3; + background-color: #c4e3f3; + } + + a.list-group-item-info.active, + a.list-group-item-info.active:hover, + a.list-group-item-info.active:focus { + color: #fff; + background-color: #2196f3; + border-color: #2196f3; + } + +.list-group-item-warning { + color: #ff9800; + background-color: #fcf8e3; +} + +a.list-group-item-warning { + color: #ff9800; +} + + a.list-group-item-warning .list-group-item-heading { + color: inherit; + } + + a.list-group-item-warning:hover, + a.list-group-item-warning:focus { + color: #ff9800; + background-color: #faf2cc; + } + + a.list-group-item-warning.active, + a.list-group-item-warning.active:hover, + a.list-group-item-warning.active:focus { + color: #fff; + background-color: #ff9800; + border-color: #ff9800; + } + +.list-group-item-danger { + color: #f44336; + background-color: #f2dede; +} + +a.list-group-item-danger { + color: #f44336; +} + + a.list-group-item-danger .list-group-item-heading { + color: inherit; + } + + a.list-group-item-danger:hover, + a.list-group-item-danger:focus { + color: #f44336; + background-color: #ebcccc; + } + + a.list-group-item-danger.active, + a.list-group-item-danger.active:hover, + a.list-group-item-danger.active:focus { + color: #fff; + background-color: #f44336; + border-color: #f44336; + } + +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} + +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + +.panel { + margin-bottom: 18px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 2px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.panel-body { + padding: 15px; +} + +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 1px; + border-top-left-radius: 1px; +} + + .panel-heading > .dropdown .dropdown-toggle { + color: inherit; + } + +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 15px; + color: inherit; +} + + .panel-title > a, + .panel-title > small, + .panel-title > .small, + .panel-title > small > a, + .panel-title > .small > a { + color: inherit; + } + +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; +} + +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} + + .panel > .list-group .list-group-item, + .panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; + } + + .panel > .list-group:first-child .list-group-item:first-child, + .panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 1px; + border-top-left-radius: 1px; + } + + .panel > .list-group:last-child .list-group-item:last-child, + .panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + } + +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} + +.list-group + .panel-footer { + border-top-width: 0; +} + +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} + + .panel > .table caption, + .panel > .table-responsive > .table caption, + .panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; + } + + .panel > .table:first-child, + .panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 1px; + border-top-left-radius: 1px; + } + + .panel > .table:first-child > thead:first-child > tr:first-child, + .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, + .panel > .table:first-child > tbody:first-child > tr:first-child, + .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 1px; + border-top-right-radius: 1px; + } + + .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, + .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, + .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, + .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, + .panel > .table:first-child > thead:first-child > tr:first-child th:first-child, + .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, + .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, + .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 1px; + } + + .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, + .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, + .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, + .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, + .panel > .table:first-child > thead:first-child > tr:first-child th:last-child, + .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, + .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, + .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 1px; + } + + .panel > .table:last-child, + .panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + } + + .panel > .table:last-child > tbody:last-child > tr:last-child, + .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, + .panel > .table:last-child > tfoot:last-child > tr:last-child, + .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 1px; + border-bottom-right-radius: 1px; + } + + .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, + .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, + .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, + .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, + .panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, + .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, + .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, + .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 1px; + } + + .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, + .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, + .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, + .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, + .panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, + .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, + .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, + .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 1px; + } + + .panel > .panel-body + .table, + .panel > .panel-body + .table-responsive, + .panel > .table + .panel-body, + .panel > .table-responsive + .panel-body { + border-top: 1px solid #f0f0f0; + } + + .panel > .table > tbody:first-child > tr:first-child th, + .panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; + } + +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} + + .panel > .table-bordered > thead > tr > th:first-child, + .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, + .panel > .table-bordered > tbody > tr > th:first-child, + .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, + .panel > .table-bordered > tfoot > tr > th:first-child, + .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .panel > .table-bordered > thead > tr > td:first-child, + .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, + .panel > .table-bordered > tbody > tr > td:first-child, + .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, + .panel > .table-bordered > tfoot > tr > td:first-child, + .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + + .panel > .table-bordered > thead > tr > th:last-child, + .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, + .panel > .table-bordered > tbody > tr > th:last-child, + .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, + .panel > .table-bordered > tfoot > tr > th:last-child, + .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .panel > .table-bordered > thead > tr > td:last-child, + .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, + .panel > .table-bordered > tbody > tr > td:last-child, + .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, + .panel > .table-bordered > tfoot > tr > td:last-child, + .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + + .panel > .table-bordered > thead > tr:first-child > td, + .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, + .panel > .table-bordered > tbody > tr:first-child > td, + .panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, + .panel > .table-bordered > thead > tr:first-child > th, + .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, + .panel > .table-bordered > tbody > tr:first-child > th, + .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; + } + + .panel > .table-bordered > tbody > tr:last-child > td, + .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, + .panel > .table-bordered > tfoot > tr:last-child > td, + .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, + .panel > .table-bordered > tbody > tr:last-child > th, + .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, + .panel > .table-bordered > tfoot > tr:last-child > th, + .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; + } + +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} + +.panel-group { + margin-bottom: 18px; +} + + .panel-group .panel { + margin-bottom: 0; + border-radius: 2px; + } + + .panel-group .panel + .panel { + margin-top: 5px; + } + + .panel-group .panel-heading { + border-bottom: 0; + } + + .panel-group .panel-heading + .panel-collapse > .panel-body, + .panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #dddddd; + } + + .panel-group .panel-footer { + border-top: 0; + } + + .panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; + } + +.panel-default { + border-color: #dddddd; +} + + .panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; + } + + .panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #dddddd; + } + + .panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; + } + + .panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #dddddd; + } + +.panel-primary { + border-color: #2196f3; +} + + .panel-primary > .panel-heading { + color: #ffffff; + background-color: #2196f3; + border-color: #2196f3; + } + + .panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #2196f3; + } + + .panel-primary > .panel-heading .badge { + color: #2196f3; + background-color: #ffffff; + } + + .panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #2196f3; + } + +.panel-success { + border-color: #d6e9c6; +} + + .panel-success > .panel-heading { + color: #4caf50; + background-color: #dff0d8; + border-color: #d6e9c6; + } + + .panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; + } + + .panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #4caf50; + } + + .panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; + } + +.panel-info { + border-color: #bce8f1; +} + + .panel-info > .panel-heading { + color: #2196f3; + background-color: #d9edf7; + border-color: #bce8f1; + } + + .panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; + } + + .panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #2196f3; + } + + .panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; + } + +.panel-warning { + border-color: #faebcc; +} + + .panel-warning > .panel-heading { + color: #ff9800; + background-color: #fcf8e3; + border-color: #faebcc; + } + + .panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; + } + + .panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #ff9800; + } + + .panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; + } + +.panel-danger { + border-color: #ebccd1; +} + + .panel-danger > .panel-heading { + color: #f44336; + background-color: #f2dede; + border-color: #ebccd1; + } + + .panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; + } + + .panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #f44336; + } + + .panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; + } + +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} + + .embed-responsive .embed-responsive-item, + .embed-responsive iframe, + .embed-responsive embed, + .embed-responsive object, + .embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; + } + +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} + +.embed-responsive-4by3 { + padding-bottom: 75%; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 2px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + + .well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); + } + +.well-lg { + padding: 24px; + border-radius: 2px; +} + +.well-sm { + padding: 9px; + border-radius: 2px; +} + +.close { + float: right; + font-size: 19.5px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + + .close:hover, + .close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); + } + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { +} + +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} + + .modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + } + + .modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); + } + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} + +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 2px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 0; + background-color: #000000; +} + + .modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); + } + + .modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); + } + +.modal-header { + padding: 15px; + border-bottom: 1px solid transparent; + min-height: #0f0f0f; +} + + .modal-header .close { + margin-top: -2px; + } + +.modal-title { + margin: 0; + line-height: transparent; +} + +.modal-body { + position: relative; + padding: 15px; +} + +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid transparent; +} + + .modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; + } + + .modal-footer .btn-group .btn + .btn { + margin-left: -1px; + } + + .modal-footer .btn-block + .btn-block { + margin-left: 0; + } + +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + + .modal-sm { + width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} + +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: roboto; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} + + .tooltip.in { + opacity: 1; + filter: alpha(opacity=100); + } + + .tooltip.top { + margin-top: -3px; + padding: 5px 0; + } + + .tooltip.right { + margin-left: 3px; + padding: 0 5px; + } + + .tooltip.bottom { + margin-top: 3px; + padding: 5px 0; + } + + .tooltip.left { + margin-left: -3px; + padding: 0 5px; + } + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #fa1414; + border-radius: 2px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #737373; +} + +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #737373; +} + +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #737373; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #fa1414; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #737373; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #737373; +} + +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #737373; +} + +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #737373; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: roboto; + font-size: 13px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #ffffff; + border-radius: 2px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} + + .popover.top { + margin-top: -10px; + } + + .popover.right { + margin-left: 10px; + } + + .popover.bottom { + margin-top: 10px; + } + + .popover.left { + margin-left: -10px; + } + +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 13px; + background-color: #ffffff; + border-bottom: 1px solid #f2f2f2; + border-radius: 1px 1px 0 0; +} + +.popover-content { + padding: 9px 14px; +} + +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover > .arrow { + border-width: 11px; +} + + .popover > .arrow:after { + border-width: 10px; + content: ""; + } + +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #cccccc; + border-top-color: #ffffff; + bottom: -11px; +} + + .popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; + } + +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #cccccc; + border-right-color: #ffffff; +} + + .popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; + } + +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #cccccc; + border-bottom-color: #ffffff; + top: -11px; +} + + .popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; + } + +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #cccccc; + border-left-color: #ffffff; +} + + .popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; + } + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} + + .carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; + } + + .carousel-inner > .item > img, + .carousel-inner > .item > a > img { + line-height: 1; + } + +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -moz-transition: -moz-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + -moz-perspective: 1000; + perspective: 1000; + } + + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + + .carousel-inner > .next.left, + .carousel-inner > .prev.right { + left: 0; + } + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} + + .carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + } + + .carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + } + + .carousel-control:hover, + .carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); + } + + .carousel-control .icon-prev, + .carousel-control .icon-next, + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + } + + .carousel-control .icon-prev, + .carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; + } + + .carousel-control .icon-next, + .carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; + } + + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + line-height: 1; + font-family: serif; + } + + .carousel-control .icon-prev:before { + content: '\2039'; + } + + .carousel-control .icon-next:before { + content: '\203a'; + } + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} + + .carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + } + + .carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; + } + +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} + + .carousel-caption .btn { + text-shadow: none; + } + +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + + .carousel-indicators { + bottom: 20px; + } +} + +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} + +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} + +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} + +.pull-right { + float: right !important; +} + +.pull-left { + float: left !important; +} + +.hide { + display: none !important; +} + +.show { + display: block !important; +} + +.invisible { + visibility: hidden; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.hidden { + display: none !important; +} + +.affix { + position: fixed; +} + +@-ms-viewport { + width: device-width; +} + +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} + +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} + +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + + table.visible-xs { + display: table; + } + + tr.visible-xs { + display: table-row !important; + } + + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} + +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} + +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} + +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + + table.visible-sm { + display: table; + } + + tr.visible-sm { + display: table-row !important; + } + + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + + table.visible-md { + display: table; + } + + tr.visible-md { + display: table-row !important; + } + + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} + +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + + table.visible-lg { + display: table; + } + + tr.visible-lg { + display: table-row !important; + } + + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} + +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} + +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} + +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: block !important; + } + + table.visible-print { + display: table; + } + + tr.visible-print { + display: table-row !important; + } + + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} + +.visible-print-block { + display: none !important; +} + +@media print { + .visible-print-block { + display: block !important; + } +} + +.visible-print-inline { + display: none !important; +} + +@media print { + .visible-print-inline { + display: inline !important; + } +} + +.visible-print-inline-block { + display: none !important; +} + +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} + +@media print { + .hidden-print { + display: none !important; + } +} + +/* + * LESS Plugins + */ + +/* + * Variable and Mixin + */ + +/* + * Font Icon Family + */ + +/* + * Grid System + */ + +/* Typography + Scaffolding + Links */ + +/* Border Radius */ + +/* Colors */ + +/* Tabs */ + +/* Form */ + +/* Table */ + +/* + * Input Group + */ + +/* + * Pagination + */ + +/* + * Popover + */ + +/* + * Dropdown + */ + +/* + * Thumbnail + */ + +/* + * Form Stats and Alerts + */ + +/* + * Buttons + */ + +/* + * Thumbnail + */ + +/* + * Carousel + */ + +/* + * Modal + */ + +/* + * Tooltips + */ + +/* + * Popover + */ + +/* + * Breadcrumbs + */ + +/* + * Jumbotron + */ + +/* + * List Groups + */ + +/* + * Badges + */ + +/* + * Material Colors + */ + +/* + * Font Face + */ + +/* + * Background Repeat + Position + */ + +/* + * CSS Animations based on animate.css + */ + +/* + * CSS Transform - Scale and Rotate + */ + +/* + * User Select + */ + +/* + * Background Image Cover + */ + +/* + * Tab Focus + */ + +/* + * Pop-in Hover effects + */ + +/* + * Override Bootstrap Button Mixin + */ + +/* + * Scale 3d + */ + +/* + * Load Font + */ + +/* + * Roboto 300 + */ + +@font-face { + font-family: "roboto"; + font-style: normal; + font-weight: 300; + src: url("fonts/Roboto-Light-webfont.eot?#iefix") format("embedded-opentype"), url("fonts/Roboto-Light-webfont.woff") format("woff"), url("fonts/Roboto-Light-webfont.ttf") format("truetype"), url("fonts/Roboto-Light-webfont.svg#icon") format("svg"); +} + +@font-face { + font-family: "roboto"; + font-style: normal; + font-weight: 400; + src: url("fonts/Roboto-Regular-webfont.eot?#iefix") format("embedded-opentype"), url("fonts/Roboto-Regular-webfont.woff") format("woff"), url("fonts/Roboto-Regular-webfont.ttf") format("truetype"), url("fonts/Roboto-Regular-webfont.svg#icon") format("svg"); +} + +@font-face { + font-family: "roboto"; + font-style: normal; + font-weight: 500; + src: url("fonts/Roboto-Medium-webfont.eot?#iefix") format("embedded-opentype"), url("fonts/Roboto-Medium-webfont.woff") format("woff"), url("fonts/Roboto-Medium-webfont.ttf") format("truetype"), url("fonts/Roboto-Medium-webfont.svg#icon") format("svg"); +} + +@font-face { + font-family: "roboto"; + font-style: normal; + font-weight: 700; + src: url("fonts/Roboto-Bold-webfont.eot?#iefix") format("embedded-opentype"), url("fonts/Roboto-Bold-webfont.woff") format("woff"), url("fonts/Roboto-Bold-webfont.ttf") format("truetype"), url("fonts/Roboto-Bold-webfont.svg#icon") format("svg"); +} + +/* + * Shadow Light normal + */ + +@font-face { + font-family: 'shadowsintolight'; + src: url(data:font-woff;base64,d09GRgABAAAAAGXYABEAAAAAp7QAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABgAAAABwAAAAca6kqtEdERUYAAAGcAAAAHAAAAB4AJwB9T1MvMgAAAbgAAABRAAAAYEb4UbRjbWFwAAACDAAAANEAAAGCcfN7jGN2dCAAAALgAAAATAAAAEwLvg8NZnBnbQAAAywAAAGxAAACZVO0L6dnYXNwAAAE4AAAAAgAAAAIAAAAEGdseWYAAAToAABSXwAAdXjeAnJuaGVhZAAAV0gAAAAxAAAANgi7IVFoaGVhAABXfAAAAB0AAAAkECMFfGhtdHgAAFecAAABbAAAAdyPFw7vbG9jYQAAWQgAAADcAAAA8Ma35shtYXhwAABZ5AAAAB8AAAAgAZQCkW5hbWUAAFoEAAAKIQAAJkztWZoJcG9zdAAAZCgAAAEIAAABuisiJjxwcmVwAABlMAAAAJ8AAADrprJQ0ndlYmYAAGXQAAAABgAAAAY6rFVBAAAAAQAAAADQyg1XAAAAAMl4MjEAAAAA0WbrK3jaY2BkYGDgAWIxIGZiYATCMiBmAfMYAAiwAKV42mNgZk5inMDAysDCOovVhIGBUQ5CM19gSGNiYGAAYQhYwMCgH8DA4AXjKwABgwMDr+oftrR/aQwMnGnME4D6J4PkWLpYd4GUMDACACFGDDoAAAB42mNgYGBmgGAZBkYGEKgB8hjBfBaGBCAtwiAAFGFh4GWoY1jAsFaBS0FEQV8hXvXP//9AWV4GBbAog4IATPT/1/+P/x/6v+1ByoP4B64PxG5VQU3GAIxsDHApRiYgwYSuAOg0FlY2dg5OLm4eXj5+AUEhYRFRMXEJSSlpGVk5eQVFJWUVVTV1DU0tbR1dPX0DQyNjE1MzcwtLK2sbWzt7B0cnZxdXN3cPTy9vH18//4DAoOCQ0LDwiMio6JjYuPiERAbqgSQwWVRMmi4A9dQuSwAAAAAoA7QE+gBmAEwAVgBgAHEAggCHAGYATgBaAGIAbwB1AIQANgBeAFwAUgBFAHMAawBQAGkAjQB4AH8AfQCLADkARwBYAC4APgA8BRF42l1Ru05bQRDdDQ8DgcTYIDnaFLOZkMZ7oQUJxNWNYmQ7heUIaTdykYtxAR9AgUQN2q8ZoKGkSJsGIRdIfEI+IRIza4iiNDs7s3POmTNLypGqd+lrz1PnJJDC3QbNNv1OSLWzAPek6+uNjLSDB1psZvTKdfv+Cwab0ZQ7agDlPW8pDxlNO4FatKf+0fwKhvv8H/M7GLQ00/TUOgnpIQTmm3FLg+8ZzbrLD/qC1eFiMDCkmKbiLj+mUv63NOdqy7C1kdG8gzMR+ck0QFNrbQSa/tQh1fNxFEuQy6axNpiYsv4kE8GFyXRVU7XM+NrBXbKz6GCDKs2BB9jDVnkMHg4PJhTStyTKLA0R9mKrxAgRkxwKOeXcyf6kQPlIEsa8SUo744a1BsaR18CgNk+z/zybTW1vHcL4WRzBd78ZSzr4yIbaGBFiO2IpgAlEQkZV+YYaz70sBuRS+89AlIDl8Y9/nQi07thEPJe1dQ4xVgh6ftvc8suKu1a5zotCd2+qaqjSKc37Xs6+xwOeHgvDQWPBm8/7/kqB+jwsrjRoDgRDejd6/6K16oirvBc+sifTv7FaAAAAAAEAAf//AA942pS9D3Qb15kvNjMYDIbD4XAwGA6GI3A0HIIACEIAOARBAoIgCKZhmqZpmmYYhstlWIVhGD4+Rqvl6umpqp6entbV09PquKqq1aqqjp/rpq5XdWcAWZujev0Qb46buqqeT5qn3ZPmpTlu6ppbb46fm+dYtgT1u3dAmU6y7alkXczcGfyZe7/v9/2+P/eaoIhRgqCWvV8hPISPSDokkSpUfXTH31kO4/1poeqh4JBwPKjbi7qrPqb3fqFKov5Bf7e/t9vfPUoZjTB5ubHq/cpnfz5K/88EfCQRgvZj5g7RScSIBaLaSxD9zm52y25JkXZfymbuOjy/ZfNi7ff4dqHfIYUtm0w57QLqczSy3zFbt5w4vLYzfslWc7bmt6WcbUpOQM7lCKdlN+5OD0iR7FBGGi6Sg5ZOMh1+eTepkz6B7DEDQxnUq3TITI+ZJE2GEXlGFGSRoRieZVg6ooQP0jwfE4QYz9PUZ0tL6vfItbrIKSGTf3A1HJuKVVTFeHDC4BQxooXCooKfLeNpkKvMFCETOvEBAYNE9N8QWggf3V+F6/3VAGoU9MQhQTTq8MS7U3bHXScEj2SQ/XZWu1Uf+ewm0dHP2URSsMW6w7Tds/l6zcfwgf4ai9tW1NqEWPMTIpxKqPXWAujlVn3xXgze3lqT0SlMCm+cNc72MIIfxojN2a25KlzZ0efPwegRpRbGx7byol+Sk9t/yFIrsd0b+KI7mbRLGglTH4JxboFxDuCx9Olkh6yg0U3SAX9Wpzr8ZiTDhkQ1RHEixUiSIAs8x/1M1BVOTzNZmZHCR358SDB0pbx+8sR6Y428SXOSwjQKBhrLNeINz8veMPEN4h8Sf0JUkzCW1WESGh01cRhE0t5I2cpd22s5vW1b9letqtLL9ddKCtGCWrGl3+4VnX4QlYHWLfvbxl2/s4/bqu77Nrpp33BLv/MduNar+KWavrj8zXAwZ3/bX0vOzn0NHQ5IzuRzuZy9z+9kn0aCldThgS30wJkiNeyPRJMk+i8yNJgdzkYzSWofmcmCrHnkoIJuQCdKUPcEB2WB6iKtIgUHNAxS0OdJR81IjylQQR/6hCgatogk62Rw2G8yvrXESJoxNTVG0RRFnYZ/FMeyIkiczDIUl7ZitMwwcZpieYm7mi6kY5XRSiw2UhmJsWK5SMHbsjMWrapSiOM50wpr5n1OYK6UVljykKgpPEVmKJaWBU7meEGUDJVOW0lal41YYayYphhaUAVygpFlJjQ6NqarIUmR39MjhpnQdTMTKy6VK6RIwZesJEJcOmSERV4gb45PTodXSTYM0weowTzUPDNMgXgOZvAPSZGoZpDwJ1GTQk0aNUOoEdDUckhXvjaV4dr6na/RW6S9mbKJu86MuGXPiM4iKAdMs8Zt2ZxVG9MW2X7nWzCXY99CczlWgqnWRGeoOdVpyx4Q8eQirPgjV7G+//FHs0ixBHtItLN1Oy3ae+pee49YS+5JgxqlUOshnOweEP0atKmmrDuLM36pSvty8AeBzdM551tj0NMRWkY9A/7XI0J/om8NCc13JFAowpnK+KXXI3snvrX2HdT7Nb+z/IdwqyDVaG/o69CFtMYznCRBdfxNKBIon8x0kXIQpECBV3wuwwGoksz4oh7BA7pFDYFYDUMzBAIHcpP0DMMN8AFFcsgPAuUF8bKUQRA2uIHsYaipw6dGQE7S2Ug2LJuJQkGiQrPVUao4f9CkJElSQ+oqG46ZLM8xIGeXEQJSwtjCwanMychISaE1VY7MT1jkMUmgWEobH7PGl+IebebE2kLGOHR4pvEDgRcVTRNB1BLqnXKBKxQoUSouTo7FGC3ES4npmem4KksqeZWRRBA3iWbESY7m6Mjy0pQIwsrrVkk3eJBbnieni3PL16fPTlGx4rgRiYkE4SWMhw3PIWaCCBAmsZd4hvh9MkdUc0h2vCA2jk5vufggAzQ47d4tF21bMUYspmzprmMCQJii00n23+BaCZ3utznRKYKETIG8TIn2AEKHfhCv/pQzwKEuZxaujoH8fN2Vn/37PxnBwJwDYB6pO1H/Pbuvfqt4/ONeV6xioh2vO7kR1hmR7gkgYk4sztpRsRaL9gX6nWgfC7fU+mJxgOni/L97AcG0PSLWhkeygNTQfoHKxM1orC+eHR7ZhuK/yH25A2Ow02mCGLZ7e0AMnYF+QKehnDNVhL5k5mkkmrN++zGQxvYcINxjTz/3NVfwAL0ApSgkcUiggq6swLFAdgRAsLIahY0mEkIfw1E+M0KAuEWwIW2+LTIMcgYilwHs8hhSYiyrZhOakZ9MJ9MKvWyWM4YMqGCYwilKLU6tlsWQLKhUafPgjKlK5DGGEiLxcNaUlHgpZobGGRAgTpQVjqKvJGdKETVmhSIbq2OZ8cnDifKkIesSN72S/vwDWqJvkqfg77EqJ8gSS1P1xkbjcOP4TZM8W1TkhYPjkfxoKLwwl4+9IGlszIqousqFE0lkUwziPcqmN4heYpCYJqoCiIttpRwa4U0G4c2NaCtRBeGIig4L025YTjtIwC5hC2MLG/VLTl8KRrbdb3fDyNIWDHo7KDaiIO7QKkEl6EdD7IFjAfiGB0aMjAwHQFfJLKMEmSIdBew30mMzY6pMa4ZGM9mlUUOdnwHmQYUTYUpcOz0eGmMUmdLimXiIqozGqUhlIcMpqqqTr3ICSzWW0wVVHFmoUELx+ROyxvESSRyeMI6cXZ6lRSmWtSLULGgBSZSpG8QdLw18KwGPhlBWxIyEtLWUTQLbErccn2hZzi54Qp6EB6JzBDzLEDZmlEAiLCI7kLHzlhXAeommACl0ZH5A5Vn6hqDFMhMLM0UuoVcKPJXQxcrM0uwofDfoLRVmrhLdRA9R3YXV0cSwHgDsDhAIuwOtYId7yH70lRmQPAtZzY4Q2SFQIGs6FXQphTF2/NUliqcUcf7yRjG5eGHFiOultZlyQqEWLpIxUiGJdcqUQT7W//Z+4+Pz82+8fFQS+dLqqTMn8DhY0HyPoYguIklU/Qgf0GCQtp6ygzAKrVvVII9+UBCzh6AfftZu92fBSOwlLbDkGKSBO2J9iUYsUWVoavnUhKEUVibzo3m9cmSB8tZ52aRmrtd/cnLhR2/fKGqjl67fWjv87vdenaDR7zCI457rIINfJf+aqAYQl+mEH2PvSdnJQSeOJHEuZbfddWRgwbLolGFW9gFG9VrO11wg8v8Pb/2xizikaEfrzlcC9+x0/VbLWr3qdlOiTdedGeiert/i/833n0bdXjsJuJUBUGLu2ZG6Q9EsvL9GkVGAI+9j9WEMR5RY81B0oJ9G13rRNScSY2sRfERGWTsi1qKRGLxFGPz+ZfyWjFhLZZJw+StptpZGR7ek5bdq+NpXxNrAV9LuNXTjwG9dttDlL33YIL7HN1hfxT0zYu25mWkASLjzC4AEak3vOIM70Au8dQezTQGtlXqt6a+QlIeORGOp9MBg5rmZ5G/9IUvSF3cl/97bMOTKbaAgj+WcfWV4LQAExPcAJshtgAkBv9Nq5rb5IVBDQNGgF2MBMvZAiYMK8L+iZxDMueDxAdHzKiBQvQEEEEMegWonERss0j2AG0nSGF06qP9KFjlWFkkK44Q6VrZoVpQlTpKSpXwse3BppcAr8uLaksQILBnjKJ6nGjeSgHlJrjQeKQqSxOqZQkZnZk9oQoyKhBSW5S/xhsALzEFyFmPJVXl8ZlymOElmuJg1kk1LkibxUhYooqYwFF1lQoZKvdE4p6oML5Ir+eUpI8slJMYqlLNhxCJNgnBl+xdYtgfJJ4hqG0LXgZTj8W1VBzxItQZ6gafJKcdPb9mihSHXd9dh+gB8BH6r6hPQTT7QP9snOiYwP0G0TWSYY6AAsRRmc0NfVgJbTNI2UxccxYu0AI7FmsAgT0iW/2ov9oTa0SnQvVowrQDPU3HbiVsNt7twG8JtF25TqK3CG3fIGPQhqQrl7C6ggTl7V87uzNnA7lSQszahk2lXgqq2K9SVSv+GdPGd7eLvvIYlSoiBJPWCJHkGwHJ39yWR5Zb9jm93U5boISxD/mx4W3BAaACR/ch7jUQ9JvYlGCQxyKakkaQcJqnj23KhaDJNy+B/qbTFMGDQ80fTSBIUlWM4RSGrWAYq4dHtCWeACQKONu6ouiCQGkWF3QkmifzDEPEj4mNCIvqIagvA1g1PC9GCbEkAW09GJHbR/c0XR8bwOQx2RCdlpp1EjNeTz2clRTcmsWsDFoQ+l0+E8osXjqrK1OyUQsOvdWVJI495aOoKoRIRwg6CGAHJ8wSRhHjYFvjGzhSKBsCwBf2IdKOhyg6DcoGzDxaL6fCC4fCBd6/JzFzVfnWK4xn6QZWO86IQDpGX2RjNlMaLssYLrEJVKUQ+8femH35C3CFOEQKRdZ/R8bAAyu34Ab3uA7ovjgjY7CXg6zk0fS1wQMDvwOQJmYook6QyoZiRFZQQL+iqMKkrGV4PCQzHqSb6Lv7hDFX0XiIYop+oepBNIrFN8qE4yA2PS1Q9okPCF1FtW4iTwIgGyUHSjAzx5LsHG6IWW/B+fO/NmIb4TenhR1SWRvGHOJEHa0+iD+vHZj4IKhQUnW4gwCz+XCcBH9odRK6N2ItkjnVlDr5AAvwCvxW81R54hIAclCUdZg/5uFEQvo6SUDg0NzsX5ljQkPxsITxeskYpM1Mul+IyK+gj8XAlG6Yqt187Losbl16pmIdPPb8xKo6eeYPcpKi7jY9eMBMbL7w0nj95eF4uzCwYMBZFGP3rXoIIERWiqqKxYPBYdOGf3wrWsFW0FYQGu+BRdqUcBdBAh2fYBZzFYULwBK1+FA9SJJtHT6FRUdcFl3UaEQo3OhEZihSR78swMYahGDDgrKKAp0v+koyTiZeQzxur/uyTn9lxOs0JqsTJzEtYLuKE4vmUvgIs6p8R1S70+1hkvKOY1YD17oUfCVOUdPFJOv3WX7rWuF1EYZyQfM/urNe0UCcCHNRWod1hrbQc8Xq72Akg0YSNL525IRe2C540EHdxITsEwg78DAyIhZlaB4KGyBD2K7EBAdJ4cPPEWKVAJcbn45RKSQwXUqSxN9+pT2jh/MZshpKTc5dPSaZnjuKo+PpS0Th/60fvvlF+CdiByCcL2UxYiB+886OfbJbHpeOneB1jPOE55z1FHEAMGnG6qg+5XiMIDfzxXT7w3wHfa/t3+VgYmDIeGIXbch5DyhrfBa6IkkxlkFvs99tCzt4v2W052+cH58WFO0ALeJIvvA14kiGEgshHiQieSHQoMwiOcwSumAgBjdLy8aOroYwhZStjavxgMrM+N7J+9caYZFZWjq9U4qXpWGJycrxSNilyOU+VN48d0uB51Th9LpTPpsOKNr1yaH05rFEhEObl7718NssZijE6Ob92rGKVwwJtJi2dNRiGvDw1p8vZqQQVx/E+4eF9z0dMFsYkQfyPRHU3Go02qikQu+86RtRygxaitS0YbZ9+/18gwaBtA/iYUnd6+Ht2oF6TegJgtFo+r/8Q0x4DzJUBRuhWu/r9O7inR6yF0T10LYpeqnCyQ3zAQMH9OzzIvzCiUkAJ9oQf2aHXd55j06OhUGkbYFcbHNQIf3fskYcYBDFyAxN+kC5EU/zI8fN7B4vUftIveASa17W5s8ePjHKqxMdGT45Kidn1hGaaXOOUGju2GYslNtYWKY1OWmH20E9+8t5RYB7KA8rIx3hGenCSUwSO+i7LmSZQFqJy+eo1F/cBGD3XQb4eJ/5bwg0SofiQ3TroyJ6tqhd1dGCdq6Ts8l2nW9iyu0UnD0AA7ns1348sRH4Q2PsT7oC3X/j+h5gptMJ4c3Wv09EB3nmwDmhYU4IdMJLQ7hi4KhdU0HDd4FqDHcoXg9UNjM/x7gOYyfurLZF0DsUE5TR0towijZSKniBIbLDX9WDAVEeQtQZbBI40tktfkuYI7UnS2eGIyRrxpChpAiDRCqUwkiEIy7eWjp4eFanE9PzaaDxviuWNs2MKk6xMj6apxme/5EQYMpoN0y+Wi3FBVEKmcIUSFXCSxUjIyM6ePxZWR0Jha3EsGStMmCt1+2qJ1cT4zNzS+vHxa1ON+xQXmThz+5ICMmyBj/Yuc5LYQ+xDNqMPWTzLBxaviIEXe2okDCoRMIGYBUTHA0PdAgq9H716QIJS2GZkhgPbQfUOcO8pGTA3WPQ2n5vuSXqyTBCZkWGsuxZVpZOiAg9ZjCm8Jiey5ZnVsgn2w8hPza9Y5fm88fOQKKTzxUJWTnKRyfl58vaptOcDXjBkSqZ+2Pjpneen4/xmfTpz4sSR+SwtRczEmasvnpimxjbO8scTCS4+ubQU2TgUis8dw7Klgr6uej8g4mQLgWHL6W7Zsk2rGkYuWDSFjaUODy3AQ+vYPeVasKVEksT/o+/nsSSFQZK8oh2GsfDd88KhY/ru3Sr+s48rrmbrcN2oO6J0zxbqt7it+kdYgz1ijfZ4UfRn7t/9c9wjirV2UQB2qou13bqBAOD/qr+NL4XFWk/YBOmEt+xgodCHXuDmHZ3wGUhyS5zhob1Cu6jv7tnJP1ub3bvNL9Bg26Y0IddCsR4UqnAdbrD6GhkYBlvfTwKFUldefPPGWS1DWQtjCZpTJBpckGRMkcqjpckrl69MqoIieotCOBIOSRmeozd++en9o4XFxZUSuMLS1FXwzq+RkTPA7YAaEh4iBDK35L1C9ILEPUnMuvaetMdxbCDStgVuJg5H7AVLv1d0SnAYgMMWC+TvRtqlRemU8xT0l4B/3WwT1O7+wSFALyeQxnQQPRh4UjoZxIHUR3Er8OX3k9lhN2wKIDcErld2GIXiAyCbJKY4gichmmOrhzbmR6hIvqTmy/n01Ep2AuhbXBGMuansQSVRSVozI0Z+I6tOTiQns/qqsLgyQamJEd1Mm4LnSv708bWKEju6Vrl08Vw+Obe4PFKYyaiT4/nV9MFMNjS1sLqUnSoXw9aFKy9kTF4vxyc3Nu/bYV0qZsMTY0VZnlo+CPqpPWx4TnlXQT/3En/dZEZYdLMMKGkhZXe7GbMuRI1AW23JcvY1c0lDn/1bVyK7QSL1utPqvUfbUr3Gt0ooV2R+/lPXQ0KnNRG3ftQCotZ2d+twaqC2CjfssDUiyhpV4Qo62Y3krpVvF/2Svtvo3iF3N1uhE/p2Ojt8F07OEU5WRRbHjKW2LQ6NMidMM8iC/Jpsko4K3qiZpLJK0Ytk0aclp9ZPnBsdX8gqLPB1cGkoLqQBuFAMK/AcFVtcO7R5JC9oCj+njS5vAA+g118+tRKjbpcuXDq7VkqMHVw/nFl6+623DoqxsGYo1is//Olte8Q6cWJzOizKRiybkMfXThxdNSZOXV/ENj5N/IK46VkhOKIDOA84Oo6As5WuW6Ck7Na7johMvGgzaAoIMEhEymGELScI8sm0woN6WoQAPCjWtux24hEf4qMI+GNxntNHQ7KZCes654lpYVNTko2ybma1TAL9Dux7UYvgexnAlbFnYuvAgj3wK7qR4tgBa9vz6gTfmbYcE76/E/TDYXVkrHTkoXhyv+WSub8pqOBx/y3/jIpocoymOVlj1cRvO2vkJS1myrLMUbxrv2dJ2pP1qsCIiMBwdgi+AlDfx3QgfPGhdJiOOxBD9R6EL1nkBEGRQgzMaPnUuStzAjVz6FiYTWbTHEOzbFrVj5x94VCRugsGkvyU0ySW4ZIa+nkLm8urUwYNrE+hZVmilJCkhtnQ2PTczCSB5y4BXtUC9Q6hEClykbCl1A2zhWABPLotEgHIQJOTTXx/xSXrmojUJNFyz47XbzG/qH/dDZ0h9dlVd/qVe/ae+i3/f/LWH7m306LtA5wHbt9Wh5Oal/aBzjCoRdguiG1w2o7aW2xP/Y8xsO8Sa6Fd3SjUgFpH09majo4e3VHbjS8b+PKeftZOiLX+RBw+co9YS+zpB32ED3D1EWlgF1JC28hV4dt3aCmD7EIbOhJARQNtWpdOe4GRtIu7QruNeH9iT/J3hcLk37ix+++5s+mSmBLIVNiVKeR9I7SFeUbJUeyPk/tJcCbzKNGFSICZkJiVH7z19srC0SOacujYuqxIgpKkKXkhf6x8eFGhjbBBT5+4dO6QOvo++OhsvmSNjIRYljHjYY5jOZE8QocYmmdE8FBAQrV0zFQEkLtF4ueemHcM1RcEit4oiXkWNUwqAjNsRhaZtQsvnSirD95lZE6UWGo5zc+eu3oZ8FthyFhs7fDRjeUwmWQiLCurEtO4ZmycfuHM5iQIvytL4GB7Vn2TRIYoE98hqkXEk0YACUIpJ8hs2VYKOL/jQ9r4WMoeuuvsFbHtiqGoOnCoGAouEzEC6MQosmxD4HiLoQByvGP+qtrbifmkhbI3oor98T3+KhHjc7kv8NElkAKpU9lhNy5ONT0jkkEmDNSX/AJfwIaPrp06flBLrM3mVy9cG1EFMV6esSLxQ5nIWCE8eejMocn02Ey4tLm2mlXD5KSmmOm4xisSx5xU08l4SBIilZGVH1avFHgra2mcPmkoaqIUmzp95NDR56eTCYnK5C3h3iembBngWmqqO1YZgvAd8mWIbxBHiTeJ6tfRWD0D7D2K7NZhOECpuep+5DJ2LX89Ci5jF7N1I+fHhzl6C4bQHcp/jBnBePuWPS6iCglnGZB2Ged2b/S7PKDfzePBGDvH0A0GCCSoxHf8Nzqi6tefQY5mv+QMZmBEi/6az597DCGx0/UM4OJX56F3GTB7PJdzcn54p5GzD/tf7+CTKXW9aZo0EN7wjowZmCUPZhJoTnCmlox24NQtSsQ+SqZ5cPpi0ArjoJTiY3icbuuFO6BneDCDCgDozNy1u/dJ6dyRt89PmXOXjh7cyAqCGjZXjp2fTCbySyfOnCtOW5wCzrs1W1neLIrplatrpxu/eOvc1PTVX1z4mHztthYCa1FWw8cbnzTeb/z48vn7b2yQt8PjlbwkVMZK3IJhjhzZXJ5MUBOnSINU79cPb9g/WT/41rWl+OjURIHPXzqzOJIeuXjt2rGJ0qgmqCKrSTFZyx+azU6dvDoxV7+6svjy33zSuH/i8p3j2WsnxEQilCzOXVovls7/7H68UFLl5c0VRU8UV58/+3xTBh6+5/lfGIrYT8xQctOTw0n+vlAaJfn7QGnilhNGVvQrKZRtxVnWb/161MVWAmcx9rfds/P1W/tf+PR5TL0psLJ1pxC8Z0/WbwVW/srjAnQcADpRdzrBlw7C3bV7/xPGWkKskQQNMAoEoUaho0fXah58gaBZN+nBAOTSqL21377n4Du8+FT+w7/6Pfxh4C+qwU6A4W08vrX/lXsL+NJ+sbZ3fx4+bn+etQtwUpiE+6C3gHof3Vfbh07RDSV0Q+0Z3E7h9lncTuP2OdzOoLYKv38H04cPQC/wy9AL3IHwvZSzn8vZz+bs6Zw9lbOfyVXhd+54E/xY7B50Evl9+yefeQ5lOrxMUO3sT+wtTD07PVNK/n1/yJL2m2+K/3+/q2kbwkDFq0MHKig9HeoDdVNMUDcOWOrTORwn9YCT4cZ5gro3CHoB2BUEIgJcwcQ6RHUEfEkP6BuiC4xP6kDKAx1Jsp0EJGQywPskI25SpqCEFJmX4+l0Oi4pUwuJoOwX9BbKL6iqJnKVqcLZjJmMxY345vokSzPwtxKZnSqDx5zI6JSqomwmxWVCcy/8mEyTV0gRHNFYQkgePXP21EaY0kMs7fGFWG5XP8dxiqYxD96byF+6dCohh+KVgjoVTiSpzGHZtIzKpSsXK5Qgmub8onEI64JFKLTuvU1MEktkkKiOIe721GC1HcHhAsBhN6pb2EtvVUNISyawM/Qf4IDzM5jQ2VOW/YyI/Z0K+EGjll0RUTrQUYBsKqIzDIcRAMCDTd5vf/Kyy/unkvZTojPKgJc6JToTzL1b9eonf4ZldkqsHZgaBTkr4/Yx3D6L2iq0O4jEgZxdzqFCgtcPlB8bnXq2KRk3JuD02S+o/VMAqEgCK36nNAbz/DXp9VD7nqS+gBBY8dtWzh6WcNZ87xhQ4sgefRr5awvd8LavbUedgBs2QyVICAT6izAg3RMFLyA7lIlGUAzadekQdx7yJMHJU4JF7xCGVMqiwEPlVUWgk+vHTuTlEcuk2vz58fGiOP3mkl4pxMaPnD+9pmS4qY0Th2bavKI6Pnn96rGQJEt8ggb7y1+VdX3+4OJkUpfTl84ue7OcLLIMrZgGFx7Ph1nZ1Nr4cHhgYW5qVMtajJqIxc6/+tr5eTWyeuj45sYeUdDk3WJ2+ezsyPraejaWAXflhp744fh3K9rs8qHVeV0VY2MrOC/98BPPDe+PiSzxfRclnS7fVrUrjaIPXb0tTWfPD1Li96E+P4+yH8OY8ZOWo4JBDFq2KmK2HwMhGHGFoPiv/++/cIWABHD01Gkn2HZPsDvqbtrXA0D0KAIGpzvwAvoQXrwOKt+hBJvTXUMnjybbRO6bj09b2Jb6u5qpD5hDUmpOmavBdEfTKjajiTClMGnIq7O07NTG+VmrklTCiXDEKK3PjSZVPjZRmbp2ZlmhQ7Qa5+eOvnAmr4GbUV7Mh8iV0k/vk9S7p8PFyWQkETn2xvs/qSbyG3PZ1UuvliiKM0rnz2xOtfu48fXj2BdJPGzQZe9HxDTxvxFVA+kWVrkBMD1ZCw9sbcrAcernUvYTd51y61a1WDpgWVaNKz/B9t/wuRzDl2pWDVV93KMcZVnEZahq21Y1riJyF+8BcjfTVME9nz/ujv4TMPpjMPoHUFHQvjpt7xNrxX0HAqgGEVrq9SfG9sF3NofZGdvXHOIy55du8MN7C6NIgeL+apuQwRxxChhOVYmPusVnDvGIIQ4hIM2iQgUEoR0MRzJuhLxJEmnMEX0yLumQtvMhbmEZui2hxYH+xWSa0UKj0Wdee/X5aI924e33D1MsJanLF+2Ly4XFI0fXI5xhhiiNonTkg/MqNcnohk5TgJ8aSHnEMKyJfCgSYUmSUhJT+4YnWfZK4xeNzz7aoFQpduLFN9750Up2csSQGFALlS5MxIrvNA6/w4c0iRdg4gVRojhcu0Konle9PyKeIr5NVPduz9+N7MDedmAQWVQsMZGyi3edKJDtqGgHwAG/QbiQSaRuBNwjznKehomKBsAEde5FQ5jdC+IbTfaVcKGnH+FbO1zryX2BQ808PdkBo9k7DF2odtOvDFrDRXrYUlx3FkYv42IShSJHZbBCgqqLTOHStWsVQX5wB3gHQ5FXORgxcWz9xPpYS6uyO7V5/MiKKRuhys03bpY1Qwb1o1WVY1nvChfSRIpJ50d4Y7wYl0Jc4/1JZf3Yhvw+z8uUEh4dLRUKWuOEhw+Mzk+VGFFVhfiJEysiK790NZNZXblCZl+kVZxEJYnCw4Zn1nuFGEQRgwQaPx7F0pnBZrmT4xNQvMj2iXYfDJ0dGMR1Tj6U00zAOPEJOPDlcA1MkbSGYVDcZwe77dlPZl3+GxS8bjI66S2o4Zhw+pXTpxYEXntwQrt4+/S4pNAUTdPcwTNXTs9KsmIqIs9Q9JtrMrhhb0Ymy1k5xCtC4/aD29ObEzEwwwIHg8GXpuen8lzjjhZa/u7ffPDB2ygH91Cjr3izxDPIq0DuQ/UpBJg6u4X9sWp5m2SS9lTKpu46nYCOnSLKPdlly8nD0xYs59mmip759Q9dqlkW7RJoaAEFc4v1W99f//hPsYksg4kslwAfod2ZIShgdSWrrtpibX2sE7SVaw+PPYVEKu+v7u+pYG3Vn8IFI0B7Xqf6849XxrBXMQw6ObzTp/MggzYIw9sNurqXtFCEBLMeuUMGSuQDclEkh90S0AQV6Fw++/LNRcHU5fnNdWns1EqFT1QWklMvnt+MNX6Ynz+0vqApgspxlKKpdDwM5EaYVHWeYaj8ifOXZxKr8+X3pY7SzHc++fjtowyvKZwRicsL9dt/c3ikqDPs4rnqghozQzLLKgotigI184tjcsc3v/mPlzLq3PrRw8umdWS5rGQmXTn7zGN6p4inyFNNdjMwWO1CouZxX7Gegrxx4MmVLVR7+RTwmKdSVe4phJzc4y24IDMLwrcHJqkfayyepK/fC7k42u8G1TPgEKh1sHe1oJoBG2aItW6jH9C0B7dh3PbiNoLbKG5juO3DbRy1NPqILPqIW/XiZ3+I6fkwOq2N4DaH2zxu96K2Cl+zgxX15Oxwzu7N2ZGcHQUfPmf3AUrnqvCr0OW9ORtlinL2CNAe4N5yX2ZvUDW6e8K9kWgs3p8dHsnlfzfjlr586+++EQtdFkxEtTWwCwta1xhO5rl1EJhSezClHsq41WrZbZ6tuxV9PlzR53JroE8ulypIDKOoCg0MWZBmLx8CWOcVkTYULSSBFvOCJHI0I8M9YR7OgQqzlLJx/JCSMGQ6HOJDXrDgqJ+eevfHb4+GSzP7cl/xMtbE+OxIWFZjSdk4+dKNF08aExcnDVFXGK0UUeY3jm3MKWJxrCyacysbI6G0ILixxFWijSS8nxAhArROIprlAJ0gR6DXBIq2etu2kOAo8KKkcDmAV4Fx6EAKhxY2uJxEGdTBP2cw9Uh6ODJJriq6yXOCwKCi53YvG+hlWAAp8Ce8d0HYafX8O7/67KO3K/MxH9VKbb75CUmT9N0rqC7l4QnqpvcmESGWiKqJ4IcF4q5iIY9izv5F3YYCv0cDQddEpw0Ou9q2cDxI8aCYrOmWk/tzdhvMotiOZ1FlYUoJT1fTqGcHdaDDWdfGcGTUrcINaqS/Wb2ryTCEs4fGSksS/PZEgqJYUVZEa0opHZqbOLtWJDVGzp9cr4yWJ56a++pLZJksv8zpITnU+OmDlxt/M3XmYL5y5CI8V4ZQ6YR3lRgl/ylR7ccliYOu146Wsdj+wRu9u/s9bf1296DTi1IPj6fs1F07baHqLEeLWlY1FUPkKIViXJWm+q5++q6rvlFQX7buDHju2fsBYj/6aNHF3rRoW3UvMt699Vv1b336Y4y8rFhrYaNIh1HrsFHW7hVrkV44sS2xNmChokIrzSIf29o/gJT4H3x6EytxBp3Wsrgdxu0IbnO4zeN2L24LuN2H2yJqq/CdO3gw9CFVLuTsfVihXW3OIYW2szk7A2rtZ1sy+b2R6ICFFLqwr7j/dyg03NSL7vp/uam5pAbl4/XtJTVgGgLANZBPLHjBPHhoICQ93WidDdOTjkZ6kCNMp0ik3fAvQ0cU0FV+kp9cO7aZDIhK+/yZlUomLHLJpVdI4pYee5ABvyTh9VIY0CleFEXgJxyDVpd4LcWQNI17MMmfeu2Ns1188IW3z68srlTAcrAsredHNrJhiiSFsalxUT59/QevlWYZMxZjwXdWcG0YQdAFL03EiCMu13Z8YJbxEqhdigGC4+xCEb0+bAcY4GuMaPuQCqNCPzPl+MStqs/E7FoFAULUmjFBTzwG0gsfkF5HRyqzy++0A1GzFcmR/PDq8TtMZFtbgJwEsLPhHUaFYEFcMNdjDkWopCcf081IhAqnM6K6dPT5Y4uqyqsiJfBH3vvZe0csmmM5QIB3TUnLfn6bFSWWS4wUs0kOBksOScrm8aXJBrn26YW5SLMW7hNvngkRY+QcUe1B+vLYoKsq2iBe44WTynh9Gy6OIe0nU3bl7o39bglZ3i3CGnf1pLD14QKObymgJnLd6/Sq4C30gUaM3/vIDXH1JFHVgtMN9q+rfqvwv36YxpoiizVg8kgBnrv3n+GeLrGmd6EMwm7cGqj1Il8vHOyB+/Yl/24I39cHCtXXiywkbmOorcJn7dAA6EMaEEVWrgofusP+4ZQDUeKDXXIHSvyBqer7stiLwa6esNyhoKu9v3n5kQ3LV0DmR3P2fj+yk46nBwXAE/td/GsaLWU3CcbMKnrc1XxKUNGooM8TAbUwEaJ7o0myR9aoDvBoIoCTVIEKKenJkiWLoVJ4cqwgsrwSGV0eoxOSJNCSEs6mz26yejpbKpVCFNXZIeYnZsaLghqJGRGD1ZJZSaLokPf9sJSszJjayKmxa+c3VH5k8zY58nNOVEOvNs43nm+ceyXrzdAHr7xV/+6SNxc6dvmVS0dDiey5ht14pVE9Lxmgb1XyMLlJHsEyAySV5hgd/JmDRPVxXMqCBIYcxPzoSXBAET8SHQGkImE5IfDmd3NbNyIioYGsICem/CSKqRWeQs6f4H+93deRzkiIcoYkB5WOEk7H4484Oxo7EhsPpABk1K3o7wAOsB09SVLDCEIi8F+UAabprjWCMUT0VC2MpAVw7rw0yUmKpBhGTOaAyiObKUliPizrEsUqC4dPbiZHaQ7l6xhUzhOPCb4W+s6SkchK9983F55eDAT+iCR+dkXUM2Pzs0L4wq13v3cprCUSCTUW4bSYoR258OKF/CwDn0FnBg8c+KMP3t80LEGISpIcIChCf9ig/r33G4QKnsyzRFXGpL9ly13909+yvXpjm+73wvD1WE5bc9kGSoHaJJA1vyN7c8jc4oLNfn2bMGnkduQxuO3YwcBsBy7cmFOkx/QhMNHVy9+cmNq16x/O6S0021befHF1fLmgrXHh8WJlc8bykm3+eE+2tfXxpdBIwiCvkwvkzcUn2N2Xl48PDo4/9U9+9YPnhYXnL1Ss9fn8yduf/qNd2teeXh7sp7jl6deqths7t8Bv+4BZJVLEE8R/6KJLlUVVdhJ64JJnq7anR0Jhi7GU3XfXseCxLdE2EJr2orUCKcdoRV3OXhSgACl6El4t0GWnh4UBMPxVPfs4EqG9ksNLSGr29KBVkH1WFslSye/sfTznun1uSS0VLLpjhOpDvEHs7UUpT0QcxjGEIIO9FHBf3NwHSlJZlJjMpCUJXHqh8MKT/X1dXY8fmuKpjZfeuLZCI48vznm9EloXdJvyeJXZN66fNSvLa6Y8f3BWYCRvGVUhz82WJVVnwxmO8fiyyxMHXzu/MZWmH1giHyIL5LOvkJX/AvTxL0E2o5WRyOLRC/Pp0YSkmGk1f5Zw8+YNz12GIvYR3yH+d6IaQ2M5jATocc8WDgEBtXG+gUzTISxDRRjMooiA2dkNlmm36Hyttd9esByNB45pOX/QXE4o/WrOZTYLAMyL4D4qrfcQdj9CZHtRrP3+4sJvgSr04fCaIncs/P7idnhN7nCPMSgWkcRSOXvc/7rPPzz5zDfQrOyWqnusqeYiROSdPx6DCe1NQMc3/DV9D2HtrKWgfM2JwxJN+Trk3UDzO+R+ElFgtHAVO5M0iDmNxHwfmenxDAdkvHYwsw/GNgnXQegFGkWMOvK8nqksFlkdXHPTSiT1ykolxjKkR40p1Akqy4PLEDJDLCXRodLkbHr2xEIhLCxzSry0WE4cnMhQ1eVTLCVrIiNomek83/rM3scWCpEQEBHqmnHlB3eur1OCLCGAnj33vW8+OR4KrXzvUoKlqPcpiRqh2GQ6ztLgZYwVYqW1s5cupuOHjx1dLISLs2mRI09ZjdsUnZ9bWTDC8c1jRxbzaujgyXPnimwyqyI5mAIMJZg5okTMI4ZS2o4moemf8m1VCczgfy9ll+46+2GqD1hOC8y/bgHHxNKgAEFRxvEC4zgQlAXo2l+CefLm7Ba/PQuzJb3eHjKH9j7mRryrgVQzYIfuOoCmxsJLNbvIZqoDERQ3zA2QrAQRs8NJXMzsvFF/T+BRyBvBD44TTFFqSKO4mDl3dHxgr25cPE337bl487UXwsaxC9fOHVJlSdA4WeFogOqklWSUg8fOHDuozC+zS2eunVtr93bsPtjujw88fvZomGY5hpkDR46RbTZfkNs8+vQATScHR45sbixFhOL4TCXLoqw7y4ZUiaKUkAITkR8tJOgHVz0rXHpsbnEh2sZ3dhgS6ePSlWR4aXXVrbUjYnSv912iQB4g8HJtu2/QjWWLTcW70d6C7Bpp78OKF+RwhXoGLdsFM2hYKK+LVO3XL9X/xHUWcmjlrqPJmAL5F95acalRH2hgtO6kwLcYqN+6V6i7WTlNrO3SutDSDtTekn701r/ZJj6xPuRJpMRaOoWch1//S/wNrfAFteFcFvkMqK3C23dQnlCuCt3oaDhXhTd+iShFcYqtDS3ywEuNENX/DT9AcC/2/a6rrt5nUDm+j09gsWmPg3oTwS/y/1mX+kfdqDqznSIxI4juZpKMOnr4wovXRqWYLk9kJ5Mbh9enrclTr1x/5dRki7T7VPUNuyhpLL1w5uXLJ/TJU9997bunJj3jk1deOL6QoRhVzVsjmdlDR4+mK7OWKgrhQqatvUPtm54uw2frcjiWLkxYuqEIWqSy3qynbHgveW/AHL/YjC/iWl1x0DE8AJ0WXmLnDHlwuL0FXeocdNfeSY+2Q0DG3K2n16Gp5RMtLAhAbnAQy8Weu04clDH6SBhahut//mgZbocIM+Z4hHteOHS6hHu36n/666984XD21p2kDwuF96/ro66wiElndycIkOjI8IJrMjtQ3RtuJdwGUItkQc8h8TFQe6v+n//a5c2PHNEBsZYaSMINadR60Ruy+Fa2Uf8v3YASfv8IakF0dsoSSBB8yA4Jgs/YXrTW6ukAvowWon2x3hcLkOKhDbwZQ0eXvrs3kvydgvRll3Io/yg1kx3udU3CXhLkxcqighwfNtwaiZgzJtLNMhLVlCmVYgUVqK4s8qI8ByRvTmaS3PSJKxeOGR6uPQmunxwLybqqyKoYLp06ebIsx+m6HKcmWdPUVF2lOF7gUAWZZUo8ywwMfv2bVxo/bNw+FzJ4auytn334wY9n0ercZqxa8RymPycOEP+VK0t2erCaJZp4EUEC0okokJds7qGBy+3xCoPiXadVwCsMcMxh6l4NS0gaJGAAfKkIyrz01N0K+ggKD6K2Csc7JqQ3R9QGesK9bql8Gh1GdmhmaxHGMQ9a6YUJsIvYOSlSOFDb4cehW0p6RJF8Mq79wGiOHPXm0n0Y3yLFyhon8rKoxAqRiY2pTEyXOgMtPkWhGU2URVpQFa+XnpDLB8/MV2bTOHbOMDR9Bi+OFvj718NjxRhz6Rck/2kdiJe/Mi093/j0zOz166/OiGZIJkkPMV69upY/eKQgH/vuGy8fJ7Zrn2nae5sIEl0ETgM0lwepKbvlrtMOJLHz0XJX5GO1kO6+HiQDv5yMqEkZeBh5h8zQsiil6cZtsVDICg2Nop9nNCGk3re8lMDp8mcndTaS5mmNatbzP/wF84b3I+IA+d8QVQ1hgHfQ9Ypjzfnbnri/Yj/85y7OHxDt/XWHVe7ZrfVbfyV9+G08n0XRLtQdTkMbotzat//v1t2bBdEO1J2M9549WL9VjH/0Q1fPY25JSI9wzzbrt976Pz787IvIUmug3+F4tsahI5sTa60cD3pb+PDDb+CbBLHWLgRQTSxu/biVUHurOPTRr/A9CbHWl4hBfz9qb71178NbuL8o1vYVC/CxB8Ra6cB+HFVq3aHo0IcrOYoFXLotBH6zstbGJRuxHd19AAoqHzB7+gYzbAvXKqBq2/4EiiRtJw5/VyC5E70l9v/nPY9qwoHJ67QUBJwAyMBCTQdBHkAsSBktwYmASAieJDmc9Jq0quu8qBjJicPTbLxQGS0qDMPrYcbXIanWSGU2T2q0ohtC4wNe1syYcsgee0jwyexIQqGT5WwmP0Vf4bSQxvDh2YufNi41mM3X7v7k7bFQNqF7dscuv/PTn8zTJ0U5ZHx+WauU01xk5G3ytY/u35hby/CMRBdfu/Pez267+d7PPMe8V4ksIbsybgcHUa4c5cQJXHEyjOsCcaAIoyDKX/W0kC71wju6eKKC15cwVpZnhIcEMJ4wLZEElx2bmihKcpJqPE8mgbHyiszFKCVbHo/JmXx+JCmeLJy5eHGM0iiVNcMU9eADcf7YudOHdM5g6QflB2/SGsuFZJ6hY2z25OnjaXF0dnl+Utm2o56bzAhhEf/KjSlXA+jH0/DjB1N2+K6zu3ULESOkJfv4D5tpKx6vLNOke7ZSRxsmtfFoOyABt+2oRQwoqOFFr7jtRG0VbtshW0LObs9V4Qo6UdGCVqLEKXwbyEtQ7dR2ytPv7HbNTMDc3gxoCMesg4OIuSL4EBh3mRZKIGIuCwMcUcNy5sjxk0WNjeVL+ThHcXqEzlaShhkuzJXBhcgkMgGBzJ87sxmm6A9ZVSxeu3o+KWxc/l71qkVnQ2/+6srizMqrjU/uUJmxs+cez+QkqXTppdfmqe28vzfh3SRGiMcIbEOq1nbIIEg1twhBxsTuGHRYtNYll0IriAhHt1D4fU+yuR7SiwOLw5mihwgMobXZ4BExeAVP1qJ1cjBIDubJwW4LHq2ZVYkyfHNZWoLLbPyQTP505e762Fi45x8cFJjLH5DC375Ii/dXxzNHMiQ1++qrSzLDSuKpxt3Gjxs/P0opdCS8Qomj5xvkaVLTeIEiSZorCrgYe/bzk4CwbEgI8apAicDweari7m3wMO25wn4AtnMMr5Vt8W7ZXgvbxv13HR3YtC46BbTZUSs2k44OGGQzObvgd1QDnrXXrcxpCaLF7EzT9UerwBBR2OvqPLiBYNI0CrBgNwUPj2IjChP1gn0Y8nuGMhGL4k1Dmd88ubmgMIaUnT55+eyqGIJfrkfC4MwzNEMBq4hzhcsXjhqakXhwW9AU4QrFHhMEE9S/GVui9JgKrAFUKZxOCDcal+HvpRvxzePHDhp6hqJCZpjLltCSJ01nKYK5w3JSc83wwwY9yWoEEMtAthkrJJGK45XSJGggK3L8COO5QRmGYnAPCN9t5C+FxU9XYTRNmVYZlOMhHlqe91tWwFd8m6h2I9HppbfcfRoyKYeht2zWclpREuRAyh646wTat6qBAbxeCO0bUW4SkV333aBup7vSb0/wnp2q2woopYKWgaqoRU5IMrUH9BI6d+ilmqtCtxsoCKrN3YjQqgo463x06pKTAFo5Hul33YZML5xIBN6tiPE7Hj+aTT+IsAXw5xIWBkbOo+D1vTAsw70g4OQ+UuSoQJLscRf9RPoBKK3pxYVxUV8+ciwdkgxZFAVJURWmvHL80IygZIQQeQJVgRgKHTZDo8+fOl1WxIioMHILoWgiS+P1A6wszzR+1ag2zjZONV5o/OBXo5KhqSJnStqKRim6oJISZVAmFSYliZNkiWIiaC5HvJMewneEMNB+HTpyF324dh/XDjuy7u6f1p1CdU+E45NRcYe2vTQWJ1B2k01ch+cZIuGJPDhYNUI1qJgCskaOxQRG1GSWanzAhbhfUDIdFr3r4DiTP2FVkmycYlWZ1RSRIhelxmGaF9HvAsSmb5KrRCdxjcArEW0uhfZSQQuW8GKCj79/1sVnD14dEGi5BzDtOhpodYAXtwxq7YBY8wfwHm6orcINOyTAi2v44Yq7TRtRavGhEkzkAOwA5d/R2TTiCLbCw2jrErS7lIf24Xzh/JV3PyG5MxQnmpIxe+mjxmvvC7ypS5O0Hs/mizoV0VU9pFvjI5yiY/5G3yLue/+WaCPizf1jWloIAbntAs52siIh0wCpaH8c4ku7x+gUYKXHVELxqSSbljNWxHtF0GLJpdkSr2SLRTfWSREadYt+jugj9hP/lnBX4gUHqz5UEjmCQrslHB2It23ZcXcDQLl1yw5YtXZZA08xA+CWSdnZQacdjtos50BT+b77yd+5jmAAtM9fd3Yx92y9bvvFmuQPuEvuQvoutA4DtVXo3EHSoM/1+ImbMLLgtuuPVtH6pS9OXacd+enhERyXc1p253KO3A7jgArjRsJ+CX7n7oRb9IG8eBxoBsf9i/pFxDhIlJruQUFnBS2Q9AzheA9NxUYX1zfzAbFgdHKKpnAJRuIEUVFWru7NRSkyllEWE6XpyYosgZjzfsEfmZmbGPks8eKbP3hx1RPbnQunTr9x/Y3T4M8xmQuXTsff/eXgADW6lh+TSkfPnIzFx8qjEYnXjr5y/QrMxATBeEYZMIAwF1NENYjmIA9Gsx0z9RIuqfELW3YCRZqT4JdTIto/CAYVB9r1ti00/M4QDxAUTOcxHgXzOJYJMpGVMAFw4xgCSXU0w2DNAk8f2iFpKDKUCeJwhhtHftrDez2Uko6A18RVjq5nwj1ie348JnLh8dPvvJDOmwK7yM0dPXdkhhXNTHj81PqMRi5Wyav/7vmLR/4JQ8va+FvvNz69sLBZaWHI0tKRkdj8+uGTZ8aAmNDUsT+O/XdMfHTp5ItLodJIZOro2TyBc+EE9RP6e0Se+HOXP6CMN17v7wRRpHjvdvWlAVLZZSHTiovX1349/+WSy64guJ7ajpLLLrG2q0tDMSnU/kbhJfTt0P9dIHwk5UFBo23hu4FPd/CuIAJ7on2Pmy5zs8XN6ksyReI9BukOBuV1gha66rIUXDmQYXgtXskMPE7TVlahYpkQ2F6OMvNWGNgFRcfGCuMLeUM3wMFnR9YvLU2t5VXy9tirr1w+0tM9c/RErLKQyFMTRy6cO2Joud3F9UkhNjozPxdhBFVUZq4eG1954Zqr4360z4WPwtmbf+HqeHUPGtY8uPYcGtYJxMKmsaZnQa6yohNF21O0osXd9m4kbo/DUD+esvlBZzcSs8csCxUNCOhSF9yG4jkAAHLKeQ5BRBYUj9uTH0eh2C6/HQZBzIM1tQdy9oS/SlmxZoEFSnC4Uoi5KRVF1SLB7ahIc4eVpvseGXbTHBaqpnS5LOmGyCl/K59fm+rPJIdolFynzFiE8ZCo+s/gVZqRi9PrZd0EU8J8lWzzJxITpbQpobI/LUR7cwNDk2ny6RZ29dt/8MNzusibKaN38d23ipJE0/TLL04983eNeCP9gWIJAtlIHl2fEEIx9eC/7JBHR8a0yvrzx1c0OdEudOmJ0YGhV97BY/7wl2jdKF0ATjiFKlVQCtqJojU4I6jiKppsAUv6aOSfTdmFu47J43i3KaK1844kbjnTKBhbcLniE/7X29TW6EgZ1/xORGGEGalQxtDmQWu9vpA+BWmzB1AO5xQRVaTdPQ5pPJBI0Xu/WClDSbyQKGbyEyNDT3m95sxYmssvn9icEzieoTyk15cpljeXp8sZ8L/yi8eOH03OL0QoioslTFLRDx+aCUViojlRjpN3BZ4PHz51ahXENjuRFAuV8VKalzPJCBdJCm27u/qy5aVDB0vA+JYPbcxm505fKqHNQD5Mjk6Ykiqy5cWDeK+Ph/ep674eYpb4P5t52gEUdWK3oxZ2KIVKFvzIPH0Vx0/6ABVHrGpLHyKBLag8uE90JmA8J1J222BtrA9FNcvcljPXNE8HPnvWhYoxgIrxulPYdc/O1VEMMZ8roBIV1NrjYu3J8TEACujcAQ17c1XoxhsFFsZy+b1Pjj8yT4Udp9g8TaBVn8/knDJagRF9HEHyAEoR9+UcMwRd6u5He1Y18747UJlB6aJm9sHjc/eEQFDdzCttlxDjvU+bocN4JJPhaQqQS0lGQtF2MT6a1iQVeH262y8IrUFdFtlYNhFW4ivpeHlmdiLEKJKX8lCMqqkqzQssxRqmwYOF/IkcDhuiMdcT3Tv6Bx+9mY16rfG5MHjhx7r9ovHy3V+ucLKisHIkP5FWRJE/9YPL+7tCpilYaVMxX3rvSmKBFSRRRBik37/s2Ud/k9gL+vAfEVUG7U5lpG700Liu2+hBE2eEYOKGU06pxdUJQKMCt2UXRKcPLUEXt6p9AXRfXwpYPtKNPtCNG2yoe/gJBDQBv8P70QAP96CNWvpyOJUqoioVRqoJewaebG79SQ9bKKbi3U43uyXxJHJZpO2Ez1BmiKGaJWvkMKAOKj32DGciPsGr0+W1c1dnaM/UUxQHD8gzHt4/tnH+q2rngScYVWAV+51ltHy2vW328qmhoLwrGLMW5W6SNHoj83OzEdkcWZsfB3OQXPjZ3VtrngPUynfv/KheCUee/erJj398JuANU7wscy+T9H/9+0tPP1OtXTsbkO433rnm97UFV0aLZLz/6vfemlEiLD9z7MKF067/NfrwQ8857/tEdHtn56qG02yku6qBtGN4TwmGQ1sOogogzOeCAkr82DLe26cd7+0DUI6HXCPxBouE04UMXcsuH4ZttLeuTga3q6PAyQug6I3HJU0+MzKqhw1aUyKZyupT+ScVdXSGkhktGVZ3dSYTo8cPLU0aqjbpPSGxtMB+fiV86tKlo92d1Gzl/nusrjCC5xBnWDc/ePciK2H7FXv4EfGG9wOCI8LEaHPXG1TqUxVxCLUXbRqBuCdajKGKTis8RGvKLVBE68AjqJZJhwfwiLhW81GtEgLCbUe1Q+ZIMaggizOcodD8xww5JvPhiKZRIq0zIRNt7KsrqkFzXtpbV8WMqUhc7MF7549TlKQfafxt473GB4dNRTFPkcZ/+u2VPvjtjRcfTBB/w6yAF7WXDBHVDIp/5MAOdCIFiDfXWRZwLZ/fcoY5lHnDZrXKt7UPDg46PTBbZth6tKtA8d//6qQLXW0AXa3AcsIeYDmR+q164vMp94o/aZtJRAsN8HnBnrTDS6tY41vRUuj6wOcBHCoFLi7627eLeE20Uq6EN1ltRfsM9kbCAHzQ7mBIcNeOM3gzzrrxrfBTRb/RbT4K2m8Tplaxu9nlbraWQm4ico2H/aiAz+n0oSQbhaSKBKHyYOOOKi0xEuIAAtPkAq7xIvH2qTBbME+NF/V0qZRXItkY2r9Fk0Fh2ZCAkmw0qyqcbCYLkfDRzTnyqqSEWJnNynpjJsKEC6UElZxYnJ/ULpMJMvanudzXl2SWlWdefPrPUCjoJXVu7dBCITO+6GtwqszFuKyEeenDqqfIdBNF4uuEW8Qw0NLc7BaLYwiL4353X09QIZYDlsSLdh5vTCDijQnyYNbRhhp5Eu8GYPOAUHjj9BCKIghyHqtYMNBMUDfLB1AZugtA7g4vqGAdjLtODyIbgKxEr0BFMvmeoJfuVBH6izzeXWv15dMrCT1OWUfPvbRIlVdOHFvTKVZWWJp68AMqFIknmEQ3yS6M68bAyO/feXte8o8OUasf3LkcksO0RK/cqV+vAC+V04mEIbOJdIR6/8iFCu3G+YgI8XPmDrGLSBMkMsrq3VpK9Qv9TquINbEFtK8L1cD4USVhp7tHmA9roDu5GhkIgfOVpIaadVIcGUlImiTITExnqVAiLAtemuRljbnBC5zYOHr/F40jUpESKCXEL5w9fFLTrpITZPxDnMMiGHqDfhd4wwZRnULTYsCM3NjXglzkqgdxCBG7UkAaZu46LfxWdaYFGZQZxBhmRLzN2RSarGdAD1tEFLd2+tswa3BG0IplA1fr7JvySze5YGd0sPW5ZtFHdjBP4pJvWgEKRruvzQlEf9Ghu2Q8CtKNWCvjEcBD8FFuaRPl8SW9hXCIDoGLyTBcKGLqkaQRTmoCL4jWGKCRJmTRPpAk7TXjohFSwU9gWBNQqdsamgTjrfFW965djM+cKS8zLMvxEn0lJlCFN3/+0fq1d08UZWpkbvXglHjxjY00x47Mv/SUlQoGW/mRodLxgqGYVkYmddJi//hPGj9G8T8y8k+/zeiN842qOlJ/71c/veHmCQnCc5G+TmTQHj4UAjFhEMfoSHsoZWt3nQ7Aq2yTZU3e+1duLCaDyowdJnTPbqnf2nfhl/8x6naYFhZGWbD5Oowy3s65/s1PtzAAMWLNx7TgPfdbUNVk7ZcPcH+LWGttQfvv94u1eH8fgrPo53/2xealFt51v+VLu+5XoRvhFbxxB3rBu130arHwNvt98f7BzG/sHPn3XcJg1qE92uomgwJ7lBTMoiQkHChyENQxmknSmL0BZfChc44sZERGlBRDjqcnzp4am8vINM2oeohnQbpZKt7X0lLqmxgtJHSaicTjnGLSa2lj9rXGBz86QxI/ejHCX/ppo/HhrZiocoyknLl55+YZZZyjQuGLt26/eSUuaDwjkwKlY7sJjh6IyyqhEyXimwQOoFZbEBkYbnFjp4hgtWOC1QUC35VCR0mQ9cQA2BsJJhJtf9vVrN8r+G06ZycBwFtAkSW/096ByVYn4BYpRTBuSSjN0Nzh+kvlfEPDCt7dCPkiQFaTnp5mSQ2gGFDRkBpLyImxfFwQfbSHSUydmE2mFeqb4MNxLJ8eTRsSQ3OyoUliUNodkSmS3HjtxluHlIgmjkzNG5WvpQfi8YXqxWW+OL+gv7mwIIfNiFpCeGfEtHIlH2Z4efHM9PDeLtcnzj74see/py0iBz7xIuFuXT7m3aoyWJSnUVzZJiynD7TfOwUw3ifavQgZBgEiBlNOL7z4LOzsDgJwO3tQAKrPX23D1SN2L7i/QmRvc9OZItkcC+CTsrvQentwQDC8gOZRMzLUXGZABfDOSMPZR1VHMERZRorFWS9Jg2krvXB1pr9/erXPpFqWzl1/+XwckB7+0HIIfF1e8ZAer/wdD8dTE++8eVFl9XDIyBQP3jwj0p5PQzrL9XaG2tuTyWCvkFyeDHAtaiqaam3dd+HiC8cWFHXl5LmTyyref0ZhfvSXT1T+6A+/Rx5t/Ou++Rk9f/Tc9fW4zjD+XasvTARU3h3L+IM7nmXPDSJEDBC3CTd2uIfZQlFZ0wuSZmFJAxFzBpvAcPnXT7vAIItI+znET3DpXpuM/hcbAm7bcSvi1o9bCbcB1Fah/dIGfCh1K+bwduA5tKteqZVrxQmz3/jfZ5B/3wU3pLMHber+/5R3vaFxm2dceqXTybJO0Sk6WZEV+Swr8uVylc+ycpav14sxruPc3Kt3M15njAlZejMmhLCaEkIIpmQlhC2YUMIYIS2jhFJMuTt7JYRulK2MUkYp3fACG6PruoLHvrSwD+kSZ+/z6py4K+2nfdvB6STfIZ9Oz/s8z+/583vwd9tF/IH92z4v3k8aDodVbUiLLDHYK4y5su7Y/Kmzo9VR4fYplkToNexLmNVrL85N1TWve1/P/qA2mu2IL7yyPEZL4eq11R9OTFW/2ODmVzd+9dZPl+Rw9eIJbrGSs4U93c/fuPmtJ7zOjvO3Poh8+oDi0BdskspS321XT0LdQCM1RDzIHXrROF6+cZkwojqJrZYjg1VzuiPytKYcB+89kwXJdJKNfqBOh+JFSR4ZeVRxgPFQ5HVFXn3UGIdgDAL0WWLYaPKcKCv4HiBJqX9vpHJosDw+M61MFvXOVNrLisw7sipzqrW0cuXCSSP/2ItLP2n1afExQ+F4OfPaJ9ufX1Hxg2rnzD5Af2R56ik60Z5NAZUlzU5+K9pRmK2NY/uDWOJQwxpqHuO3NuwxOGra/BbhD6oSocIuf0sHJnNK57EN1yM2koNY1J6ORE3++Nek8oiwwo3LkIk7qtyN4d1mr3L3tqr9pkSsB6GAIwX7sG0cldefPAot+ROwbeG3dglbeqSF34S9iRHqF+NHe9JPTuxMChg/CgX3O8c7BaXQr237wwBAsZZouv2kZewYhATKIyNNG8gNKX3k4XyAHQqZtpbc6eKO1Gp8B7RC+FrdKZGGD9IRlHX9mYtrc06Qt5AsyyiVymZKC6FiuWqmVq3l1HzGRDG6c+/UqVNBvo9BGWn2+fOZQ8O9pm0MTvd1pzs6nhlDxYXXz1fEjOlzIsfpzrkroWaISE/rWraQ7kyk9nuLS7Pd+/A/CWbrnp+2hFhcTEud9Gl8fx/cevAhCjiTOgSshjZRqrmBBhORde3zSStimrQiYoDT6BtoPgaCioF7w37UPIbcIxigwUiNrrYTfAAjzx46BpyynA2hQXy14yx6W2RDC7urrMDTMTrHCwJC22vYC8L6suz4qp1OK6LMnHSF04gyBJ5DhQsXSh28f3AGGY6irCqXbm/euqyULKYuaBiXktzL2IM76C/Mx9jnebZdX0eC0Qo01sAitKIiueJmMwHefmKrkZCbJqxB7PeCHPJF8Hth2SWSDYF0CXQWyCJsDgyCCDAKFgwnP/h4OzJBtwlzuyIoBKmILuLw73YgSTyUCcZ4bA0NAfE8ZG05SVOscinIaggbCXSa5miUznIO79sCp/PlmTl7tJbDJuC3gHS0xReurNR1aXQiRMH08blJ2b6wumJzhaFn3/h2xn3uzjKnjc3NGXqtVj771qdt3w8KeV9mq9QAMHuRkjCV6KD8QEMi8HUfBjeDUPKPl0lL7endhbbxNRWUQvCw/IOYQwT2EF+OF+sPXD2vauFEpVpzRRFfkKEZIYNiKscwrJm2OHVm8Ux9SkLMqCVUzq1ePmO8SVONeqiwjiynj06WSj/a/uLCkXOPYxlg2fr1tzdeclBU2xZSFFthTYzbQqqVpKO+WI16BNY4gURDoF+wNxJPgGgah++eV4w4maGrExsCkh4iee2k37bp4N5jcdQ4j+6nBZrkUaCWzw1VTbP5T/EalFjESpapKiK9UvRiiGEJBYpkBQG/vSiZImdapiDkS+OlvCgyNz2Ht9T7LfPqq1dNNcg7vHr/DHq1mN2r6t2OJQjS/NnLZ+eljME7GtrY/nD71GWNlUzBWnkFujsVUve1yJxjN6knqBcoQiaawK65vNVKJcA0pGxsGo60Awo/+Ox3kTEO5cbI282h/UDlvj44BGN5fNi28P4u9edjpTcUYnn1d6Keu48i3ziB5dq0ct4O7d5QAUARc7hM74BaQkrX9bD0h+nvI8QiGAsO7/UYu2Bn07ZfLYuqxHNuzmHZeMKVOxn6JOJZLOtGdf54TkCCbHhZ07cEecVeqs8wFwNO98YnK5Z97fXXCtDMLh04kB/4zs3a8LBpbv8MmZyoayIya3MzOtLq798yWadkISNz/CThA8ndR+iXbBYj23cpEjkjbaX2JhGMtN+ye+H3swEw9spNsROrA5G0lZIM1F/vdUURGLsdm+ntvgvcdetmL8l1kq1Ftj2wZdfT8HL7yN/vzRIzZMvrfXYn/snxdhdYwR+GX94idHMm4XzstfsgE/qQ4DHifIz+9t8UozujsPb6EdUgFlkw7rF4314srDnF5TNsbqF+ppxHCqs4PE2DSiGhTXaxdP8eYpm64Sr8xNrajZCRkaDlj6T7lj56v5x55b2P3v25w3BMERkRf/s/Yy7LUgWIQRJGZnAHN3SlB6ipdWzHUUB2EQS+hqGBZqMjok0EtN1xkGQ7qKbeQ9BVM8AaspnA9rIZR1ipHAS9SabLDUMBDHgp7H76AJkxF7chzR619g/DiCb3MNhJtyypYxu3W+NjfmW2EqA/S6anqRleKZ55b/u9j9nO5OhsbVREKHzx0gsFPoPuuXJhckIam7x8ceXipUn9mp3NCaygOMVsMtXnHVu7dfNSBnEsyyOt4Gcx4oK6hAcz6B3uD9QUdazdg28N0I2ndgexIaVWxc8SBlQtQXwc7EJ/crQjFt+jah43kieZHWsSX3Aq85ALQwvIoDOMIcoIeP1gxg1JjPV5GOhB28IeWsJPoB2RWGI8gC/aYzTOqYybbglmRUy7dlbQ7bJeWH7ptaprIA6px0/VQ7FUUQJDLxo6l8tnWU0bnR6z5XBmcWFK5jlF5/yrV8/S3rnrs7rAhpVx0S3ZgijqTik4/saVk447anqo4OjV5au1E4uqyOuCqJVDj88VMpny8enq87UwY8rY4EBn+zNvUV+KG3VhvNBgBkgRbGpzfSC1EzpKRaGjffjHSiWjONnXB44UAX0lZiSgrwsZ0SodRgEj+sHnDyx0jlujqoAASd0fjCSCvBKhsmhM4a/29EBjfJOA4m68zqfxq4c9vzfjohrrShXBn+tOrif37RmIqHigEG8YegObReCqngLyifwgg9Ue4oA6kO4qgKRKZCBJCq9ADxuU2OGCB7YeppYMACFumfZQmzxGqtz48WlfK9qakEnbU1nRt0IbGaMTNi+Vp+cXZi0O+yuCNDl3ohZI6dFK0dDYrJdhNT3UVV+eLIjBifqcgrCwOtxk2XVPXNlYCMqOJoqCU3b5iamQFbRnrp9fvr5YtIBeQFV52cqEM8u16smymwk8Ph+W4cYKgrp0Yvracs1wQ5SL7uUUu8TMxm5TBymDihoC09xWSyTGNTsA4/+iglZ85cA+3QVYOFLzWOfH2xp/ii1UF2YnZbMQ5LOOZPqC6E7UHKvo2xz2Axw36+iGoRoSz35SnvEVPm3Ol/nymM/zyLEqlbLC81pakcKCizJhUeU42fjSDAvqfzCd4v/yfKzxzefr7jj7r8/+cTqR5GP3NrmRpLbXd7/pfPyu8xVy6KsnHJY/p7fov9G//5PZK3feXet8rjfnfv+prz0nfrB32DsUQx2mSCh+g3408bO9TzfYiBlChqP2SzNGRHMw2ZuEE/wbeEb/A2/smUkAeNpjYGRgYADiNPd//vH8Nl8Z5DkYQOBi2mttGP1vwZ8ZHFKcaUAuBwMTSBQATNIMKgAAAHjaY2BkYOBM+1MAIv8t+K/HIcUAFEEB5QCFzwWxAAAAeNo1UT9IAlEc/u79nnlBhDXE8RA5joiIG0Qk5DgkRKLBoSGEFkeJhmiIcGwJpMnWpmiUJmtocHSSaIqIiKDlaAgHh3DKvtM8+PG799735/e+p75RBj+5mpZlkLbukef/obQwx+6qN7hWESVVZR8gJ1xLFy4iBJKDsWxk1QkWVANb3Ctqgw3pwNU2FuUZnoCcNhzVRlqeYPCDLEbkbqMqDfj0qNHLJFv0dZHXFeIj5PQxzx5RkiOEukvNOkIrwIEawejcBBckThHoPRQlhYxeJsdwbWOXe47uwaF2SKyTtDlHh3ofcBI19t5E3xAPehZ0hBXe0VMDKLlAJZ5DNbEknfFA9eh9hgzvXLZSWEf0e82Z8szK1zcIqRkqD6vyjk0pE+uTy5zU2vhBDHN74SxNFOSG+l/kDJlXn37kq/54KLf0i/NnlvoOmK8Dsy4eoPb5Lpf/5bM++WDnU/ys9A6MzYrPYrx+Bf4A55BUUnjaY2Bg0IHCWYwOTArMbixZLE9YlVgzWNewS3FwcThw1HBs4rjFacHZwcXDNYnbhvsLTxavHu8Rvha+E/wy/EkCEQIdgnJCCsLLRLaIJok5iT0S95IQk3SS7JH8IS0hPUFmlayb7D65FPkMBQVFISULpRfKKipRKttU41SvqUWp1ak7qPdosGiYaPzSrNNS03qgXaeToSul26b7RO+UfpD+LAMfQyXDDUZhxizGBSYJJodMvUyXmSmY7TGPMb9hkWexyTLEchEQnsIBP1lJWTlZZVlNAcM9AEMMR+542mNgZGBgKGeoZGBlAAEmBkYgFmMAUSIgAQAaxQEpAHja3VrLbhvXGT6y06IJEi+66KKLYCDYRQzQspM4KWJ0w0iUrYYiFZKK6iVFDsWJyRmWM5TCV+gT9Am66GN01csTdNPHKLrsf77/P7eZ4aUuCgOFQPLMzDn/9fsv54yUUj9V/1D31cF77yulCvrw+EA9pCse31MP1O9lfF/11B9k/J56rv4l4x+pjw8aMv6xig5+LeOf0Ph7Gb9P49/J+ANVHPxRxh+q5/c+lvFHh4t7PRk/UM8f/knGf1Y/e/hPGf9FPXv0oYz/qh48+pWM/6Y+eCR8/35f/fzRQB2rTC3UWi1Vom7UlDSK1CdqpB7T72fqmfqUPg0af0PP5+paxTRzRvMj9ZLGubqj70SlWPWmNOcmmHFEVDN6/lj1ic9Qjenqjp5H6oyeFnQVqbaVokerbtSK6AyJWpl7yPsFrdyH5gtPp33mRyUpvgP/nJ5n0PgZaB3ht0zR0HPUdllw1/N34SnNpSCuL9RT+ttv1buQ8yOKFv0ZEL8E/jyFjwogI1MTGt3BhzHd4Rkz+h3RdUpXMfktIj+n9Kt5RTR/irl98mSbfrukUwypHOV2QEHrVEaIRof+RPTnZAs5G3lGsFsismidZ8CSpjuEZGbmkJ7kwOpQ3dInAT6v6VtTu6NrLb1+qqVtqm8xZvxHJZ/mxFd7akH3cpI0B7Ujor4kaz8lvU9JT2Nf/XnyTv40Z+eLC9VSHWjXpd8BfHFGyNN3+/S9yRMRUdIo/BJrY7LZkryucbEWdD5Tv3zHWurPBWWeFnnuXH1NmrUstrV/b0gjRkAEZDus7saojin26GNgguOB815OvzraONsVgqUMkTcGqsa4p79vBZ0Lmh8LJ5ZFo3gmeNRrh6B6i5UTK9WCnmTqe7o7Au4anhQrerrA2sLTza0dQWqmy76N6elEVjirDGnmENLOYQMXRTNkD53XE9F6JJLPoX+KCEqQa/zoYwlZ9ltrjyGk0zLF3tzM+mICK2g7sTXfII5TWHcK3lNPPy3/nOavJQdoi0zFU+MgE8ytJLHcSSHdEHZIBf9TxLbGj8sLmVh1iYj3cyej6BRRNoQfTX00fqhmTV9ythDLvZIZDcHWisaJvTOnmfp6YjOe0Yw1Zc/ozHRNKwvLi+3M9WIo2TSDN801S7r28J1C4wg5cybZdW1nziHnDHbMkasHJcwxCrR9RzSP9TAcU1DiqpEgGzu8G3/z+hFmG+tcS7WZWYvEUunGoMb3ttmC7fUUPHzd/PzP0uWVChhieCy2GMJKZtUS9tB6GYSlguO8xrYri4frvSxSb2eHgrr1bMcpMMk5aOlZ1kjC9l3CpzEwUa3uRkcXCdoCa8SsyR8h0n15Ne3fInss4TWTASfii2pE8LyhxGi5z6jvCnQnybY2mg2RGWeC3SzAX0ZrV54sLksa7XOL2qLG7pnX9SQY13vA5YsTqkunVHU79BnQp4vaq58cbum+DsUaE8k/RhMjk9bdVZMJuhG2QtWjfhRHtX3nK4kKzesTWvd4b+sbHI6Ep+lR5xi/sTGYS83SWfwo6PJMFvfzRizRuCIaI/GB0bAhWSGROA47Mz8yQl+7Suh8c4idSxi9zicdieNNvjCo8uM9R2yMShnb115fT4A3v38e1XglF6ld7LBvfPm7siKBFLNKR7cLR6YP4Q7DdAqMqm17A+4CFpgRe1kph+XrM/Hb4NDX9bxSC/fTdXv1mUv3Y+QborK4HJABcWOJqkKeNGwu0H69lv6ogLZm7RN00WG/YVa5ziaT/QjPdhl3UvJS1drlrnY7EhpWwxFqWCpzb2xGnsMuLsvxbNNjlrPiNnQYu0eQ9w5VO0UdXWKVwbPv3SZsNwW3fTyZQ9vUVrfYahTbe1y/b6SznNv7BfA+RQc7EmvdwX4mLjP5dnVvIbJknufYM2kN1sMo22yrI28v06JsdE4Voo8dXBc7t18gUvT4pFI/LiDRHNHmdnCcVVnqWHzIFkhFukbQiZv9CHfPN7JDD+0d6p4R1UKqtOvwXA4rI3Oz9o7Typ4NmB54LT0L0+ReOPYkdH1g2Cevt3aE/j6F+9nZ1i57BbSWn7oziPw/1JazhdnRlXEykWycoTtlyzLCxrLXylB5X1jUfIpa3UE34vdou2M0FYyHGSeRDJAIT+59VxIjdXmoYbNZNQMxh115OxcPhru5cA/Ccml/TbyY+Qzavz3f/X1Xlq+6L/nf7EEaO3YhMfbv0yD6TE7iCPV3pXzacLux4+AOOpGey+3n67s/1+vnQtHfuYX93Biy+hg1XVEhfJ7Ad4wsztA/yG7B7/ym6Oj0iifSuY+9M72p3DFVw6+1zgYLsegCupsznLlYkitIHfU56j/fK+Q8IwEmx+BmvGn4GQ1MNWV88hma37Fv3p9nYtmQT2hn7vQT6btvMfOutuNaSafr4udzyR7ZHtHyNrGyEvnNmn26bX//wRbKoeUP2NMl6K0Lr14Xcn602FINw/pXtssIHuJ9/MJmW/bFri413MswDY7/sJ9O7VnMQvSIa7pxRuTcQ4mxjtljMDq07xb25CHd0HUYf/u70eewrdmhpyWbhx7ed6eYBTXH7+Pq6W5DDp/icVUOTyrcyYl/vjjHnNh2gGPwzaWzWUo/z2cgBbwUe9l2F+Ybgjyd8xZevdaZ4g3ku5MKcBPgvNoVMr3/zs5+Pt5s6WVQV/yTil0xxKiqRpFDzxcBerZ3OtWuiWWr66gae++TmPIKUWaQsanqcmQkciKy3vNMw+8QHacQi5s47jo7+/8/K9tnpzOwO50OYdjsacL3kmXJr9ExZ/acJcX7l5nnq1t6msgJ/2TjTrrcAZU76+qJLVd9/zxP79COVZtkPyMttC4s+yu8UXPv2vp4RzBQVzSzh2d6ZYS3Vl3KNGc4GzyhO3r325fnh0DgFXZ7r2jeJWgxjR59a9qv5f1DhOvXeEt8hj2iXttSv5E3Y31Q7dI4gqwXeP/Xknl6hdbjEjp11Eu697Xw69Aq877wHLKwpAO677iGUp2Bo5GMLXNMOvDTJtE+Az0tfwOW0uOOlfNUJG3CRpryAG8rL2HrHu5e0u8FzeO3l03ozNJ2oMMpPWddWpCAPcESHeON6GvMeElyDSDFBTDIMxvQUOtzgvWa6ze4y5J1xcs99DKGypHYkuXQ9v/Ocu5D/zbeFPFajZWqJBF83QbfHvzQEus35d2mbx+2vsOglvAE70Gb0LxfK7GhFnqhDgWGw0vo0YJF2pjdxznFMSi17Xq9sof7A48m45t93/aseCxnGC31LXFtCXaasFGoBUeClt9pwZZuyvexzR++lzvixWPr0y7QVLXKFWKuhVlN+KNvrXCKOD0XyS89JJlYvxQcdq1koX1NvJh5++QIpmV4hx48wdvutkjYt9bYTfforf6f4QonSK4L5f/iuZL830QPpv8f4Cs8+5Jo6/9a0d9f2f9i+QJ1aUJ5VWfsAhw42/q1wtQ+1Op/Ay6aYeIAAAB42n3M104CYRSF0e/Qewd7731mYCh2BLH33iVRgcQYoyHG19IX1Dj/tedmZe+dHGz8fx8gNrFjx4ETF248ePHhJ0CQEGEiRIkRJ0GSFC200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDNo6BikyWCSJUeeArPMMc8CiyyxTJEVSpRZpcIa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd91TFIU5xiVs84hWf+CUgQQlJWCISlZjE+eJbEpKUlKv2/Pla193Nl4amaWXLoqb8y8bvoNSVhjKtzChNZVaZU+aVBWXRUld/dd331Kg13x4fqu91qzIqlqalWSn9ACnqRHp42j3MsQ6CMBQF0D4qBStQBlYTnJuoCb8gOLAQpzb6C67OxsRRv+XVybj4afrU2u2em5t7h9cZ4cJ6TAfjAK7WdUKbGZa2x2pD4WinKPTOMOR1i1yvUNTtjT8j/UVMEGuPESFuPJLPbO+REpKlx5iQzn8AlP42r9sHk6BYpB3vDtRktMu3gRNi1gQWRHkKVMSiCyyJavGnxUq/Aa6pQk0AAAFVQTqrAAA=) format('woff'); + font-weight: normal; + font-style: normal; +} + +/* + * Vendors + */ + +@font-face { + font-family: weather-icons; + src: url('fonts/weather-icons/weather-icons.eot'); + src: url('fonts/weather-icons/weather-icons.eot?#iefix') format('embedded-opentype'), url('fonts/weather-icons/weather-icons.woff') format('woff'), url('fonts/weather-icons/weather-icons.ttf') format('truetype'), url('fonts/weather-icons/weather-icons.svg#icon') format('svg'); + font-weight: 400; + font-style: normal; +} + +#weather-widget [class*="icon-"] { + font-family: 'weather-icons'; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-0:before { + content: ":"; +} + +.icon-1:before { + content: "p"; +} + +.icon-2:before { + content: "S"; +} + +.icon-3:before { + content: "Q"; +} + +.icon-4:before { + content: "S"; +} + +.icon-5:before { + content: "W"; +} + +.icon-6:before { + content: "W"; +} + +.icon-7:before { + content: "W"; +} + +.icon-8:before { + content: "W"; +} + +.icon-9:before { + content: "I"; +} + +.icon-10:before { + content: "W"; +} + +.icon-11:before { + content: "I"; +} + +.icon-12:before { + content: "I"; +} + +.icon-13:before { + content: "I"; +} + +.icon-14:before { + content: "I"; +} + +.icon-15:before { + content: "W"; +} + +.icon-16:before { + content: "I"; +} + +.icon-17:before { + content: "W"; +} + +.icon-18:before { + content: "U"; +} + +.icon-19:before { + content: "Z"; +} + +.icon-20:before { + content: "Z"; +} + +.icon-21:before { + content: "Z"; +} + +.icon-22:before { + content: "Z"; +} + +.icon-23:before { + content: "Z"; +} + +.icon-24:before { + content: "E"; +} + +.icon-25:before { + content: "E"; +} + +.icon-26:before { + content: "3"; +} + +.icon-27:before { + content: "a"; +} + +.icon-28:before { + content: "A"; +} + +.icon-29:before { + content: "a"; +} + +.icon-30:before { + content: "A"; +} + +.icon-31:before { + content: "6"; +} + +.icon-32:before { + content: "1"; +} + +.icon-33:before { + content: "6"; +} + +.icon-34:before { + content: "1"; +} + +.icon-35:before { + content: "W"; +} + +.icon-36:before { + content: "1"; +} + +.icon-37:before { + content: "S"; +} + +.icon-38:before { + content: "S"; +} + +.icon-39:before { + content: "S"; +} + +.icon-40:before { + content: "M"; +} + +.icon-41:before { + content: "W"; +} + +.icon-42:before { + content: "I"; +} + +.icon-43:before { + content: "W"; +} + +.icon-44:before { + content: "a"; +} + +.icon-45:before { + content: "S"; +} + +.icon-46:before { + content: "U"; +} + +.icon-47:before { + content: "S"; +} + +.btn-file { + overflow: hidden; + position: relative; + vertical-align: middle; +} + + .btn-file > input { + position: absolute; + top: 0; + right: 0; + margin: 0; + opacity: 0; + filter: alpha(opacity=0); + font-size: 23px; + height: 100%; + width: 100%; + direction: ltr; + cursor: pointer; + } + +.fileinput { + margin-bottom: 9px; + display: inline-block; +} + + .fileinput .form-control { + padding-top: 7px; + padding-bottom: 5px; + display: inline-block; + margin-bottom: 0px; + vertical-align: middle; + cursor: text; + } + + .fileinput .thumbnail { + overflow: hidden; + display: inline-block; + margin-bottom: 5px; + vertical-align: middle; + text-align: center; + } + + .fileinput .thumbnail > img { + max-height: 100%; + } + + .fileinput .btn { + vertical-align: middle; + } + +.fileinput-exists .fileinput-new, +.fileinput-new .fileinput-exists { + display: none; +} + +.fileinput-inline .fileinput-controls { + display: inline; +} + +.fileinput-filename { + vertical-align: middle; + display: inline-block; + overflow: hidden; +} + +.form-control .fileinput-filename { + vertical-align: bottom; +} + +.fileinput.input-group { + display: table; +} + + .fileinput.input-group > * { + position: relative; + z-index: 2; + } + + .fileinput.input-group > .btn-file { + z-index: 1; + } + +.fileinput-new.input-group .btn-file, +.fileinput-new .input-group .btn-file { + border-radius: 0 2px 2px 0; +} + + .fileinput-new.input-group .btn-file.btn-xs, + .fileinput-new .input-group .btn-file.btn-xs, + .fileinput-new.input-group .btn-file.btn-sm, + .fileinput-new .input-group .btn-file.btn-sm { + border-radius: 0 2px 2px 0; + } + + .fileinput-new.input-group .btn-file.btn-lg, + .fileinput-new .input-group .btn-file.btn-lg { + border-radius: 0 2px 2px 0; + } + +.form-group.has-warning .fileinput .fileinput-preview { + color: #ff9800; +} + +.form-group.has-warning .fileinput .thumbnail { + border-color: #faebcc; +} + +.form-group.has-error .fileinput .fileinput-preview { + color: #f44336; +} + +.form-group.has-error .fileinput .thumbnail { + border-color: #ebccd1; +} + +.form-group.has-success .fileinput .fileinput-preview { + color: #4caf50; +} + +.form-group.has-success .fileinput .thumbnail { + border-color: #d6e9c6; +} + +.input-group-addon:not(:first-child) { + border-left: 0; +} + +/*! + * Waves v0.7.2 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + */ + +.waves-effect { + position: relative; + cursor: pointer; + display: inline-block; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; +} + + .waves-effect .waves-ripple { + position: absolute; + border-radius: 50%; + width: 100px; + height: 100px; + margin-top: -50px; + margin-left: -50px; + opacity: 0; + background: rgba(0, 0, 0, 0.2); + background: -webkit-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -o-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -moz-radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: radial-gradient(rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + -webkit-transition: all 0.5s ease-out; + -moz-transition: all 0.5s ease-out; + -o-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; + -webkit-transition-property: -webkit-transform, opacity; + -moz-transition-property: -moz-transform, opacity; + -o-transition-property: -o-transform, opacity; + transition-property: transform, opacity; + -webkit-transform: scale(0) translate(0, 0); + -moz-transform: scale(0) translate(0, 0); + -ms-transform: scale(0) translate(0, 0); + -o-transform: scale(0) translate(0, 0); + transform: scale(0) translate(0, 0); + pointer-events: none; + } + + .waves-effect.waves-light .waves-ripple { + background: rgba(255, 255, 255, 0.4); + background: -webkit-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -o-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: -moz-radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + background: radial-gradient(rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%); + } + + .waves-effect.waves-classic .waves-ripple { + background: rgba(0, 0, 0, 0.2); + } + + .waves-effect.waves-classic.waves-light .waves-ripple { + background: rgba(255, 255, 255, 0.4); + } + +.waves-notransition { + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + transition: none !important; +} + +.waves-button, +.waves-circle { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, #ffffff 100%, #000000 100%); +} + + .waves-button, + .waves-button:hover, + .waves-button:visited, + .waves-button-input { + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: none; + outline: none; + color: inherit; + background-color: rgba(0, 0, 0, 0); + font-size: 1em; + line-height: 1em; + text-align: center; + text-decoration: none; + z-index: 1; + } + +.waves-button { + padding: 0.85em 1.1em; + border-radius: 0.2em; +} + +.waves-button-input { + margin: 0; + padding: 0.85em 1.1em; +} + +.waves-input-wrapper { + border-radius: 0.2em; + vertical-align: bottom; +} + + .waves-input-wrapper.waves-button { + padding: 0; + } + + .waves-input-wrapper .waves-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; + } + +.waves-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; +} + +.waves-float { + -webkit-mask-image: none; + -webkit-box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); + box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); + -webkit-transition: all 300ms; + -moz-transition: all 300ms; + -o-transition: all 300ms; + transition: all 300ms; +} + + .waves-float:active { + -webkit-box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); + box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); + } + +.waves-block { + display: block; +} + +/* Firefox Bug: link not triggered */ + +a.waves-effect .waves-ripple { + z-index: -1; +} + +/* + * Load Website related LESS files + */ + +/* + * Generate Margin Class + * margin, margin-top, margin-bottom, margin-left, margin-right + */ + +.m-0 { + margin: 0px !important; +} + +.m-t-0 { + margin-top: 0px !important; +} + +.m-b-0 { + margin-bottom: 0px !important; +} + +.m-l-0 { + margin-left: 0px !important; +} + +.m-r-0 { + margin-right: 0px !important; +} + +.m-5 { + margin: 5px !important; +} + +.m-t-5 { + margin-top: 5px !important; +} + +.m-b-5 { + margin-bottom: 5px !important; +} + +.m-l-5 { + margin-left: 5px !important; +} + +.m-r-5 { + margin-right: 5px !important; +} + +.m-10 { + margin: 10px !important; +} + +.m-t-10 { + margin-top: 10px !important; +} + +.m-b-10 { + margin-bottom: 10px !important; +} + +.m-l-10 { + margin-left: 10px !important; +} + +.m-r-10 { + margin-right: 10px !important; +} + +.m-15 { + margin: 15px !important; +} + +.m-t-15 { + margin-top: 15px !important; +} + +.m-b-15 { + margin-bottom: 15px !important; +} + +.m-l-15 { + margin-left: 15px !important; +} + +.m-r-15 { + margin-right: 15px !important; +} + +.m-20 { + margin: 20px !important; +} + +.m-t-20 { + margin-top: 20px !important; +} + +.m-b-20 { + margin-bottom: 20px !important; +} + +.m-l-20 { + margin-left: 20px !important; +} + +.m-r-20 { + margin-right: 20px !important; +} + +.m-25 { + margin: 25px !important; +} + +.m-t-25 { + margin-top: 25px !important; +} + +.m-b-25 { + margin-bottom: 25px !important; +} + +.m-l-25 { + margin-left: 25px !important; +} + +.m-r-25 { + margin-right: 25px !important; +} + +.m-30 { + margin: 30px !important; +} + +.m-t-30 { + margin-top: 30px !important; +} + +.m-b-30 { + margin-bottom: 30px !important; +} + +.m-l-30 { + margin-left: 30px !important; +} + +.m-r-30 { + margin-right: 30px !important; +} + +/* + * Generate Padding Class + * padding, padding-top, padding-bottom, padding-left, padding-right + */ + +.p-0 { + padding: 0px !important; +} + +.p-t-0 { + padding-top: 0px !important; +} + +.p-b-0 { + padding-bottom: 0px !important; +} + +.p-l-0 { + padding-left: 0px !important; +} + +.p-r-0 { + padding-right: 0px !important; +} + +.p-5 { + padding: 5px !important; +} + +.p-t-5 { + padding-top: 5px !important; +} + +.p-b-5 { + padding-bottom: 5px !important; +} + +.p-l-5 { + padding-left: 5px !important; +} + +.p-r-5 { + padding-right: 5px !important; +} + +.p-10 { + padding: 10px !important; +} + +.p-t-10 { + padding-top: 10px !important; +} + +.p-b-10 { + padding-bottom: 10px !important; +} + +.p-l-10 { + padding-left: 10px !important; +} + +.p-r-10 { + padding-right: 10px !important; +} + +.p-15 { + padding: 15px !important; +} + +.p-t-15 { + padding-top: 15px !important; +} + +.p-b-15 { + padding-bottom: 15px !important; +} + +.p-l-15 { + padding-left: 15px !important; +} + +.p-r-15 { + padding-right: 15px !important; +} + +.p-20 { + padding: 20px !important; +} + +.p-t-20 { + padding-top: 20px !important; +} + +.p-b-20 { + padding-bottom: 20px !important; +} + +.p-l-20 { + padding-left: 20px !important; +} + +.p-r-20 { + padding-right: 20px !important; +} + +.p-25 { + padding: 25px !important; +} + +.p-t-25 { + padding-top: 25px !important; +} + +.p-b-25 { + padding-bottom: 25px !important; +} + +.p-l-25 { + padding-left: 25px !important; +} + +.p-r-25 { + padding-right: 25px !important; +} + +.p-30 { + padding: 30px !important; +} + +.p-t-30 { + padding-top: 30px !important; +} + +.p-b-30 { + padding-bottom: 30px !important; +} + +.p-l-30 { + padding-left: 30px !important; +} + +.p-r-30 { + padding-right: 30px !important; +} + +/* + * Font Weight + */ + +.f-300 { + font-weight: 300 !important; +} + +.f-400 { + font-weight: 400 !important; +} + +.f-500 { + font-weight: 500 !important; +} + +.f-700 { + font-weight: 700 !important; +} + +/* + * Position Classes + */ + +.p-relative { + position: relative !important; +} + +.p-absolute { + position: absolute !important; +} + +.p-fixed { + position: fixed !important; +} + +.p-static { + position: static !important; +} + +/* + * Overflow + */ + +.o-hidden { + overflow: hidden !important; +} + +.o-visible { + overflow: visible !important; +} + +.o-auto { + overflow: auto !important; +} + +/* + * Display + */ + +.d-block { + display: block !important; +} + +.di-block { + display: inline-block !important; +} + +/* + * Material Background Colors + */ + +.bgm-white { + background-color: #ffffff !important; +} + +.c-white { + color: #ffffff !important; +} + +.bgm-black { + background-color: #000000 !important; +} + +.c-black { + color: #000000 !important; +} + +.bgm-brown { + background-color: #795548 !important; +} + +.c-brown { + color: #795548 !important; +} + +.bgm-pink { + background-color: #e91e63 !important; +} + +.c-pink { + color: #e91e63 !important; +} + +.bgm-red { + background-color: #f44336 !important; +} + +.c-red { + color: #f44336 !important; +} + +.bgm-blue { + background-color: #2196f3 !important; +} + +.c-blue { + color: #2196f3 !important; +} + +.bgm-purple { + background-color: #9c27b0 !important; +} + +.c-purple { + color: #9c27b0 !important; +} + +.bgm-deeppurple { + background-color: #673ab7 !important; +} + +.c-deeppurple { + color: #673ab7 !important; +} + +.bgm-lightblue { + background-color: #03a9f4 !important; +} + +.c-lightblue { + color: #03a9f4 !important; +} + +.bgm-cyan { + background-color: #00bcd4 !important; +} + +.c-cyan { + color: #00bcd4 !important; +} + +.bgm-teal { + background-color: #009688 !important; +} + +.c-teal { + color: #009688 !important; +} + +.bgm-green { + background-color: #4caf50 !important; +} + +.c-green { + color: #4caf50 !important; +} + +.bgm-lightgreen { + background-color: #8bc34a !important; +} + +.c-lightgreen { + color: #8bc34a !important; +} + +.bgm-lime { + background-color: #cddc39 !important; +} + +.c-lime { + color: #cddc39 !important; +} + +.bgm-yellow { + background-color: #ffeb3b !important; +} + +.c-yellow { + color: #ffeb3b !important; +} + +.bgm-amber { + background-color: #ffc107 !important; +} + +.c-amber { + color: #ffc107 !important; +} + +.bgm-orange { + background-color: #ff9800 !important; +} + +.c-orange { + color: #ff9800 !important; +} + +.bgm-deeporange { + background-color: #ff5722 !important; +} + +.c-deeporange { + color: #ff5722 !important; +} + +.bgm-gray { + background-color: #9e9e9e !important; +} + +.c-gray { + color: #9e9e9e !important; +} + +.bgm-bluegray { + background-color: #607d8b !important; +} + +.c-bluegray { + color: #607d8b !important; +} + +.bgm-indigo { + background-color: #3f51b5 !important; +} + +.c-indigo { + color: #3f51b5 !important; +} + +/* + * Background Colors + */ + +.bg-black-trp { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +/* + * Border + */ + +.b-0 { + border: 0 !important; +} + +/* + * width + */ + +.w-100 { + width: 100% !important; +} + +/* + * Media - Overriding the Media object to 3.2 version in order to prevent issues like text overflow. + */ + +.media { + overflow: visible; +} + + .media:before, + .media:after { + content: " "; + display: table; + } + + .media:after { + clear: both; + } + + .media:before, + .media:after { + content: " "; + display: table; + } + + .media:after { + clear: both; + } + + .media > .pull-left { + padding-right: 15px; + } + + .media > .pull-right { + padding-left: 15px; + } + +.media-heading { + font-size: 14px; + margin-bottom: 10px; +} + +.media-body { + zoom: 1; + display: block; + width: auto; +} + +.media-object { + border-radius: 2px; +} + +.close { + opacity: 0.5; + filter: alpha(opacity=50); + font-weight: normal; + text-shadow: none; +} + + .close:hover { + color: inherit; + opacity: 1; + filter: alpha(opacity=100); + } + +.dl-horizontal dt { + text-align: left; +} + +*, +button, +input, +i, +a { + -webkit-font-smoothing: antialiased; +} + + *, + *:active, + *:hover { + outline: none !important; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0) !important; + } + +html, +body { + min-height: 100vh; +} + +html { + overflow-x: hidden\0/; + -ms-overflow-style: none; +} + +body { + font-weight: 400; + padding-top: 65px; + -webkit-animation-name: fadeIn; + animation-name: fadeIn; + -webkit-animation-duration: 1000ms; + animation-duration: 1000ms; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +audio, +video { + outline: none; +} + +p { + margin-bottom: 20px; +} + +small { + font-size: 11px; +} + +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small { + font-size: 12px; +} + +/* + * Ordered Lists + */ + +.clist { + list-style: none; +} + + .clist > li:before { + font-family: 'Material Design Iconic Font'; + margin: 0 10px 0 -20px; + vertical-align: middle; + } + + .clist.clist-angle > li:before { + content: "\f1b6"; + } + + .clist.clist-check > li:before { + content: "\f299"; + } + + .clist.clist-star > li:before { + content: "\f2e5"; + } + +#main { + position: relative; +} + +body #content { + padding: 30px 0; +} + +@media (min-width: 1200px) { + body .sw-toggled #content { + padding: 30px 0 30px 250px; + } +} + +@media (min-width: 1200px) { + body .sw-toggled #content > .container { + width: calc(100% - 30px); + } +} + +#header { + background: #4285F4; + box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.3); + height: 65px; + position: fixed; + z-index: 1001; + width: 100%; + left: 0; + padding-right: 10px; + top: 0; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + + #header:not(.sidebar-toggled).header-up { + -webkit-transform: translate3d(0, -70px, 0); + transform: translate3d(0, -70px, 0); + } + +.header-inner { + list-style: none; + padding: 15px 0; +} + + .header-inner > li { + display: inline-block; + vertical-align: top; + } + + .header-inner > li:not(:last-child) { + margin-right: -2px; + } + + .header-inner .logo a { + color: #fff; + text-transform: uppercase; + padding: 6px 10px; + display: block; + font-size: 16px; + font-weight: 100; + } + +#menu-trigger { + width: 65px; + height: 35px; + cursor: pointer; +} + + #menu-trigger .line-wrap .line { + background-color: #fff; + } + + #menu-trigger:before { + content: ""; + position: absolute; + top: 9px; + left: 7px; + width: 45px; + height: 45px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.22); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + z-index: 0; + } + + #menu-trigger.open:before { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + +.top-menu { + list-style: none; + padding: 0; +} + + .top-menu > li { + display: inline-block; + } + +@media (max-width: 767px) { + .top-menu > li { + position: static !important; + } +} + +.top-menu > li .dropdown-menu-lg { + padding: 0; +} + + .top-menu > li .dropdown-menu-lg .lv-body { + height: 275px; + overflow-y: auto; + } + +@media (min-width: 768px) { + .top-menu > li:not(#toggle-width) { + position: relative; + } + + .top-menu > li:not(#toggle-width):before { + left: 0; + top: 0; + content: ""; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform: scale3d(0, 0, 0); + -moz-transform: scale3d(0, 0, 0); + -ms-transform: scale3d(0, 0, 0); + -o-transform: scale3d(0, 0, 0); + transform: scale3d(0, 0, 0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + background-color: rgba(0, 0, 0, 0.12); + z-index: 0; + border-radius: 2px; + opacity: 0; + filter: alpha(opacity=0); + } + + .top-menu > li:not(#toggle-width):hover:before { + -webkit-transform: scale3d(1, 1, 1); + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -o-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + opacity: 1; + filter: alpha(opacity=100); + } + + .top-menu > li:not(#toggle-width).open:before { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + opacity: 1; + filter: alpha(opacity=100); + } +} + +.top-menu > li > a { + height: 35px; + min-width: 50px; + display: inline-block; + background-position: center; + background-repeat: no-repeat; + position: relative; + z-index: 1; +} + + .top-menu > li > a > .tmn-counts { + position: absolute; + color: #FFF; + font-style: normal; + background: #f44336; + padding: 1px 5px; + border-radius: 2px; + right: 7px; + top: -3px; + font-size: 10px; + -webkit-animation-name: wobble; + animation-name: wobble; + -webkit-animation-duration: 500ms; + animation-duration: 500ms; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + } + + .top-menu > li > a.tm-log { + background-image: url("img/icons/menu-2.png"); + } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .top-menu > li > a.tm-log { + background-image: url("img/icons/menu-2@2x.png"); + background-size: 18px 12px; + } +} + +.top-menu > li > a.tm-settings { + background-image: url("img/icons/ellipsis.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .top-menu > li > a.tm-settings { + background-image: url("img/icons/ellipsis@2x.png"); + background-size: 24px 24px; + } +} + +.top-menu > li > a.tm-notification { + background-image: url("img/icons/notification.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .top-menu > li > a.tm-notification { + background-image: url("img/icons/notification@2x.png"); + background-size: 24px 24px; + } +} + +.top-menu > li > a.tm-message { + background-image: url("img/icons/message.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .top-menu > li > a.tm-message { + background-image: url("img/icons/message@2x.png"); + background-size: 24px 24px; + } +} + +.top-menu > li > a.tm-search { + background-image: url("img/icons/search.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .top-menu > li > a.tm-search { + background-image: url("img/icons/search@2x.png"); + background-size: 24px 24px; + } +} + +.top-menu > li > a.tm-task { + background-image: url("img/icons/task.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .top-menu > li > a.tm-task { + background-image: url("img/icons/task@2x.png"); + background-size: 24px 24px; + } +} + +.top-menu > li:before { + top: -1px !important; +} + +@media (max-width: 767px) { + .top-menu .dropdown-menu-lg { + width: calc(100% - 28px) !important; + } + + .top-menu .dropdown-menu { + right: 14px; + top: 55px; + } +} + +@media (min-width: 1200px) { + .top-menu #toggle-width .toggle-switch { + margin: -12px 30px 0 0; + } + + .top-menu #toggle-width .toggle-switch .ts-helper { + height: 11px; + width: 33px; + } + + .top-menu #toggle-width .toggle-switch .ts-helper:before { + width: 20px; + height: 20px; + top: -5px; + } + + .top-menu #toggle-width .toggle-switch input:checked + .ts-helper { + background: rgba(0, 0, 0, 0.26); + } + + .top-menu #toggle-width .toggle-switch input:checked + .ts-helper:before { + left: 18px; + background: #fff; + } +} + +@media (max-width: 1200px) { + .top-menu #toggle-width { + display: none; + } +} + +#notifications { + position: relative; +} + + #notifications .lv-body { + overflow-x: hidden; + } + + #notifications:before { + content: ""; + position: absolute; + width: 100%; + height: calc(100% - 70px); + background: url(img/notifications.png) no-repeat center; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 400ms; + transition-duration: 400ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: scale(0) rotate(-180deg); + -ms-transform: scale(0) rotate(-180deg); + -o-transform: scale(0) rotate(-180deg); + transform: scale(0) rotate(-180deg); + opacity: 0; + filter: alpha(opacity=0); + top: 42px; + } + + #notifications.empty:before { + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + -o-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + opacity: 1; + filter: alpha(opacity=100); + } + +#top-search-wrap { + position: absolute; + top: -65px; + left: 0; + width: 100%; + height: 65px; + background: #4285F4; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + opacity: 0; + filter: alpha(opacity=0); + z-index: 10; +} + +@media (min-width: 768px) { + #top-search-wrap { + text-align: center; + } +} + +#top-search-wrap input[type="text"] { + border: 0; + height: 40px; + padding: 0 10px 0 40px; + font-size: 18px; + margin: 12px; + width: 500px; + border-radius: 2px; + color: rgba(51, 51, 51, 0.69); + background-color: rgba(255, 255, 255, 0.26); + background-image: url("img/icons/search.png"); + background-repeat: no-repeat; + background-position: 10px center; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + #top-search-wrap input[type="text"] { + background-image: url("img/icons/search@2x.png"); + background-size: 24px 24px; + } +} + +#top-search-wrap input[type="text"]:focus { + background-color: rgba(255, 255, 255, 0.4); +} + +@media (max-width: 767px) { + #top-search-wrap input[type="text"] { + width: calc(100% - 60px); + } +} + +#top-search-wrap #top-search-close { + position: absolute; + top: 16px; + font-size: 23px; + font-style: normal; + color: rgba(0, 0, 0, 0.38); + width: 35px; + text-align: center; + border-radius: 2px; + cursor: pointer; + right: 20px; +} + + #top-search-wrap #top-search-close:hover { + background-color: rgba(0, 0, 0, 0.15); + color: #000; + } + +@media (max-width: 767px) { + #top-search-wrap #top-search-close { + right: 7px; + } +} + +.search-toggled #top-search-wrap { + top: 0; + opacity: 1; + filter: alpha(opacity=100); +} + +/* + * Full Width Layout + */ + +@media (min-width: 1200px) { + .sw-toggled #header { + padding-left: 15px; + } + + .sw-toggled #menu-trigger { + display: none; + } +} + +/* + * For Stupid IE9 + */ + +.ie9 #header:not(.sidebar-toggled).header-up { + display: none; +} + +:-webkit-full-screen [data-action="fullscreen"] { + display: none; +} + +:-moz-full-screen [data-action="fullscreen"] { + display: none; +} + +:-ms-fullscreen [data-action="fullscreen"] { + display: none; +} + +:full-screen [data-action="fullscreen"] { + display: none; +} + +:fullscreen [data-action="fullscreen"] { + display: none; +} + +#sidebar { + position: fixed; + background: #fff; + box-shadow: 0 0 10px rgba(51, 51, 51, 0.38); + top: 65px; + height: calc(100% - 65px); + -webkit-transform: translate3d(-250px, 0, 0); + transform: translate3d(-250px, 0, 0); + z-index: 5; + width: 268px; + overflow: hidden; + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; +} + + #sidebar .sidebar-inner { + height: 100%; + box-sizing: border-box; + width: 268px; + } + + #sidebar .sidebar-inner .si-inner { + width: 268px; + } + + #sidebar.toggled { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + filter: alpha(opacity=100); + } + + #sidebar .profile-menu > a { + display: block; + height: 129px; + margin-bottom: 5px; + width: 100%; + background: url(img/profile-menu.png) no-repeat left top; + background-size: 100%; + } + + #sidebar .profile-menu > a .profile-pic { + padding: 12px; + } + + #sidebar .profile-menu > a .profile-pic > img { + width: 47px; + height: 47px; + border-radius: 50%; + border: 3px solid rgba(0, 0, 0, 0.14); + box-sizing: content-box; + } + + #sidebar .profile-menu > a .profile-info { + background: rgba(0, 0, 0, 0.37); + padding: 7px 14px; + color: #fff; + margin-top: 20px; + position: relative; + } + + #sidebar .profile-menu > a .profile-info > i { + font-size: 19px; + line-height: 100%; + position: absolute; + right: 5px; + top: 7px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + #sidebar .profile-menu .main-menu { + display: none; + margin: 0 0 0; + border-bottom: 1px solid #E6E6E6; + } + + #sidebar .profile-menu:before, + #sidebar .profile-menu:after { + content: " "; + display: table; + } + + #sidebar .profile-menu:after { + clear: both; + } + + #sidebar .profile-menu:before, + #sidebar .profile-menu:after { + content: " "; + display: table; + } + + #sidebar .profile-menu:after { + clear: both; + } + + #sidebar .profile-menu.toggled .profile-info > i { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + } + + #sidebar .main-menu { + list-style: none; + padding-left: 0; + margin: 20px 0 0 0; + } + + #sidebar .main-menu > li > a { + padding: 14px 20px 14px 52px; + display: block; + color: #4C4C4C; + font-weight: 500; + position: relative; + } + + #sidebar .main-menu > li > a:hover { + color: #262626; + background-color: #f7f7f7; + } + + #sidebar .main-menu > li > a > i { + position: absolute; + left: 16px; + font-size: 20px; + top: 0; + width: 25px; + text-align: center; + padding: 9px 0; + } + + #sidebar .main-menu > li.sub-menu > a:before, + #sidebar .main-menu > li.sub-menu > a:after { + position: absolute; + right: 10px; + top: 12px; + color: #575757; + font-family: 'Material Design Iconic Font'; + font-size: 17px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + } + + #sidebar .main-menu > li.sub-menu > a:before { + content: "\f0fb"; + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + + #sidebar .main-menu > li.sub-menu > a:after { + content: "\f111"; + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + } + + #sidebar .main-menu > li.sub-menu > ul { + list-style: none; + background: #f7f7f7; + display: none; + padding: 0; + } + + #sidebar .main-menu > li.sub-menu > ul > li > a { + color: #7f7f7f; + padding: 8px 20px 8px 50px; + font-weight: 500; + display: block; + } + + #sidebar .main-menu > li.sub-menu > ul > li > a.active, + #sidebar .main-menu > li.sub-menu > ul > li > a:hover { + color: #000; + } + + #sidebar .main-menu > li.sub-menu > ul > li:first-child > a { + padding-top: 14px; + } + + #sidebar .main-menu > li.sub-menu > ul > li:last-child > a { + padding-bottom: 16px; + } + + #sidebar .main-menu > li.sub-menu.toggled > a:before { + content: "\f0fb"; + -webkit-transform: scale(0) rotate(-90deg); + -ms-transform: scale(0) rotate(-90deg); + -o-transform: scale(0) rotate(-90deg); + transform: scale(0) rotate(-90deg); + } + + #sidebar .main-menu > li.sub-menu.toggled > a:after { + content: "\f111"; + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + + #sidebar .main-menu > li.sub-menu.active > ul { + display: block; + } + + #sidebar .main-menu > li.active > a { + color: #262626; + background-color: #F4F4F4; + } + +/* + * Full width layout + */ + +body:not(.sw-toggled) #sidebar { + box-shadow: 0 0 10px rgba(51, 51, 51, 0.38); +} + +@media (min-width: 1200px) { + body .sw-toggled #sidebar { + -webkit-transform: translate3d(0, 0, 0) !important; + transform: translate3d(0, 0, 0) !important; + opacity: 1 !important; + filter: alpha(opacity=100) !important; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + } +} + +@media (max-width: 1200px) { + body .sw-toggled #sidebar { + box-shadow: 0 0 10px rgba(51, 51, 51, 0.38); + } +} + +/* + * For Stupid IE9 + */ + +@media (min-width: 1200px) { + .ie9 body .sw-toggled #sidebar { + display: block; + } +} + +.ie9 body:not(.sw-toggled) #sidebar:not(.toggled) { + display: none; +} + +input:active, +input:focus { + outline: 0; + box-shadow: none !important; +} + +.form-control { + box-shadow: none; + border: 0; + border-bottom: 1px solid #e0e0e0; +} + + .form-control:active, + .form-control:focus { + border-bottom-color: #b4b4b4; + } + +.dropdown-menu { + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + margin-top: 1px; +} + + .dropdown-menu > li > a { + padding: 8px 17px; + -webkit-transition: background-color; + -o-transition: background-color; + transition: background-color; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + font-family: roboto; + } + + .dropdown-menu.dropdown-menu-lg { + width: 300px; + } + + .dropdown-menu.dropdown-menu-sm { + width: 150px; + } + + .dropdown-menu.dropdown-menu-right { + right: 0; + left: auto; + } + + .dropdown-menu.dropdown-menu-right > li > a { + } + + .dropdown-menu.dm-icon > li > a > .md { + line-height: 100%; + vertical-align: top; + font-size: 18px; + width: 28px; + } + + .dropdown-menu:not([class*="bgm-"]) > li > a { + color: #4C4C4C; + } + + .dropdown-menu:not([class*="bgm-"]) > li > a:hover { + color: #000; + } + + .dropdown-menu[class*="bgm-"] > li > a { + font-weight: 300; + color: #fff; + } + +.dropdown:not([data-animation]) .dropdown-menu, +.btn-group:not([data-animation]) .dropdown-menu { + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + opacity: 0; + filter: alpha(opacity=0); + display: block; +} + +.dropdown .dropdown-menu:not([data-animation]).pull-right, +.bootstrap-select .dropdown-menu:not([data-animation]).pull-right, +.btn-group .dropdown-menu:not([data-animation]).pull-right, +.dropdown .dropdown-menu:not([data-animation]).dropdown-menu-right, +.bootstrap-select .dropdown-menu:not([data-animation]).dropdown-menu-right, +.btn-group .dropdown-menu:not([data-animation]).dropdown-menu-right { + -webkit-transform-origin: top right; + -moz-transform-origin: top right; + -ms-transform-origin: top right; + transform-origin: top right; +} + +.dropdown .dropdown-menu:not([data-animation]):not(.pull-right):not(.dropdown-menu-right), +.bootstrap-select .dropdown-menu:not([data-animation]):not(.pull-right):not(.dropdown-menu-right), +.btn-group .dropdown-menu:not([data-animation]):not(.pull-right):not(.dropdown-menu-right) { + -webkit-transform-origin: top left; + -moz-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; +} + +.dropup .dropdown-menu:not([data-animation]).pull-right, +.dropup .dropdown-menu:not([data-animation]).dropdown-menu-right { + -webkit-transform-origin: bottom right; + -moz-transform-origin: bottom right; + -ms-transform-origin: bottom right; + transform-origin: bottom right; +} + +.dropup .dropdown-menu:not([data-animation]):not(.pull-right):not(.dropdown-menu-right) { + -webkit-transform-origin: bottom left; + -moz-transform-origin: bottom left; + -ms-transform-origin: bottom left; + transform-origin: bottom left; +} + +.dropdown.open .dropdown-menu:not([data-animation]), +.dropup.open .dropdown-menu:not([data-animation]), +.bootstrap-select.open .dropdown-menu:not([data-animation]), +.btn-group.open .dropdown-menu:not([data-animation]) { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + opacity: 1; + filter: alpha(opacity=100); +} + +.dropdown-header { + padding: 3px 17px; + margin-top: 10px; + color: #b1b1b1; + text-transform: uppercase; + font-weight: normal; +} + +.btn-group.open .dropdown-toggle { + box-shadow: none; +} + +.listview { + position: relative; +} + + .listview:not(.lv-lg):not(.lv-message) .lv-item { + padding: 10px 15px; + } + +@media (min-width: 480px) { + .listview.lv-lg .lv-item { + padding: 17px 35px 17px 25px; + } +} + +@media (max-width: 767px) { + .listview.lv-lg .lv-item { + padding: 17px 35px 17px 20px; + } +} + +.listview.lv-lg .lv-item:hover { + background-color: #FFFFDB; +} + +.listview .lv-item { + position: relative; + display: block; + -webkit-transition: background-color; + -o-transition: background-color; + transition: background-color; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; +} + + .listview .lv-item .lv-small { + font-size: 12px; + color: #A9A9A9; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: block; + width: 100%; + } + + .listview .lv-item .checkbox, + .listview .lv-item.media { + margin: 0; + } + + .listview .lv-item .lv-actions { + position: absolute; + } + +@media (min-width: 480px) { + .listview .lv-item .lv-actions { + right: 15px; + height: 30px; + margin-top: -15px; + top: 50%; + } +} + +@media (max-width: 767px) { + .listview .lv-item .lv-actions { + right: 7px; + top: 10px; + } +} + +.listview .lv-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: block; +} + +.listview a.lv-item:hover { + background: #ECF9FF; +} + +.listview [class*="lv-img"] { + border-radius: 50%; +} + +.listview .lv-img { + width: 50px; + height: 50px; +} + +.listview .lv-img-sm { + width: 35px; + height: 35px; +} + +.listview .lv-header { + text-align: center; + padding: 15px 10px 13px; + line-height: 100%; + text-transform: uppercase; + border-bottom: 1px solid #F0F0F0; + font-weight: 500; + color: #4C4C4C; +} + + .listview .lv-header .actions { + position: absolute; + top: 6px; + right: 8px; + z-index: 10; + } + +.listview .lv-header-alt { + background: #f8f8f8; + padding: 12px; + border-bottom: 1px solid #EEE; +} + + .listview .lv-header-alt:before, + .listview .lv-header-alt:after { + content: " "; + display: table; + } + + .listview .lv-header-alt:after { + clear: both; + } + + .listview .lv-header-alt:before, + .listview .lv-header-alt:after { + content: " "; + display: table; + } + + .listview .lv-header-alt:after { + clear: both; + } + + .listview .lv-header-alt .lv-actions { + z-index: 3; + float: right; + margin-top: 3px; + position: relative; + } + + .listview .lv-header-alt .lv-actions > li > a { + margin: 0 3px; + } + +.listview .lvh-label { + color: #818181; + display: inline-block; + margin: 0; + font-size: 14px; + font-weight: normal; + padding: 0 10px; + line-height: 33px; + vertical-align: middle; +} + +.listview .lv-footer { + display: block; + text-align: center; + padding: 7px 10px 8px; + border-top: 1px solid #F0F0F0; + line-height: 100%; + font-size: 11px; + margin-top: 20px; + color: #828282; +} + +.listview a.lv-footer:hover { + color: #050505; +} + +.listview.lv-bordered .lv-item:not(:last-child) { + border-bottom: 1px solid #f0f0f0; +} + +.listview .lv-attrs { + list-style: none; + padding: 0; + margin: 5px 0 0 0; +} + + .listview .lv-attrs > li { + display: inline-block; + padding: 2px 10px 3px; + font-size: 12px; + margin-top: 5px; + margin-right: 2px; + } + + .listview .lv-attrs > li:not(.info):not(.primary):not(.warning):not(.danger) { + border: 1px solid #dedede; + background: #ffffff; + color: #5e5e5e; + } + + .listview .lv-attrs > li.info { + border: 1px solid #00bcd4; + background: #00bcd4; + color: #ffffff; + } + + .listview .lv-attrs > li.primary { + border: 1px solid #2196f3; + background: #2196f3; + color: #ffffff; + } + + .listview .lv-attrs > li.warning { + border: 1px solid #ff9800; + background: #ff9800; + color: #ffffff; + } + + .listview .lv-attrs > li.danger { + border: 1px solid #f44336; + background: #f44336; + color: #ffffff; + } + + .listview .lv-attrs > li > a { + display: block; + } + +.listview:not(.lv-message) .lv-title { + color: #000; +} + +/* + * Inside Card will have more padding + */ + +.card-body .lv-item { + padding: 12px 20px; +} + +.progress { + box-shadow: none; + border-radius: 0; + height: 5px; + margin-bottom: 0; +} + + .progress .progress-bar { + box-shadow: none; + } + +#action-center { + position: fixed; + background: #fff; + padding: 20px 0; + width: 260px; + box-shadow: 0 0 10px rgba(51, 51, 51, 0.38); + height: calc(100% - 65px); + right: -280px; + top: 65px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + z-index: 5; + opacity: 0; + filter: alpha(opacity=0); +} + + #action-center.toggled { + right: 0; + opacity: 1; + filter: alpha(opacity=100); + } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { +} + +/* + * Chat Status Icons + */ + +[class*="chat-status"] { + position: absolute; + width: 10px; + height: 10px; + border-radius: 50%; + top: -3px; + right: 12px; + border: 2px solid #FFF; +} + +/* Simple Mixin */ + +.chat-status-online { + box-shadow: 0 0 0 1px #1ec01e; + background: #1ec01e; +} + +.chat-status-offline { + box-shadow: 0 0 0 1px #e73f3f; + background: #e73f3f; +} + +.chat-status-busy { + box-shadow: 0 0 0 1px #ffa500; + background: #ffa500; +} + +/* + * For Stupid IE9 + */ + +.ie9 #action-center { + right: 0; +} + + .ie9 #action-center:not(.toggled) { + display: none; + } + +.nav-tabs { + list-style: none; + padding: 0; + white-space: nowrap; + margin: 0; + overflow: hidden; + box-shadow: inset 0 -2px 0 0 #eeeeee; +} + + .nav-tabs > li { + display: inline-block; + vertical-align: top; + } + + .nav-tabs > li > a { + display: inline-block; + color: #7a7a7a; + text-transform: uppercase; + position: relative; + width: 100%; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + font-weight: 500; + } + + .nav-tabs > li > a:after { + content: ""; + height: 2px; + position: absolute; + width: 100%; + left: 0; + bottom: 0; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + } + +@media (min-width: 768px) { + .nav-tabs > li > a { + padding: 15px; + } +} + +@media (max-width: 768px) { + .nav-tabs > li > a { + padding: 15px 8px; + } +} + +.nav-tabs > li.active > a { + color: #000; +} + + .nav-tabs > li.active > a:after { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + +.nav-tabs.nav-tabs-right { + text-align: right; +} + +.nav-tabs.tn-justified > li { + display: table-cell; + width: 1%; + text-align: center; +} + +.nav-tabs.tn-icon > li .md { + font-size: 22px; + line-height: 100%; + min-height: 25px; +} + +.nav-tabs:not([data-tab-color]) > li > a:after { + background: #2196f3; +} + +.nav-tabs[data-tab-color="green"] > li > a:after { + background: #4caf50; +} + +.nav-tabs[data-tab-color="red"] > li > a:after { + background: #f44336; +} + +.nav-tabs[data-tab-color="teal"] > li > a:after { + background: #009688; +} + +.nav-tabs[data-tab-color="amber"] > li > a:after { + background: #ffc107; +} + +.nav-tabs[data-tab-color="black"] > li > a:after { + background: #000000; +} + +.nav-tabs[data-tab-color="cyan"] > li > a:after { + background: #00bcd4; +} + +.tab-content { + padding: 20px 0; +} + +.card { + position: relative; + background: #fff; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + margin-bottom: 30px; +} + + .card .card-header { + position: relative; + } + +@media screen and (min-width: 768px) { + .card .card-header:not(.ch-alt) { + padding: 23px 26px; + } +} + +@media screen and (max-width: 991px) { + .card .card-header:not(.ch-alt) { + padding: 18px; + } +} + +.card .card-header h2 { + margin: 0; + line-height: 100%; + font-size: 17px; + font-weight: 400; +} + + .card .card-header h2 small { + display: block; + margin-top: 8px; + color: #AEAEAE; + line-height: 160%; + } + +@media screen and (min-width: 768px) { + .card .card-header.ch-alt { + padding: 23px 26px; + } +} + +@media screen and (max-width: 991px) { + .card .card-header.ch-alt { + padding: 18px 18px 28px; + } +} + +.card .card-header.ch-alt:not([class*="bgm-"]) { + background-color: #f7f7f7; +} + +.card .card-header[class*="bgm-"] h2, +.card .card-header[class*="bgm-"] h2 small { + color: #fff; +} + +.card .card-header .actions { + position: absolute; + right: 10px; + z-index: 2; + top: 15px; +} + +.card .card-header .btn-float { + right: 25px; + bottom: -23px; + z-index: 1; +} + +@media screen and (min-width: 768px) { + .card .card-body.card-padding { + padding: 23px 26px; + } +} + +@media screen and (max-width: 991px) { + .card .card-body.card-padding { + padding: 18px; + } +} + +.card .card-body.card-padding-sm { + padding: 15px; +} + +.chart-edge { + margin: 20px -8px 0 -10px; + overflow: hidden; +} + + .chart-edge .flot-chart { + bottom: -14px; + } + +.charts-row { + margin-top: 50px; + margin-bottom: 20px; +} + +.mini-charts-item { + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + position: relative; + margin-bottom: 30px; +} + + .mini-charts-item .chart { + padding: 15px; + float: left; + } + + .mini-charts-item .chart.chart-pie { + margin: 0 20px; + } + + .mini-charts-item .count { + overflow: hidden; + color: rgba(255, 255, 255, 0.9); + padding: 16px 12px; + } + + .mini-charts-item .count > h2 { + margin: 0; + line-height: 100%; + font-size: 22px; + font-weight: 300; + color: #fff; + } + + .mini-charts-item .count > small { + margin-bottom: 2px; + display: block; + } + + .mini-charts-item .count > h2, + .mini-charts-item .count > small { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .mini-charts-item > .clearfix, + .mini-charts-item > .dl-horizontal dd, + .mini-charts-item > .container, + .mini-charts-item > .container-fluid, + .mini-charts-item > .row, + .mini-charts-item > .form-horizontal .form-group, + .mini-charts-item > .btn-toolbar, + .mini-charts-item > .btn-group-vertical > .btn-group, + .mini-charts-item > .nav, + .mini-charts-item > .navbar, + .mini-charts-item > .navbar-header, + .mini-charts-item > .navbar-collapse, + .mini-charts-item > .pager, + .mini-charts-item > .panel-body, + .mini-charts-item > .modal-footer { + position: relative; + z-index: 1; + } + + .mini-charts-item:before { + -webkit-transition: width; + -o-transition: width; + transition: width; + -webkit-transition-duration: 500ms; + transition-duration: 500ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + content: ""; + width: 113px; + height: 100%; + background: rgba(0, 0, 0, 0.1); + position: absolute; + left: 0; + top: 0; + } + + .mini-charts-item:hover .count { + color: #fff !important; + } + + .mini-charts-item:hover:before { + width: 100%; + } + +/* + * Sparkline Tooltip + */ + +#jqstooltip { + min-width: 21px; + min-height: 23px; + text-align: center; + border: 0; + background: #fff; + box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3); + background-color: #fff; +} + + #jqstooltip .jqsfield { + font-size: 12px; + font-weight: 700; + font-family: inherit; + text-align: center; + color: #333; + } + + #jqstooltip .jqsfield > span { + display: none; + } + +/* + * Easy Pie Charts + */ + +.epc-item { + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + position: relative; + margin-bottom: 30px; + padding: 30px 20px; + text-align: center; +} + +.easy-pie { + display: inline-block; + position: relative; + padding: 0 5px 10px; +} + + .easy-pie .percent { + position: absolute; + font-weight: 300; + width: 100%; + line-height: 100%; + left: 0; + } + + .easy-pie .percent:after { + content: "%"; + } + + .easy-pie.main-pie .percent { + margin-top: 49px; + font-size: 50px; + text-align: center; + } + + .easy-pie.main-pie .percent:not([class*="c-"]) { + color: rgba(255, 255, 255, 0.7); + } + + .easy-pie.main-pie .percent:after { + font-size: 30px; + } + + .easy-pie.main-pie .pie-title { + color: #fff; + } + + .easy-pie:not(.main-pie) .percent { + font-size: 26px; + margin-top: 37px; + } + + .easy-pie:not(.main-pie) .percent:after { + font-size: 20px; + } + + .easy-pie .pie-title { + position: absolute; + width: 100%; + text-align: center; + bottom: -3px; + left: 0; + } + +/* + * Recet Items Table Chart + */ + +#recent-items-chart { + width: calc(100% + 19px); + height: 150px; + margin: -20px -10px 0; + bottom: -10px; +} + +/* + * Flot Chart + */ + +[class*="flot-chart"] { + width: 100%; + display: block; +} + +.flot-chart { + height: 200px; +} + +.flot-chart-pie { + height: 300px; +} + +@media (min-width: 768px) { + .flot-chart-pie { + margin-bottom: 20px; + } +} + +.flot-tooltip, +#flotTip { + position: absolute; + color: #333; + display: none; + font-size: 12px; + box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1); + padding: 3px 10px; + background-color: #fff; + z-index: 99999; +} + +[class*="flc-"] { + text-align: center; + margin: 10px 0 5px; +} + + [class*="flc-"] table { + display: inline-block; + } + + [class*="flc-"] .legendColorBox > div { + border: #fff !important; + } + + [class*="flc-"] .legendColorBox > div > div { + border-radius: 50%; + } + + [class*="flc-"] .legendLabel { + padding: 0 8px 0 3px; + } + +.dash-widget-item { + position: relative; + min-height: 380px; + margin-bottom: 30px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); +} + + .dash-widget-item .dash-widget-header { + position: relative; + } + + .dash-widget-item .dash-widget-header .actions { + display: none; + position: absolute; + right: 4px; + top: 6px; + padding: 0; + list-style: none; + } + + .dash-widget-item .dash-widget-header .actions > li { + display: inline-block; + vertical-align: baseline; + } + + .dash-widget-item .dash-widget-header .actions > li > a { + color: #fff; + font-size: 20px; + } + + .dash-widget-item .dash-widget-footer { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + } + + .dash-widget-item .dash-widget-title { + padding: 12px 20px; + position: absolute; + width: 100%; + left: 0; + font-weight: 300; + } + + .dash-widget-item:hover .dash-widget-header .actions { + display: block; + } + + + + +.btn { + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + border: 0; + text-transform: uppercase; +} + + .btn[class*="bgm-"] { + color: #fff; + } + + .btn:not(.btn-link):not(.btn-float):not(.command-edit):not(.command-delete):not(.selectpicker) { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + } + + .btn:not(.btn-link):not(.btn-float):not(.command-edit):not(.command-delete):not(.selectpicker):hover { + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15); + } + + .btn .caret { + margin-top: -3px; + } + +.btn-group:not(.bootstrap-select), +.btn-group-vertical:not(.bootstrap-select) { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3); +} + +.btn-group .btn, +.btn-group-vertical .btn, +.btn-group .btn:active, +.btn-group-vertical .btn:active, +.btn-group .btn:focus, +.btn-group-vertical .btn:focus, +.btn-group .btn-group, +.btn-group-vertical .btn-group { + box-shadow: none !important; +} + +.btn-group .btn, +.btn-group-vertical .btn { + margin: 0; +} + +.btn-xs, +.btn-group-xs > .btn { + padding: 2px 5px; + font-size: 11px; + line-height: 1.5; + border-radius: 2px; +} + +.btn-link { + color: #797979; + text-decoration: none; + border-radius: 2px; +} + + .btn-link:hover { + color: #0a0a0a; + } + + .btn-link:hover, + .btn-link:active, + .btn-link:focus { + text-decoration: none; + } + +.btn-inverse { + color: #ffffff; + background-color: #454545; + border-color: transparent; +} + + .btn-inverse:hover, + .btn-inverse:focus, + .btn-inverse.focus, + .btn-inverse:active, + .btn-inverse.active, + .open > .dropdown-toggle.btn-inverse { + color: #ffffff; + background-color: #2b2b2b; + border-color: rgba(0, 0, 0, 0); + } + + .btn-inverse:active, + .btn-inverse.active, + .open > .dropdown-toggle.btn-inverse { + background-image: none; + } + + .btn-inverse.disabled, + .btn-inverse[disabled], + fieldset[disabled] .btn-inverse, + .btn-inverse.disabled:hover, + .btn-inverse[disabled]:hover, + fieldset[disabled] .btn-inverse:hover, + .btn-inverse.disabled:focus, + .btn-inverse[disabled]:focus, + fieldset[disabled] .btn-inverse:focus, + .btn-inverse.disabled.focus, + .btn-inverse[disabled].focus, + fieldset[disabled] .btn-inverse.focus, + .btn-inverse.disabled:active, + .btn-inverse[disabled]:active, + fieldset[disabled] .btn-inverse:active, + .btn-inverse.disabled.active, + .btn-inverse[disabled].active, + fieldset[disabled] .btn-inverse.active { + background-color: #454545; + border-color: transparent; + } + + .btn-inverse .badge { + color: #454545; + background-color: #ffffff; + } + + .btn-inverse:hover, + .btn-inverse:focus, + .btn-inverse.focus, + .btn-inverse:active, + .open > .dropdown-toggle.btn-inverse { + color: #ffffff; + background-color: #454545; + border-color: transparent; + } + + .btn-inverse:active, + .btn-inverse.active, + .open > .dropdown-toggle.btn-inverse { + background-image: none; + } + + .btn-inverse.disabled, + .btn-inverse[disabled], + fieldset[disabled] .btn-inverse, + .btn-inverse.disabled:hover, + .btn-inverse[disabled]:hover, + fieldset[disabled] .btn-inverse:hover, + .btn-inverse.disabled:focus, + .btn-inverse[disabled]:focus, + fieldset[disabled] .btn-inverse:focus, + .btn-inverse.disabled.focus, + .btn-inverse[disabled].focus, + fieldset[disabled] .btn-inverse.focus, + .btn-inverse.disabled:active, + .btn-inverse[disabled]:active, + fieldset[disabled] .btn-inverse:active { + background-color: #454545; + border-color: transparent; + } + + .btn-inverse .badge { + color: #454545; + background-color: #ffffff; + } + +.btn-icon { + border-radius: 50%; + width: 40px; + height: 40px; + padding: 0; + text-align: center; + position: relative; +} + + .btn-icon:before { + left: 0; + top: 0; + content: ""; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform: scale3d(0, 0, 0); + -moz-transform: scale3d(0, 0, 0); + -ms-transform: scale3d(0, 0, 0); + -o-transform: scale3d(0, 0, 0); + transform: scale3d(0, 0, 0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + background-color: 50%; + z-index: 0; + border-radius: 300ms; + opacity: 0; + filter: alpha(opacity=0); + } + + .btn-icon:hover:before { + -webkit-transform: scale3d(1, 1, 1); + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -o-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + opacity: 1; + filter: alpha(opacity=100); + } + + .btn-icon .md { + font-size: 17px; + } + + .btn-icon.btn-default:hover { + background: #fff; + } + +.btn-icon-text > .md, +.btn-icon-text > .socicon { + font-size: 15px; + vertical-align: top; + display: inline-block; + margin-top: 1px; + line-height: 100%; + margin-right: 5px; +} + +.btn-float { + width: 50px; + height: 50px; + border-radius: 50%; + position: absolute !important; + line-height: 38px; +} + + .btn-float:hover { + box-shadow: 0 2px 7px rgba(0, 0, 0, 0.18); + } + + .btn-float i { + font-size: 23px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 500ms; + transition-duration: 500ms; + } + + .btn-float:hover i { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } + + .btn-float:not(.bgm-white):not(.bgm-gray) > i { + color: #fff; + } + + .btn-float.bgm-white > i, + .btn-float.bgm-gray > i { + color: #333; + } + +.open .btn { + outline: none !important; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0) !important; +} + + .open .btn:focus, + .open .btn:active { + outline: none !important; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0) !important; + } + +/* + * Checkbox and Radio + */ + +.checkbox label, +.radio label { + padding-left: 30px; + position: relative; +} + +.checkbox input, +.radio input { + top: 0; + left: 0; + margin-left: 0 !important; + z-index: 1; + cursor: pointer; + opacity: 0; + filter: alpha(opacity=0); + margin-top: 0; +} + +.checkbox .input-helper:before, +.radio .input-helper:before, +.checkbox .input-helper:after, +.radio .input-helper:after { + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + position: absolute; + content: ""; +} + +.checkbox .input-helper:before, +.radio .input-helper:before { + left: 0; + border: 1px solid #ccc; +} + +.checkbox.disabled, +.radio.disabled { + opacity: 0.6; + filter: alpha(opacity=60); +} + +.checkbox input { + width: 17px; + height: 17px; +} + + .checkbox input:checked + .input-helper:before { + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + } + + .checkbox input:checked + .input-helper:after { + -webkit-transform: scale(1) rotate(-50deg); + -ms-transform: scale(1) rotate(-50deg); + -o-transform: scale(1) rotate(-50deg); + transform: scale(1) rotate(-50deg); + opacity: 1; + filter: alpha(opacity=100); + } + +.checkbox .input-helper:before { + top: 0; + width: 17px; + height: 17px; +} + +.checkbox .input-helper:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transform: scale(0) rotate(80deg); + -ms-transform: scale(0) rotate(80deg); + -o-transform: scale(0) rotate(80deg); + transform: scale(0) rotate(80deg); + width: 22px; + height: 9px; + border-bottom: 2px solid #009688; + border-left: 2px solid #009688; + border-bottom-left-radius: 2px; + left: -1px; + top: 1px; +} + +.has-error .checkbox .input-helper:before { + border-color: #f99d97; +} + +.has-error .checkbox .input-helper:after { + border-bottom-color: #f77066; + border-left-color: #f77066; +} + +.has-success .checkbox .input-helper:before { + border-color: #92cf94; +} + +.has-success .checkbox .input-helper:after { + border-bottom-color: #6ec071; + border-left-color: #6ec071; +} + +.has-warning .checkbox .input-helper:before { + border-color: #ffdb6d; +} + +.has-warning .checkbox .input-helper:after { + border-bottom-color: #ffce3a; + border-left-color: #ffce3a; +} + +.radio input { + width: 19px; + height: 19px; +} + + .radio input:checked + .input-helper:after { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + +.radio .input-helper:before { + top: -1px; + width: 19px; + height: 19px; + border-radius: 50%; +} + +.radio .input-helper:after { + width: 11px; + height: 11px; + background: #009688; + border-radius: 50%; + top: 3px; + left: 4px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); +} + +.checkbox-inline, +.radio-inline { + vertical-align: top; + margin-top: 0; + padding-left: 25px; +} + +/* + * Select + */ + +html:not(.ie9) .select { + position: relative; +} + + html:not(.ie9) .select:before { + position: absolute; + top: 0; + content: ""; + height: calc(100% - 2px); + width: 30px; + background-color: #FFF; + background-position: right calc(100% - 7px); + background-repeat: no-repeat; + background-image: url("img/select.png"); + pointer-events: none; + z-index: 5; + } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + html:not(.ie9) .select:before { + background-image: url("img/select@2x.png"); + background-size: 12px 12px; + } +} + +html:not(.ie9) .select:not(.fg-line):before { + right: 0; +} + +html:not(.ie9) .select.fg-line:before { + right: 10px; +} + +/* + * Input Group + */ + +.input-group-addon { + border-width: 0px 0px 1px 0px; +} + +/* + * Input Feilds + */ + +.fg-line { + position: relative; + vertical-align: top; + /* Validation Stats */ +} + + .fg-line:not(.form-group) { + display: inline-block; + width: 100%; + } + + .fg-line .form-control { + resize: none; + } + + .fg-line .form-control:not(:disabled) { + color: #000; + } + + .fg-line .form-control:disabled { + color: #9d9d9d; + background: transparent; + } + + .fg-line:not(.disabled):after, + .fg-line:not(.readonly):after { + position: absolute; + z-index: 3; + bottom: 0; + left: 0; + height: 2px; + width: 0; + content: ""; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + .fg-line:not([class*=has-]):after { + background: #2196f3; + } + + .fg-line.input-toggled:after { + width: 100%; + } + + .fg-line.readonly .form-control { + color: #9d9d9d; + background: transparent; + } + + .fg-line.fg-toggled:after { + width: 100%; + } + + .fg-line.has-success:after { + background: #4caf50; + } + + .fg-line.has-warning:after { + background: #ffc107; + } + + .fg-line.has-error:after { + background: #f44336; + } + +/* Validation Stats for inner fg-line*/ + +.has-success .fg-line:after { + background: #4caf50; +} + +.has-warning .fg-line:after { + background: #ffc107; +} + +.has-error .fg-line:after { + background: #f44336; +} + +.fg-float { + margin-top: 2px; + position: relative; +} + + .fg-float .form-control { + position: relative; + background: transparent; + z-index: 1; + } + + .fg-float .form-control::-moz-placeholder { + color: #ffffff; + opacity: 1; + } + + .fg-float .form-control:-ms-input-placeholder { + color: #ffffff; + } + + .fg-float .form-control::-webkit-input-placeholder { + color: #ffffff; + } + + .fg-float .fg-label { + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + position: absolute; + top: 5px; + font-weight: 400; + color: #959595; + pointer-events: none; + z-index: 0; + left: 0; + white-space: nowrap; + } + + .fg-float .input-lg + .fg-label { + font-size: 17px; + } + + .fg-float .input-sm + .fg-label { + font-size: 11px; + } + + .fg-float .fg-toggled + .fg-label { + top: -20px; + font-size: 11px; + } + +.form-control { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0; + border-radius: 0; +} + + .form-control:focus { + box-shadow: none; + } + + .form-control.auto-size { + padding-top: 6px; + } + +.form-group { + margin-bottom: 20px; +} + +/* + * Validation + */ + +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #4caf50; +} + +.has-success .form-control { + border-color: #b5dfb7; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-success .form-control:focus { + border-color: #92cf94; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #fcfefc; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #fcfefc; + } + +.has-success .input-group-addon { + color: #4caf50; + border-color: #b5dfb7; + background-color: #ffffff; +} + +.has-success .form-control-feedback { + color: #4caf50; +} + +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #ff9800; +} + +.has-warning .form-control { + border-color: #ffd699; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-warning .form-control:focus { + border-color: #ffc166; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + } + +.has-warning .input-group-addon { + color: #ff9800; + border-color: #ffd699; + background-color: #ffffff; +} + +.has-warning .form-control-feedback { + color: #ff9800; +} + +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #f44336; +} + +.has-error .form-control { + border-color: #fccbc7; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-error .form-control:focus { + border-color: #f99d97; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + } + +.has-error .input-group-addon { + color: #f44336; + border-color: #fccbc7; + background-color: #ffffff; +} + +.has-error .form-control-feedback { + color: #f44336; +} + +.has-success .form-control, +.has-warning .form-control, +.has-error .form-control { + box-shadow: none; +} + +.form-control-feedback { + font-size: 20px; +} + +.control-label { + font-weight: normal; +} + +/* + * Input Groups + */ + +.input-group { + /* Mixin for Input Group */ +} + + .input-group .input-group-addon { + vertical-align: bottom; + padding: 0; + } + + .input-group .input-group-addon .md { + line-height: 100%; + } + + .input-group:not(.input-group-lg):not(.input-group-sm) .input-group-addon:not(.last) { + padding-right: 10px; + } + + .input-group:not(.input-group-lg):not(.input-group-sm) .input-group-addon.last { + padding-left: 10px; + } + + .input-group:not(.input-group-lg):not(.input-group-sm) .input-group-addon .md { + font-size: 23px; + } + + .input-group.input-group-lg .input-group-addon:not(.last) { + padding-right: 15px; + } + + .input-group.input-group-lg .input-group-addon.last { + padding-left: 15px; + } + + .input-group.input-group-lg .input-group-addon .md { + font-size: 30px; + } + + .input-group.input-group-sm .input-group-addon:not(.last) { + padding-right: 5px; + } + + .input-group.input-group-sm .input-group-addon.last { + padding-left: 5px; + } + + .input-group.input-group-sm .input-group-addon .md { + font-size: 18px; + } + + .input-group > [class*="col-"] { + padding: 0; + } + + .input-group .fg-line { + padding: 0 10px; + } + + .input-group .fg-line:after { + left: 10px; + } + + .input-group .fg-line.fg-toggled:after { + width: calc(100% - 20px); + } + +/* + * Toggle Switch + */ + +.toggle-switch { + display: inline-block; + vertical-align: top; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + + .toggle-switch .ts-label { + display: inline-block; + margin: 0 20px 0 0; + vertical-align: top; + -webkit-transition: color 0.56s cubic-bezier(0.4, 0, 0.2, 1); + transition: color 0.56s cubic-bezier(0.4, 0, 0.2, 1); + } + + .toggle-switch .ts-helper { + display: inline-block; + position: relative; + width: 40px; + height: 16px; + border-radius: 8px; + background: rgba(0, 0, 0, 0.26); + -webkit-transition: background 0.28s cubic-bezier(0.4, 0, 0.2, 1); + transition: background 0.28s cubic-bezier(0.4, 0, 0.2, 1); + vertical-align: middle; + cursor: pointer; + } + + .toggle-switch .ts-helper:before { + content: ''; + position: absolute; + top: -4px; + left: -4px; + width: 24px; + height: 24px; + background: #fafafa; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28); + border-radius: 50%; + webkit-transition: left 0.28s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); + transition: left 0.28s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); + } + + .toggle-switch:not(.disabled) .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(128, 128, 128, 0.1); + } + + .toggle-switch input { + position: absolute; + z-index: 1; + width: 46px; + margin: 0 0 0 -4px; + height: 24px; + opacity: 0; + filter: alpha(opacity=0); + cursor: pointer; + } + + .toggle-switch input:checked + .ts-helper:before { + left: 20px; + } + + .toggle-switch:not([data-ts-color]) input:not(:disabled):checked + .ts-helper { + background: rgba(0, 150, 136, 0.5); + } + + .toggle-switch:not([data-ts-color]) input:not(:disabled):checked + .ts-helper:before { + background: #009688; + } + + .toggle-switch:not([data-ts-color]) input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(0, 150, 136, 0.2); + } + + .toggle-switch.disabled { + opacity: 0.6; + filter: alpha(opacity=60); + } + + .toggle-switch[data-ts-color="red"] input:not(:disabled):checked + .ts-helper { + background: rgba(244, 67, 54, 0.5); + } + + .toggle-switch[data-ts-color="red"] input:not(:disabled):checked + .ts-helper:before { + background: #f44336; + } + + .toggle-switch[data-ts-color="red"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(244, 67, 54, 0.2); + } + + .toggle-switch[data-ts-color="blue"] input:not(:disabled):checked + .ts-helper { + background: rgba(33, 150, 243, 0.5); + } + + .toggle-switch[data-ts-color="blue"] input:not(:disabled):checked + .ts-helper:before { + background: #2196f3; + } + + .toggle-switch[data-ts-color="blue"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(33, 150, 243, 0.2); + } + + .toggle-switch[data-ts-color="amber"] input:not(:disabled):checked + .ts-helper { + background: rgba(255, 193, 7, 0.5); + } + + .toggle-switch[data-ts-color="amber"] input:not(:disabled):checked + .ts-helper:before { + background: #ffc107; + } + + .toggle-switch[data-ts-color="amber"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(255, 193, 7, 0.2); + } + + .toggle-switch[data-ts-color="purple"] input:not(:disabled):checked + .ts-helper { + background: rgba(156, 39, 176, 0.5); + } + + .toggle-switch[data-ts-color="purple"] input:not(:disabled):checked + .ts-helper:before { + background: #9c27b0; + } + + .toggle-switch[data-ts-color="purple"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(156, 39, 176, 0.2); + } + + .toggle-switch[data-ts-color="pink"] input:not(:disabled):checked + .ts-helper { + background: rgba(233, 30, 99, 0.5); + } + + .toggle-switch[data-ts-color="pink"] input:not(:disabled):checked + .ts-helper:before { + background: #e91e63; + } + + .toggle-switch[data-ts-color="pink"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(233, 30, 99, 0.2); + } + + .toggle-switch[data-ts-color="lime"] input:not(:disabled):checked + .ts-helper { + background: rgba(205, 220, 57, 0.5); + } + + .toggle-switch[data-ts-color="lime"] input:not(:disabled):checked + .ts-helper:before { + background: #cddc39; + } + + .toggle-switch[data-ts-color="lime"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(205, 220, 57, 0.2); + } + + .toggle-switch[data-ts-color="cyan"] input:not(:disabled):checked + .ts-helper { + background: rgba(0, 188, 212, 0.5); + } + + .toggle-switch[data-ts-color="cyan"] input:not(:disabled):checked + .ts-helper:before { + background: #00bcd4; + } + + .toggle-switch[data-ts-color="cyan"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(0, 188, 212, 0.2); + } + + .toggle-switch[data-ts-color="green"] input:not(:disabled):checked + .ts-helper { + background: rgba(76, 175, 80, 0.5); + } + + .toggle-switch[data-ts-color="green"] input:not(:disabled):checked + .ts-helper:before { + background: #4caf50; + } + + .toggle-switch[data-ts-color="green"] input:not(:disabled):checked + .ts-helper:active:before { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), 0 0 0 20px rgba(76, 175, 80, 0.2); + } + +.pagination { + border-radius: 0; +} + + .pagination > li { + margin: 0 2px; + display: inline-block; + vertical-align: top; + } + + .pagination > li > a, + .pagination > li > span { + border-radius: 50% !important; + padding: 0; + width: 40px; + height: 40px; + line-height: 38px; + text-align: center; + font-size: 14px; + z-index: 1; + position: relative; + } + + .pagination > li > a > .md, + .pagination > li > span > .md { + font-size: 22px; + } + + .pagination > li > a:before, + .pagination > li > span:before { + left: 0; + top: 0; + content: ""; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform: scale3d(0, 0, 0); + -moz-transform: scale3d(0, 0, 0); + -ms-transform: scale3d(0, 0, 0); + -o-transform: scale3d(0, 0, 0); + transform: scale3d(0, 0, 0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + background-color: rgba(0, 0, 0, 0.1); + z-index: 0; + border-radius: 50%; + opacity: 0; + filter: alpha(opacity=0); + } + + .pagination > li > a:hover:before, + .pagination > li > span:hover:before { + -webkit-transform: scale3d(1, 1, 1); + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -o-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + opacity: 1; + filter: alpha(opacity=100); + } + + .pagination > li.disabled { + opacity: 0.5; + filter: alpha(opacity=50); + } + +/* + * Listview Pagination + */ + +.lv-pagination { + width: 100%; + text-align: center; + padding: 40px 0; + border-top: 1px solid #F0F0F0; + margin-top: 0; + margin-bottom: 0; +} + +.popover { + box-shadow: 0 2px 30px rgba(0, 0, 0, 0.2); +} + +.popover-title { + border-bottom: 0; + padding: 15px; + font-size: 12px; + text-transform: uppercase; +} + +.popover-content { + padding: 0 15px 15px; +} + + .popover-content p { + margin-bottom: 0; + } + +.fw-container .tab-content { + padding: 25px 0; +} + +.fw-container .fw-footer { + text-align: center; + margin: 30px 0 0; + width: 100%; + border-top: 2px solid #eee; + padding: 15px 0; +} + +.alert { + padding-left: 30px; + font-size: 13px; +} + + .alert span { + cursor: pointer; + } + + .alert:not(.alert-dismissible) { + padding-right: 30px; + } + + .alert.alert-dismissable { + padding-right: 44px; + } + +.alert-inverse { + background: rgba(51, 51, 51, 0.9); + box-shadow: 0 0 5px rgba(51, 51, 51, 0.5); + color: #fff; +} + + .alert-inverse a { + color: #fff; + } + +.growl-animated { + border: 0; + color: #fff; +} + + .growl-animated.alert-info { + background: rgba(33, 150, 243, 0.8); + box-shadow: 0 0 5px rgba(33, 150, 243, 0.5); + } + + .growl-animated.alert-success { + background: rgba(76, 175, 80, 0.8); + box-shadow: 0 0 5px rgba(76, 175, 80, 0.5); + } + + .growl-animated.alert-warning { + background: rgba(255, 152, 0, 0.8); + box-shadow: 0 0 5px rgba(255, 152, 0, 0.5); + } + + .growl-animated.alert-danger { + background: rgba(244, 67, 54, 0.8); + box-shadow: 0 0 5px rgba(244, 67, 54, 0.5); + } + +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #e0e0e0; + box-shadow: 0 0 6px #EAEAEA; +} + +/* + * Lightbox + */ + +.lightbox .lightbox-item { + position: relative; +} + + .lightbox .lightbox-item > img { + width: 100%; + } + + .lightbox .lightbox-item:before { + left: 0; + top: 0; + content: ""; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform: scale3d(0, 0, 0); + -moz-transform: scale3d(0, 0, 0); + -ms-transform: scale3d(0, 0, 0); + -o-transform: scale3d(0, 0, 0); + transform: scale3d(0, 0, 0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + background-color: rgba(0, 0, 0, 0.1); + z-index: 0; + border-radius: 0; + opacity: 0; + filter: alpha(opacity=0); + } + + .lightbox .lightbox-item:hover:before { + -webkit-transform: scale3d(1, 1, 1); + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -o-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + opacity: 1; + filter: alpha(opacity=100); + } + + .lightbox .lightbox-item:hover { + cursor: pointer; + } + +.lightbox [data-src]:before, +.lightbox [data-src]:after { + content: " "; + display: table; +} + +.lightbox [data-src]:after { + clear: both; +} + +.lightbox [data-src]:before, +.lightbox [data-src]:after { + content: " "; + display: table; +} + +.lightbox [data-src]:after { + clear: both; +} + +.lightbox .lightbox-item:not(.p-item) { + position: relative; +} + +/* + * Carousel + */ + +.carousel .carousel-control { + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + opacity: 0; + filter: alpha(opacity=0); +} + + .carousel .carousel-control .md { + position: absolute; + top: 50%; + left: 50%; + line-height: 100%; + } + +@media screen and (min-width: 768px) { + .carousel .carousel-control .md { + font-size: 60px; + width: 60px; + height: 60px; + margin-top: -30px; + margin-left: -30px; + } +} + +@media screen and (max-width: 991px) { + .carousel .carousel-control .md { + width: 24px; + height: 24px; + margin-top: -12px; + margin-left: -12px; + } +} + +.carousel:hover .carousel-control { + opacity: 1; + filter: alpha(opacity=100); +} + +.carousel .carousel-caption { + background: rgba(0, 0, 0, 0.6); + left: 0; + right: 0; + bottom: 0; + width: 100%; + padding-bottom: 50px; +} + + .carousel .carousel-caption > h3 { + color: #fff; + margin: 0 0 5px; + font-weight: 300; + } + + .carousel .carousel-caption > p { + margin: 0; + } + +@media screen and (max-width: 991px) { + .carousel .carousel-caption { + display: none; + } +} + +.carousel .carousel-indicators { + bottom: 10px; + margin: 0; + left: 0; + bottom: 0; + width: 100%; + padding: 0 0 6px; + background: rgba(0, 0, 0, 0.6); +} + + .carousel .carousel-indicators li { + border-radius: 0; + width: 15px; + border: 0; + background: #fff; + height: 3px; + margin: 0; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + } + + .carousel .carousel-indicators li.active { + width: 25px; + height: 3px; + background: #ff9800; + } + +.modal .modal-content { + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.31); + border-radius: 3px; + border: 0; +} + +.modal .modal-header { + padding: 23px 26px; +} + +.modal .modal-body { + padding: 0 26px 10px; +} + +.modal .modal-footer .btn-link { + font-size: 14px; + color: #000; + font-weight: 500; +} + + .modal .modal-footer .btn-link:hover { + background-color: #eee; + } + +.modal:not([data-modal-color]) .modal-footer .btn-link { + font-weight: 500; +} + + .modal:not([data-modal-color]) .modal-footer .btn-link:hover { + background-color: #eee; + } + +.modal[data-modal-color] { + color: #fff; +} + + .modal[data-modal-color] .modal-title, + .modal[data-modal-color] .modal-footer .btn-link { + color: #fff; + } + + .modal[data-modal-color] .modal-footer { + background: rgba(0, 0, 0, 0.1); + } + + .modal[data-modal-color] .modal-backdrop { + background: #fff; + } + + .modal[data-modal-color] .modal-footer .btn-link { + font-weight: 400; + } + + .modal[data-modal-color] .modal-footer .btn-link:hover { + background-color: rgba(0, 0, 0, 0.1); + } + +.modal[data-modal-color="blue"] .modal-content { + background: #2196f3; +} + +.modal[data-modal-color="cyan"] .modal-content { + background: #00bcd4; +} + +.modal[data-modal-color="green"] .modal-content { + background: #4caf50; +} + +.modal[data-modal-color="lightgreen"] .modal-content { + background: #8bc34a; +} + +.modal[data-modal-color="lightblue"] .modal-content { + background: #03a9f4; +} + +.modal[data-modal-color="amber"] .modal-content { + background: #ffc107; +} + +.modal[data-modal-color="teal"] .modal-content { + background: #009688; +} + +.modal[data-modal-color="orange"] .modal-content { + background: #ff9800; +} + +.modal[data-modal-color="bluegray"] .modal-content { + background: #607d8b; +} + +.modal[data-modal-color="red"] .modal-content { + background: #f44336; +} + +.modal-backdrop { + z-index: 10; +} + +.panel { + box-shadow: none; + border: 0; +} + +.panel-heading { + padding: 0; +} + +.panel-title > a { + padding: 10px 15px; + display: block; + font-size: 13px; +} + +.panel-collapse .panel-heading { + position: relative; +} + + .panel-collapse .panel-heading .panel-title > a { + padding: 8px 5px 16px 30px; + color: #000; + position: relative; + } + + .panel-collapse .panel-heading .panel-title > a:after, + .panel-collapse .panel-heading .panel-title > a:before { + position: absolute; + bottom: 0; + left: 0; + height: 2px; + width: 100%; + content: ""; + } + + .panel-collapse .panel-heading .panel-title > a:after { + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + } + + .panel-collapse .panel-heading:not(.active) .panel-title > a:before { + background: #eee; + } + + .panel-collapse .panel-heading:before, + .panel-collapse .panel-heading:after { + font-family: 'Material Design Iconic Font'; + font-size: 17px; + position: absolute; + left: 0; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + top: 4px; + } + + .panel-collapse .panel-heading:before { + content: "\f0fb"; + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + + .panel-collapse .panel-heading:after { + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + content: "\f111"; + } + + .panel-collapse .panel-heading.active .panel-title > a:after { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + + .panel-collapse .panel-heading.active:before { + -webkit-transform: scale(0) rotate(-90deg); + -ms-transform: scale(0) rotate(-90deg); + -o-transform: scale(0) rotate(-90deg); + transform: scale(0) rotate(-90deg); + } + + .panel-collapse .panel-heading.active:after { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + +.panel-collapse .panel-body { + border-top: 0 !important; + padding-left: 5px; + padding-right: 5px; +} + +.panel-group:not([data-collapse-color]) .panel-collapse .panel-heading.active .panel-title > a:after { + background: #2196f3; +} + +.panel-group[data-collapse-color="red"] .panel-collapse .panel-heading.active .panel-title > a:after { + background: #f44336; +} + +.panel-group[data-collapse-color="green"] .panel-collapse .panel-heading.active .panel-title > a:after { + background: #4caf50; +} + +.panel-group[data-collapse-color="amber"] .panel-collapse .panel-heading.active .panel-title > a:after { + background: #ffc107; +} + +.panel-group[data-collapse-color="teal"] .panel-collapse .panel-heading.active .panel-title > a:after { + background: #009688; +} + +.panel-group[data-collapse-color="black"] .panel-collapse .panel-heading.active .panel-title > a:after { + background: #000000; +} + +.panel-group[data-collapse-color="cyan"] .panel-collapse .panel-heading.active .panel-title > a:after { + background: #00bcd4; +} + +.tooltip-inner { + border-radius: 1px; + padding: 3px 10px 5px; +} + +.breadcrumb { + border-bottom: 1px solid #E5E5E5; + border-radius: 0; +} + + .breadcrumb > li > a { + color: #A9A9A9; + } + + .breadcrumb > li > a:hover { + color: #7c7c7c; + } + +@media (min-width: 768px) { + body:not(.sw-toggled) .breadcrumb { + padding: 10px 33px 11px; + } +} + +@media (min-width: 1199px) { + body .sw-toggled .breadcrumb { + padding: 10px 33px 11px 280px; + } +} + +#messages-main { + position: relative; +} + + #messages-main:before, + #messages-main:after { + content: " "; + display: table; + } + + #messages-main:after { + clear: both; + } + + #messages-main:before, + #messages-main:after { + content: " "; + display: table; + } + + #messages-main:after { + clear: both; + } + + #messages-main .ms-block { + padding: 23px 20px 0; + } + + #messages-main .ms-menu { + position: absolute; + left: 0; + top: 0; + background: #F8F8F8; + border-right: 1px solid #EEE; + padding-bottom: 50px; + height: 100%; + width: 240px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + } + +@media (max-width: 767px) { + #messages-main .ms-menu { + height: calc(100% - 58px); + -webkit-transform: translate3d(-240px, 58px, 0); + transform: translate3d(-240px, 58px, 0); + opacity: 0; + filter: alpha(opacity=0); + z-index: 1; + } + + #messages-main .ms-menu.toggled { + -webkit-transform: translate3d(0, 58px, 0); + transform: translate3d(0, 58px, 0); + opacity: 1; + filter: alpha(opacity=100); + } +} + +#messages-main .ms-menu .lv-item { + padding-left: 20px; + padding-right: 20px; +} + + #messages-main .ms-menu .lv-item.active { + background: #fff; + } + + #messages-main .ms-menu .lv-item:not(.active):hover { + background: #F2F2F2; + cursor: pointer; + } + +@media (min-width: 768px) { + #messages-main .ms-body { + padding-left: 240px; + } +} + +@media (max-width: 767px) { + #messages-main .ms-body { + overflow: hidden; + } +} + +#messages-main .ms-user:before, +#messages-main .ms-user:after { + content: " "; + display: table; +} + +#messages-main .ms-user:after { + clear: both; +} + +#messages-main .ms-user:before, +#messages-main .ms-user:after { + content: " "; + display: table; +} + +#messages-main .ms-user:after { + clear: both; +} + +#messages-main .ms-user > img { + border-radius: 50%; + width: 40px; + float: left; +} + +#messages-main .ms-user > div { + overflow: hidden; + padding: 7px 5px 7px 15px; + font-size: 11px; +} + +#messages-main #ms-compose { + position: fixed; + bottom: 120px; + z-index: 1; + right: 30px; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28); +} + +#ms-menu-trigger { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + float: left; + margin: 1px 0 0 -7px; +} + +@media (min-width: 768px) { + #ms-menu-trigger { + display: none; + } +} + +#ms-menu-trigger .line-wrap .line { + background-color: #717171; +} + +/* + * For Message + */ + +.lv-message .lv-item { + padding: 20px; +} + + .lv-message .lv-item.right { + text-align: right; + } + + .lv-message .lv-item.right .lv-avatar { + margin-right: 0; + margin-left: 15px; + } + + .lv-message .lv-item:not(.right) .ms-item { + background: #ffc107; + color: #fff; + } + + .lv-message .lv-item.right .ms-item { + background: #eee; + } + +.lv-avatar { + width: 35px; + height: 35px; + border-radius: 50%; + color: #FFF; + text-align: center; + line-height: 34px; + font-size: 15px; + margin-right: 15px; + padding: 0 !important; + text-transform: uppercase; +} + + .lv-avatar > img { + width: 35px; + height: 35px; + border-radius: 50%; + vertical-align: top; + } + +.ms-item { + padding: 13px 19px 15px; + border-radius: 2px; + display: inline-block; +} + +@media (min-width: 768px) { + .ms-item { + max-width: 70%; + } +} + +.ms-date { + display: block; + color: #B3B3B3; + margin-top: 7px; +} + + .ms-date > i { + font-size: 14px; + vertical-align: bottom; + line-height: 100%; + } + +.ms-reply { + box-shadow: 0 -20px 20px -5px #ffffff; + position: relative; + margin: 0 !important; +} + + .ms-reply textarea { + width: 100%; + font-size: 13px; + border: 0; + padding: 10px 8px; + resize: none; + height: 60px; + } + + .ms-reply button { + position: absolute; + top: 0; + right: 0; + border: 0; + height: 100%; + width: 60px; + font-size: 25px; + background: #F5F5F5; + color: #2196f3; + } + + .ms-reply button:hover { + background: #f2f2f2; + } + +.four-zero-content { + background: #fff; + padding: 20px; +} + + .four-zero-content:before { + height: 50%; + width: 100%; + position: absolute; + top: 0; + left: 0; + background: #EDECEC; + content: ""; + } + +.four-zero { + background: #00bcd4; + box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27); + border-radius: 2px; + position: absolute; + top: 50%; + margin-top: -150px; + color: #fff; + text-align: center; + padding: 15px; + height: 300px; + width: 500px; + left: 50%; + margin-left: -250px; +} + + .four-zero h2 { + font-size: 130px; + } + +@media (max-width: 767px) { + .four-zero { + width: calc(100% - 40px); + left: 20px; + margin-left: 0; + height: 260px; + margin-top: -130px; + } + + .four-zero h2 { + font-size: 90px; + } +} + +.four-zero h2 { + line-height: 100%; + color: #fff; + font-weight: 100; +} + +.four-zero small { + display: block; + font-size: 26px; + margin-top: -10px; +} + +.four-zero footer { + background: rgba(0, 0, 0, 0.13); + position: absolute; + left: 0; + bottom: 0; + width: 100%; + padding: 10px; +} + + .four-zero footer > a { + font-size: 21px; + display: inline-block; + color: #FFF; + margin: 0 1px; + line-height: 40px; + width: 40px; + height: 40px; + background: rgba(0, 0, 0, 0.09); + border-radius: 50%; + text-align: center; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + .four-zero footer > a:hover { + background: rgba(0, 0, 0, 0.2); + } + +.login-content { + overflow: hidden; + height: 100%; +} + + .login-content .lc-block { + background: #fff; + box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27); + border-radius: 2px; + padding: 35px 55px 35px; + width: 500px; + display: inline-block; + margin-top: -60px; + vertical-align: middle; + position: relative; + } + +@media (max-width: 767px) { + .login-content .lc-block { + padding: 15px 35px 25px 20px; + width: calc(100% - 60px); + } +} + +.login-content .lc-block .checkbox { + margin: 5px 0 0 42px; + text-align: left; +} + +.login-content .lc-block .btn-login { + position: fixed; + top: 50%; + margin-top: -25px; + right: -25px; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28); +} + +.login-content .lc-block:not(.toggled) { + display: none; +} + +.login-content .lc-block.toggled { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; + -webkit-animation-duration: 200ms; + animation-duration: 200ms; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + z-index: 10; +} + +.login-content .login-navigation { + list-style: none; + padding: 0; + margin: 0; + position: absolute; + width: 100%; + text-align: center; + left: 0%; + bottom: -45px; +} + + .login-content .login-navigation > li { + display: inline-block; + margin: 0 2px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 150ms; + transition-duration: 150ms; + cursor: pointer; + vertical-align: top; + color: #fff; + line-height: 16px; + min-width: 16px; + min-height: 16px; + text-transform: uppercase; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + } + + .login-content .login-navigation > li > span { + opacity: 0; + filter: alpha(opacity=0); + } + + .login-content .login-navigation > li:not(:hover) { + font-size: 0px; + border-radius: 100%; + } + + .login-content .login-navigation > li:hover { + border-radius: 10px; + padding: 0 5px; + font-size: 8px; + } + + .login-content .login-navigation > li:hover > span { + opacity: 1; + filter: alpha(opacity=100); + } + +body .login-content { + text-align: center; +} + + body .login-content:after { + content: ""; + vertical-align: middle; + display: inline-block; + width: 1px; + height: 100%; + } + + body .login-content:before { + height: 50%; + width: 100%; + position: absolute; + top: 0; + left: 0; + background: #00bcd4; + content: ""; + z-index: 0; + } + +#profile-main { + min-height: 500px; + position: relative; +} + + #profile-main .pm-overview { + overflow-y: auto; + } + +@media (min-width: 1200px) { + #profile-main .pm-overview { + width: 300px; + } +} + +@media (min-width: 768px) and (max-width: 1200px) { + #profile-main .pm-overview { + width: 250px; + } +} + +@media (min-width: 768px) { + #profile-main .pm-overview { + position: absolute; + left: 0; + top: 0; + height: 100%; + background: #f8f8f8; + border-right: 1px solid #eee; + } +} + +@media (max-width: 767px) { + #profile-main .pm-overview { + width: 100%; + background: #333; + text-align: center; + } +} + +@media (min-width: 1200px) { + #profile-main .pm-body { + padding-left: 300px; + } +} + +@media (min-width: 768px) and (max-width: 1200px) { + #profile-main .pm-body { + padding-left: 250px; + } +} + +@media (max-width: 767px) { + #profile-main .pm-body { + padding-left: 0; + } +} + +#profile-main .pmo-pic { + position: relative; + margin: 20px; +} + +@media (min-width: 768px) { + #profile-main .pmo-pic img { + width: 100%; + border-radius: 2px 2px 0 0; + } +} + +@media (max-width: 767px) { + #profile-main .pmo-pic img { + width: 180px; + display: inline-block; + height: 180px; + border-radius: 50%; + border: 4px solid #fff; + box-shadow: 0 8px 17px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19); + } +} + +#profile-main .pmo-pic .pmo-stat { + border-radius: 0 0 2px 2px; + color: #fff; + text-align: center; + padding: 30px 5px 0; +} + +@media (min-width: 768px) { + #profile-main .pmo-pic .pmo-stat { + background: #ffc107; + padding-bottom: 15px; + } +} + +#profile-main .pmo-pic .pmop-edit { + position: absolute; + top: 0; + left: 0; + color: #fff; + background: rgba(0, 0, 0, 0.38); + text-align: center; + padding: 10px 10px 7px; + -webkit-transition: opacity; + -o-transition: opacity; + transition: opacity; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; +} + + #profile-main .pmo-pic .pmop-edit:hover { + background: rgba(0, 0, 0, 0.8); + } + + #profile-main .pmo-pic .pmop-edit i { + font-size: 18px; + vertical-align: middle; + margin-top: -3px; + } + +@media (min-width: 768px) { + #profile-main .pmo-pic .pmop-edit { + width: 100%; + opacity: 0; + filter: alpha(opacity=0); + } + + #profile-main .pmo-pic .pmop-edit i { + margin-right: 4px; + } +} + +#profile-main .pmo-pic:hover .pmop-edit { + opacity: 1; + filter: alpha(opacity=100); +} + +#profile-main .pmo-pic .pmop-message { + position: absolute; + bottom: 27px; + left: 50%; + margin-left: -25px; +} + + #profile-main .pmo-pic .pmop-message .dropdown-menu { + padding: 5px 0 55px; + left: -90px; + width: 228px; + height: 150px; + top: -74px; + -webkit-transform-origin: center; + -moz-transform-origin: center; + -ms-transform-origin: center; + transform-origin: center; + } + + #profile-main .pmo-pic .pmop-message .dropdown-menu textarea { + width: 100%; + height: 95px; + border: 0; + resize: none; + padding: 10px 19px; + } + + #profile-main .pmo-pic .pmop-message .dropdown-menu button { + position: absolute; + bottom: 5px; + left: 93px; + } + +#profile-main .pmb-block { + margin-bottom: 20px; +} + +@media (min-width: 1200px) { + #profile-main .pmb-block { + padding: 40px 42px 0; + } +} + +@media (max-width: 1199px) { + #profile-main .pmb-block { + padding: 30px 20px 0; + } +} + +#profile-main .pmb-block:last-child { + margin-bottom: 50px; +} + +#profile-main .pmb-block .pmbb-header { + margin-bottom: 25px; + position: relative; +} + + #profile-main .pmb-block .pmbb-header .actions { + position: absolute; + top: -2px; + right: 0; + } + + #profile-main .pmb-block .pmbb-header h2 { + margin: 0; + font-weight: 100; + font-size: 20px; + } + +#profile-main .pmb-block .pmbb-edit { + position: relative; + z-index: 1; + display: none; +} + +#profile-main .pmb-block .pmbb-edit, +#profile-main .pmb-block .pmbb-view { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; + -webkit-animation-duration: 1000ms; + animation-duration: 1000ms; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +#profile-main .pmb-block.toggled .pmbb-edit { + display: block; +} + +#profile-main .pmb-block.toggled .pmbb-view { + display: none; +} + +#profile-main .pmo-block { + padding: 25px; +} + + #profile-main .pmo-block > h2 { + font-size: 16px; + margin: 0 0 15px; + } + +#profile-main .pmo-items .pmob-body { + padding: 0 10px; +} + +#profile-main .pmo-items a { + display: block; + padding: 4px; +} + + #profile-main .pmo-items a img { + width: 100%; + } + +#profile-main .pmo-contact ul { + list-style: none; + margin: 0; + padding: 0; +} + + #profile-main .pmo-contact ul li { + position: relative; + padding: 8px 0 8px 35px; + } + + #profile-main .pmo-contact ul li i { + font-size: 18px; + vertical-align: top; + line-height: 100%; + position: absolute; + left: 0; + } + +@media (max-width: 767px) { + .c-timeline { + background: #edecec; + box-shadow: none; + } + + .c-timeline .nav-tabs { + background: #fff; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + } +} + +.timeline { + position: relative; +} + +@media (min-width: 768px) { + .timeline { + padding: 50px; + padding-left: 100px; + } +} + +@media (max-width: 767px) { + .timeline { + margin-top: 30px; + } +} + +.t-view { + border: 1px solid #eee; + position: relative; + margin-bottom: 35px; +} + +@media (max-width: 767px) { + .t-view { + background: #fff; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + } +} + +.t-view .tv-header { + padding: 16px 18px; + border-bottom: 1px solid #eee; + background: #F9F9F9; +} + + .t-view .tv-header .actions { + position: absolute; + top: 5px; + right: 10px; + } + +.t-view .tv-body { + padding: 23px 25px; +} + + .t-view .tv-body .tvb-lightbox { + margin: 0 -8px 15px; + } + + .t-view .tv-body .tvb-lightbox [data-src] { + padding: 0 5px; + margin-bottom: 5px; + } + +.t-view .tvh-user { + display: block; +} + + .t-view .tvh-user img { + width: 46px; + height: 46px; + border-radius: 50%; + } + +.t-view:before { + position: absolute; + width: 40px; + height: 40px; + border-radius: 50%; + left: -70px; + top: 0; + border: 3px solid #FFF; + text-align: center; + font-size: 20px; + line-height: 34px; + color: #FFF; + font-family: 'Material Design Iconic Font'; + z-index: 1; +} + +.t-view:after { + content: ""; + position: absolute; + top: 0; + left: -50px; + width: 1px; + height: calc(100% + 37px); +} + +.t-view[data-tv-type="text"]:before { + content: "\f11b"; + background: #00bcd4; + box-shadow: 0 0 0 1px #00bcd4; +} + +.t-view[data-tv-type="text"]:after { + background: #00bcd4; +} + +.t-view[data-tv-type="image"]:before { + content: "\f224"; + background: #4caf50; + box-shadow: 0 0 0 1px #4caf50; +} + +.t-view[data-tv-type="image"]:after { + background: #4caf50; +} + +.t-view[data-tv-type="video"]:before { + content: "\f0cc"; + background: #ffc107; + box-shadow: 0 0 0 1px #ffc107; +} + +.t-view[data-tv-type="video"]:after { + background: #ffc107; +} + +.t-view .tvb-stats { + list-style: none; + padding: 0; + margin: 10px 0 20px; +} + + .t-view .tvb-stats > li { + display: inline-block; + padding: 5px 10px 6px; + border: 1px solid #ccc; + margin-right: 2px; + } + + .t-view .tvb-stats > li i { + font-size: 15px; + line-height: 100%; + vertical-align: top; + margin-top: 2px; + } + + .t-view .tvb-stats > li.tvbs-comments { + border-color: #4caf50; + color: #4caf50; + } + + .t-view .tvb-stats > li.tvbs-likes { + border-color: #03a9f4; + color: #03a9f4; + } + + .t-view .tvb-stats > li.tvbs-views { + border-color: #ff9800; + color: #ff9800; + } + +.tv-comments .tvc-lists { + padding: 0; + list-style: none; + margin: 0; +} + + .tv-comments .tvc-lists > li { + padding: 15px 20px; + margin: 0; + border-top: 1px solid #eee; + } + +.tvc-more { + color: #333; + display: block; + margin-bottom: -10px; +} + + .tvc-more:hover { + color: #000; + } + + .tvc-more i { + vertical-align: middle; + margin-right: 5px; + } + +.p-header { + position: relative; + margin: 0 -7px; +} + + .p-header .actions { + position: absolute; + top: -18px; + right: 0; + } + +.p-menu { + list-style: none; + padding: 0 5px; + margin: 0 0 30px; +} + + .p-menu > li { + display: inline-block; + vertical-align: top; + } + + .p-menu > li > a { + display: block; + padding: 5px 20px 5px 0; + font-weight: 500; + text-transform: uppercase; + font-size: 15px; + } + + .p-menu > li > a > i { + margin-right: 4px; + font-size: 20px; + vertical-align: middle; + margin-top: -5px; + } + + .p-menu > li:not(.active) > a { + color: #4285F4; + } + + .p-menu > li:not(.active) > a:hover { + color: #333; + } + + .p-menu > li.active > a { + color: #000; + } + +@media (max-width: 991px) { + .p-menu .pm-search { + margin: 20px 2px 30px; + display: block; + } + + .p-menu .pm-search input[type="text"] { + width: 100%; + border: 1px solid #ccc; + } +} + +.p-menu .pms-inner { + margin: -3px 0 0; + position: relative; + top: -2px; + overflow: hidden; + white-space: nowrap; +} + + .p-menu .pms-inner i { + vertical-align: top; + font-size: 20px; + line-height: 100%; + position: absolute; + left: 9px; + top: 7px; + } + + .p-menu .pms-inner input[type="text"] { + height: 35px; + border-radius: 2px; + padding: 0 10px 0 40px; + } + +@media (min-width: 768px) { + .p-menu .pms-inner input[type="text"] { + border: 1px solid #fff; + width: 50px; + background: transparent; + position: relative; + z-index: 1; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + .p-menu .pms-inner input[type="text"]:focus { + border-color: #DFDFDF; + width: 200px; + } +} + +.photos .p-item { + margin-bottom: 24px; + position: relative; +} + + .photos .p-item:before { + left: 0; + top: 0; + content: ""; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform: scale3d(0, 0, 0); + -moz-transform: scale3d(0, 0, 0); + -ms-transform: scale3d(0, 0, 0); + -o-transform: scale3d(0, 0, 0); + transform: scale3d(0, 0, 0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + background-color: rgba(0, 0, 0, 0.5); + z-index: 0; + border-radius: 0; + opacity: 0; + filter: alpha(opacity=0); + } + + .photos .p-item:hover:before { + -webkit-transform: scale3d(1, 1, 1); + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -o-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + opacity: 1; + filter: alpha(opacity=100); + } + + .photos .p-item img { + width: 100%; + border-radius: 2px; + } + +.photos .btn-float { + z-index: 1; + bottom: 40px; + right: 40px; + position: fixed; +} + +.contacts .c-item { + border: 1px solid #e2e2e2; + border-radius: 2px; + margin-bottom: 24px; +} + + .contacts .c-item .ci-avatar { + display: block; + } + + .contacts .c-item .ci-avatar img { + width: 100%; + border-radius: 2px 2px 0 0; + } + +.contacts .ci-avatar { + margin: -1px -1px 0; +} + +.contacts .c-info { + text-align: center; + margin-top: 15px; + padding: 0 5px; +} + + .contacts .c-info strong { + color: #000; + font-size: 14px; + font-weight: 500; + } + + .contacts .c-info small { + color: #999; + margin-top: 3px; + } + + .contacts .c-info strong, + .contacts .c-info small { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: block; + } + +.contacts .c-footer { + border-top: 1px solid #e2e2e2; + margin-top: 18px; +} + + .contacts .c-footer > button { + padding: 4px 10px 3px; + display: block; + width: 100%; + text-align: center; + color: #333; + font-weight: 500; + border-radius: 2px; + background: #fff; + border: 0; + } + + .contacts .c-footer > button > i { + font-size: 16px; + vertical-align: middle; + margin-top: -3px; + } + +.z-depth-1 { + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.16), 0 2px 10px rgba(0, 0, 0, 0.12); +} + +.z-depth-1-top { + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12); +} + +.z-depth-1-bottom { + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.16); +} + +.z-depth-2 { + box-shadow: 0 8px 17px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19); +} + +.z-depth-2-top { + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.19); +} + +.z-depth-2-bottom { + box-shadow: 0 8px 17px rgba(0, 0, 0, 0.2); +} + +.z-depth-3 { + box-shadow: 0 12px 15px rgba(0, 0, 0, 0.24), 0 17px 50px rgba(0, 0, 0, 0.19); +} + +.z-depth-3-top { + box-shadow: 0 17px 50px rgba(0, 0, 0, 0.19); +} + +.z-depth-3-bottom { + box-shadow: 0 12px 15px rgba(0, 0, 0, 0.24); +} + +.z-depth-4 { + box-shadow: 0 16px 28px rgba(0, 0, 0, 0.22), 0 25px 55px rgba(0, 0, 0, 0.21); +} + +.z-depth-4-top { + box-shadow: 0 25px 55px rgba(0, 0, 0, 0.21); +} + +.z-depth-4-bottom { + box-shadow: 0 16px 28px rgba(0, 0, 0, 0.22); +} + +.z-depth-5 { + box-shadow: 0 27px 24px rgba(0, 0, 0, 0.2), 0 40px 77px rgba(0, 0, 0, 0.22); +} + +.z-depth-5-top { + box-shadow: 0 40px 77px rgba(0, 0, 0, 0.22); +} + +.z-depth-5-bottom { + box-shadow: 0 27px 24px rgba(0, 0, 0, 0.2); +} + +.z-depth-animation .z-depth-1, +.z-depth-animation .z-depth-2, +.z-depth-animation .z-depth-3, +.z-depth-animation .z-depth-4, +.z-depth-animation .z-depth-5 { + transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* + * Block Header + * Used for Heading outside the Cards. + */ + +.block-header { + margin-bottom: 25px; + position: relative; +} + +@media screen and (min-width: 768px) { + .block-header { + padding: 0 22px; + } +} + +@media screen and (max-width: 991px) { + .block-header { + padding: 0 18px; + } +} + +.block-header > h2 { + font-size: 15px; + color: #777; + margin: 0; + font-weight: 400; + text-transform: uppercase; +} + + .block-header > h2 > small { + display: block; + text-transform: none; + margin-top: 8px; + margin-bottom: 20px; + color: #9E9E9E; + line-height: 140%; + } + +.block-header .actions { + position: absolute; + right: 10px; + top: -5px; + z-index: 3; +} + +/* + * Header Actions + */ + +.actions { + list-style: none; + padding: 0; + z-index: 2; + margin: 0; +} + + .actions > li { + display: inline-block; + vertical-align: baseline; + } + + .actions > li > a, + .actions > a { + width: 30px; + height: 30px; + line-height: 29px; + display: inline-block; + text-align: center; + position: relative; + } + + .actions > li > a > i, + .actions > a > i { + -webkit-transition: color; + -o-transition: color; + transition: color; + -webkit-transition-duration: 1300ms; + transition-duration: 1300ms; + color: #adadad; + font-size: 20px; + } + + .actions > li > a:hover > i, + .actions > a:hover > i { + color: #000; + } + + .actions > li > a:before, + .actions > a:before { + left: 0; + top: 0; + content: ""; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform: scale3d(0, 0, 0); + -moz-transform: scale3d(0, 0, 0); + -ms-transform: scale3d(0, 0, 0); + -o-transform: scale3d(0, 0, 0); + transform: scale3d(0, 0, 0); + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + background-color: rgba(0, 0, 0, 0.1); + z-index: 0; + border-radius: 50%; + opacity: 0; + filter: alpha(opacity=0); + } + + .actions > li > a:hover:before, + .actions > a:hover:before { + -webkit-transform: scale3d(1, 1, 1); + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -o-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + opacity: 1; + filter: alpha(opacity=100); + } + + .actions > li.open > a > i, + .actions.open > a > i { + color: #000; + } + + .actions > li.open > a:before, + .actions.open > a:before { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + opacity: 1; + filter: alpha(opacity=100); + } + + .actions.actions-alt > li > a > i { + color: #fff; + } + + .actions.actions-alt > li > a > i:hover { + color: #fff; + } + + .actions.actions-alt > li.open > a > i { + color: #fff; + } + + .actions.open { + z-index: 3; + } + +/* + * Collapse Menu Icons + */ + +.line-wrap { + width: 18px; + height: 12px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + margin: 10px 20px; +} + + .line-wrap .line { + width: 18px; + height: 2px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + .line-wrap .line.center { + margin: 3px 0; + } + +.open .line-wrap { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} + + .open .line-wrap .line.top { + width: 12px; + transform: translateX(8px) translateY(1px) rotate(45deg); + -webkit-transform: translateX(8px) translateY(1px) rotate(45deg); + } + + .open .line-wrap .line.bottom { + width: 12px; + transform: translateX(8px) translateY(-1px) rotate(-45deg); + -webkit-transform: translateX(8px) translateY(-1px) rotate(-45deg); + } + +/* + * Social Icons + */ + +.socicon { + font-family: 'socicon' !important; +} + +/* + * Load More + */ + +.load-more { + text-align: center; + margin-top: 30px; +} + + .load-more a { + padding: 5px 10px 3px; + display: inline-block; + background-color: #f44336; + color: #FFF; + border-radius: 2px; + white-space: nowrap; + } + + .load-more a i { + font-size: 20px; + vertical-align: middle; + position: relative; + margin-top: -2px; + } + + .load-more a:hover { + background-color: #ea1c0d; + } + +.ie-warning { + position: fixed; + top: 0; + left: 0; + z-index: 9999; + background: #000000; + width: 100%; + height: 100%; + text-align: center; + color: #fff; + font-family: "Courier New", Courier, monospace; + padding: 50px 0; +} + + .ie-warning p { + font-size: 17px; + } + + .ie-warning .iew-download { + background: #fff; + list-style: none; + padding: 30px 0; + margin: 50px -50px; + } + + .ie-warning .iew-download > li { + display: inline; + zoom: 1; + vertical-align: top; + } + + .ie-warning .iew-download > li > a { + display: block; + color: #000; + width: 140px; + font-size: 15px; + padding: 15px 0; + } + + .ie-warning .iew-download > li > a > div { + margin-top: 10px; + } + + .ie-warning .iew-download > li > a:hover { + background-color: #eee; + } + +/* + * Vendor Overrides + */ + +.mejs-container { + outline: none; +} + + .mejs-container .mejs-controls { + background: #ec592f; + height: 50px; + padding: 10px 5px 0; + } + + .mejs-container .mejs-controls div { + height: 5px; + } + + .mejs-container .mejs-controls div.mejs-time-rail { + position: absolute; + left: 0; + top: 0; + padding: 0; + width: 100% !important; + } + + .mejs-container .mejs-controls div.mejs-time-rail .mejs-time-total { + margin: 0; + width: 100% !important; + background: #ec592f; + } + + .mejs-container .mejs-controls div.mejs-time-rail .mejs-time-loaded { + background: #D04B25; + } + + .mejs-container .mejs-controls div.mejs-time-rail .mejs-time-current { + background: #ffea00; + } + + .mejs-container .mejs-controls div.mejs-time-rail .mejs-time-buffering { + background: #ec592f; + } + + .mejs-container .mejs-controls div.mejs-time-rail span:not(.mejs-time-float), + .mejs-container .mejs-controls div.mejs-time-rail a { + border-radius: 0; + height: 3px; + } + + .mejs-container .mejs-controls .mejs-button button { + background-color: #ec592f; + width: 15px; + height: 15px; + background-position: center; + } + + .mejs-container .mejs-controls .mejs-button button:focus { + outline: none !important; + } + + .mejs-container .mejs-controls .mejs-volume-button { + position: absolute; + right: 35px; + } + + .mejs-container .mejs-controls .mejs-play button { + background-image: url("img/icons/play.png"); + } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .mejs-container .mejs-controls .mejs-play button { + background-image: url("img/icons/play@2x.png"); + background-size: 15px 15px; + } +} + +.mejs-container .mejs-controls .mejs-pause button { + background-image: url("img/icons/pause.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .mejs-container .mejs-controls .mejs-pause button { + background-image: url("img/icons/pause@2x.png"); + background-size: 15px 15px; + } +} + +.mejs-container .mejs-controls .mejs-mute button { + background-image: url("img/icons/speaker.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .mejs-container .mejs-controls .mejs-mute button { + background-image: url("img/icons/speaker@2x.png"); + background-size: 15px 15px; + } +} + +.mejs-container .mejs-controls .mejs-unmute button { + background-image: url("img/icons/speaker-2.png"); +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .mejs-container .mejs-controls .mejs-unmute button { + background-image: url("img/icons/speaker-2@2x.png"); + background-size: 15px 15px; + } +} + +.mejs-container .mejs-controls .mejs-fullscreen-button { + position: absolute; + right: 5px; +} + + .mejs-container .mejs-controls .mejs-fullscreen-button button { + background-image: url("img/icons/fullscreen.png"); + } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .mejs-container .mejs-controls .mejs-fullscreen-button button { + background-image: url("img/icons/fullscreen@2x.png"); + background-size: 15px 15px; + } +} + +/** CALENDAR WIDGET **/ + +#calendar-widget { + margin-bottom: 30px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); +} + +#fc-actions { + position: absolute; + top: 24px; + right: 12px; +} + +.fc { + background-color: #fff; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); + margin-bottom: 30px; +} + + .fc td { + border-color: #f0f0f0; + text-align: center !important; + } + + .fc th { + background: #f32c1e; + color: rgba(255, 255, 255, 0.9); + font-weight: 400; + padding: 6px 0; + } + + .fc table tr > td:first-child { + border-left-width: 0; + } + + .fc .ui-widget-header { + border-width: 0; + } + +.fc-toolbar { + background-color: #f44336; + margin-bottom: 0; + padding: 20px 7px 19px; + position: relative; +} + + .fc-toolbar h2 { + color: rgba(255, 255, 255, 0.9); + margin-top: 7px; + font-size: 20px; + font-weight: 300; + text-transform: uppercase; + } + + .fc-toolbar .ui-button { + border: 0; + background: 0 0; + padding: 0; + outline: none !important; + text-align: center; + } + + .fc-toolbar .ui-button > span { + position: relative; + font-family: 'Material Design Iconic Font'; + font-size: 20px; + color: #FFF; + line-height: 100%; + width: 30px; + padding-top: 5px; + display: block; + margin-top: 2px; + } + + .fc-toolbar .ui-button > span:before { + position: relative; + z-index: 1; + } + + .fc-toolbar .ui-button > span.ui-icon-circle-triangle-w:before { + content: "\f297"; + } + + .fc-toolbar .ui-button > span.ui-icon-circle-triangle-e:before { + content: "\f298"; + } + + .fc-toolbar .ui-button > span:after { + content: ""; + width: 0; + position: absolute; + top: 50%; + height: 0; + border-radius: 50%; + left: 50%; + z-index: 0; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + } + + .fc-toolbar .ui-button:hover > span:after { + width: 31px; + height: 31px; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.2); + } + +.fc-event { + padding: 0; + font-size: 11px; + border-radius: 0; + border: 0; + border-radius: 2px; +} + + .fc-event .fc-title { + padding: 2px 0; + display: block; + } + + .fc-event .fc-time { + float: left; + background: rgba(0, 0, 0, 0.2); + padding: 2px 6px; + margin: 0 0 0 -1px; + } + +.fc-view, +.fc-view > table { + border: 0; + overflow: hidden; + /* + @media @min-992 { + width: ~"calc(100% + 1px)"; + } + */ +} + + .fc-view > table > tbody > tr > .ui-widget-content { + border-top: 0; + } + +div.fc-row { + margin-right: 0 !important; + border: 0 !important; +} + +/* Even Tag Color */ + +.event-tag { + margin-top: 5px; +} + + .event-tag > span { + border-radius: 50%; + width: 30px; + height: 30px; + margin-right: 3px; + position: relative; + display: inline-block; + cursor: pointer; + } + + .event-tag > span:hover { + opacity: 0.8; + filter: alpha(opacity=80); + } + + .event-tag > span.selected:before { + font-family: 'Material Design Iconic Font'; + content: "\f299"; + position: absolute; + text-align: center; + top: 3px; + width: 100%; + font-size: 17px; + color: #FFF; + } + +.bootgrid-footer .infoBar, +.bootgrid-header .actionBar { + text-align: left; +} + +.bootgrid-footer .search, +.bootgrid-header .search { + vertical-align: top; +} + +.bootgrid-header { + padding: 0 25px 10px; +} + + .bootgrid-header .search { + border: 1px solid #e0e0e0; + } + + .bootgrid-header .search .form-control, + .bootgrid-header .search .input-group-addon { + border: 0; + } + + .bootgrid-header .search .glyphicon-search { + vertical-align: top; + padding: 10px 10px 0; + } + + .bootgrid-header .search .glyphicon-search:before { + content: "\f05f"; + font-family: 'Material Design Iconic Font'; + font-size: 17px; + vertical-align: top; + line-height: 100%; + } + +@media (min-width: 480px) { + .bootgrid-header .search { + width: 300px; + } +} + +@media (max-width: 480px) { + .bootgrid-header .search { + width: 100%; + padding-right: 90px; + } +} + +.bootgrid-header .actions { + box-shadow: none; +} + + .bootgrid-header .actions .btn-group { + border: 1px solid #e0e0e0; + } + + .bootgrid-header .actions .btn-group .btn { + height: 35px; + box-shadow: none !important; + background: transparent; + } + + .bootgrid-header .actions .btn-group .dropdown-menu { + padding: 10px 20px; + } + + .bootgrid-header .actions .btn-group .dropdown-menu .dropdown-item { + padding: 0 0 0 27px !important; + } + + .bootgrid-header .actions .btn-group .dropdown-menu .dropdown-item:hover { + background-color: #fff !important; + } + +@media (min-width: 768px) { + .bootgrid-header .actions .btn-group .dropdown-menu { + left: 0; + -webkit-transform-origin: top left; + -moz-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + margin-top: 1px; + } +} + +.bootgrid-header .actions .btn-group .caret { + display: none; +} + +.bootgrid-header .actions .btn-group .md { + line-height: 100%; + font-size: 18px; + vertical-align: top; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; +} + +.bootgrid-header .actions .btn-group.open .md { + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} + +@media (max-width: 480px) { + .bootgrid-header .actions { + position: absolute; + top: 0; + right: 15px; + } +} + +.bootgrid-table th > .column-header-anchor > .icon { + top: 0px; + font-size: 20px; + line-height: 100%; +} + +.bootgrid-footer .col-sm-6 { + padding: 10px 30px 20px; +} + +@media (max-width: 768px) { + .bootgrid-footer .col-sm-6 { + text-align: center; + } +} + +@media (max-width: 768px) { + .bootgrid-footer .infoBar { + display: none; + } +} + +.bootgrid-footer .infoBar .infos { + border: 1px solid #EEE; + display: inline-block; + float: right; + padding: 7px 30px; + font-size: 12px; + margin-top: 5px; +} + +.select-cell .checkbox { + margin: 0; +} + +.command-edit, +.command-delete { + background: #fff; + border: 1px solid #eee !important; +} + +.bootstrap-select > .btn-default { + background: none !important; + border-bottom: 1px solid #e0e0e0 !important; + border-radius: 0; + padding-left: 0; + padding-right: 0; +} + + .bootstrap-select > .btn-default:before { + position: absolute; + top: 0; + right: 0; + content: ""; + height: calc(100% - 2px); + width: 30px; + background-color: #FFF; + background-position: right calc(100% - 7px); + background-repeat: no-repeat; + background-image: url("img/select.png"); + pointer-events: none; + z-index: 5; + } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .bootstrap-select > .btn-default:before { + background-image: url("img/select@2x.png"); + background-size: 12px 12px; + } +} + +.bootstrap-select > .btn-default:after { + position: absolute; + z-index: 3; + bottom: -1px; + left: 0; + height: 2px; + width: 0; + content: ""; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; +} + +.bootstrap-select > .btn-default:not(.disabled):after, +.bootstrap-select > .btn-default:not(.readonly):after { + background: #2196f3; +} + +.bootstrap-select > .btn-default.disabled:after, +.bootstrap-select > .btn-default.readonly:after { + background: #ccc; +} + +.bootstrap-select.open > .selectpicker:after { + width: 100%; +} + +.bootstrap-select .bs-searchbox { + padding: 0 18px; + margin: 5px 0 10px; + position: relative; +} + + .bootstrap-select .bs-searchbox:before { + position: absolute; + left: 14px; + top: 2px; + width: 30px; + height: 100%; + content: "\f05f"; + font-family: 'Material Design Iconic Font'; + font-size: 25px; + } + + .bootstrap-select .bs-searchbox input { + padding-left: 25px; + border: 0; + } + +.bootstrap-select.btn-group .dropdown-menu li a.opt { + padding-left: 17px; +} + +.bootstrap-select .check-mark { + margin-top: -5px !important; + font-size: 19px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + display: block !important; + position: absolute; + top: 11px; + right: 15px; +} + + .bootstrap-select .check-mark:before { + content: "\f023"; + font-family: 'Material Design Iconic Font'; + } + +.bootstrap-select .selected .check-mark { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); +} + +.bootstrap-select .notify { + bottom: 0 !important; + margin: 0 !important; + width: 100% !important; + border: 0 !important; + background: #f44336 !important; + color: #fff !important; + text-align: center; +} + +.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn) { + width: 100%; +} + +/* Chosen */ +/* Chosen v1.4.2 | (c) 2011-2015 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ + +.chosen-container { + position: relative; + display: inline-block; + vertical-align: middle; + font-size: 13px; + zoom: 1; + *display: inline; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + + .chosen-container * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + .chosen-container .chosen-drop { + position: absolute; + top: 100%; + left: -9999px; + z-index: 1010; + width: 100%; + border: 1px solid #aaa; + border-top: 0; + background: #fff; + box-shadow: 0 4px 5px rgba(0,0,0,.15); + } + + .chosen-container.chosen-with-drop .chosen-drop { + left: 0; + } + + .chosen-container a { + cursor: pointer; + } + + .chosen-container .search-choice .group-name, .chosen-container .chosen-single .group-name { + margin-right: 4px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-weight: 400; + color: #999; + } + + .chosen-container .search-choice .group-name:after, .chosen-container .chosen-single .group-name:after { + content: ":"; + padding-left: 2px; + vertical-align: top; + } + +.chosen-container-single .chosen-single { + position: relative; + display: block; + overflow: hidden; + padding: 0 0 0 8px; + height: 25px; + border: 1px solid #aaa; + border-radius: 5px; + background-color: #fff; + background: -webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4)); + background: -webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%); + background: -moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%); + background: -o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%); + background: linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%); + background-clip: padding-box; + box-shadow: 0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1); + color: #444; + text-decoration: none; + white-space: nowrap; + line-height: 24px; +} + +.chosen-container-single .chosen-default { + color: #999; +} + +.chosen-container-single .chosen-single span { + display: block; + overflow: hidden; + margin-right: 26px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.chosen-container-single .chosen-single-with-deselect span { + margin-right: 38px; +} + +.chosen-container-single .chosen-single abbr { + position: absolute; + top: 6px; + right: 26px; + display: block; + width: 12px; + height: 12px; + background: url(chosen-sprite.png) -42px 1px no-repeat; + font-size: 1px; +} + + .chosen-container-single .chosen-single abbr:hover { + background-position: -42px -10px; + } + +.chosen-container-single.chosen-disabled .chosen-single abbr:hover { + background-position: -42px -10px; +} + +.chosen-container-single .chosen-single div { + position: absolute; + top: 0; + right: 0; + display: block; + width: 18px; + height: 100%; +} + + .chosen-container-single .chosen-single div b { + display: block; + width: 100%; + height: 100%; + background: url(chosen-sprite.png) no-repeat 0 2px; + } + +.chosen-container-single .chosen-search { + position: relative; + z-index: 1010; + margin: 0; + padding: 3px 4px; + white-space: nowrap; +} + + .chosen-container-single .chosen-search input[type=text] { + margin: 1px 0; + padding: 4px 20px 4px 5px; + width: 100%; + height: auto; + outline: 0; + border: 1px solid #aaa; + background: #fff url(chosen-sprite.png) no-repeat 100% -20px; + background: url(chosen-sprite.png) no-repeat 100% -20px; + font-size: 1em; + font-family: sans-serif; + line-height: normal; + border-radius: 0; + } + +.chosen-container-single .chosen-drop { + margin-top: -1px; + border-radius: 0 0 4px 4px; + background-clip: padding-box; +} + +.chosen-container-single.chosen-container-single-nosearch .chosen-search { + position: absolute; + left: -9999px; +} + +.chosen-container .chosen-results { + color: #444; + position: relative; + overflow-x: hidden; + overflow-y: auto; + margin: 0 4px 4px 0; + padding: 0 0 0 4px; + max-height: 240px; + -webkit-overflow-scrolling: touch; +} + + .chosen-container .chosen-results li { + display: none; + margin: 0; + padding: 5px 6px; + list-style: none; + line-height: 15px; + word-wrap: break-word; + -webkit-touch-callout: none; + } + + .chosen-container .chosen-results li.active-result { + display: list-item; + cursor: pointer; + } + + .chosen-container .chosen-results li.disabled-result { + display: list-item; + color: #ccc; + cursor: default; + } + + .chosen-container .chosen-results li.highlighted { + background-color: #3875d7; + background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc)); + background-image: -webkit-linear-gradient(#3875d7 20%,#2a62bc 90%); + background-image: -moz-linear-gradient(#3875d7 20%,#2a62bc 90%); + background-image: -o-linear-gradient(#3875d7 20%,#2a62bc 90%); + background-image: linear-gradient(#3875d7 20%,#2a62bc 90%); + color: #fff; + } + + .chosen-container .chosen-results li.no-results { + color: #777; + display: list-item; + background: #f4f4f4; + } + + .chosen-container .chosen-results li.group-result { + display: list-item; + font-weight: 700; + cursor: default; + } + + .chosen-container .chosen-results li.group-option { + padding-left: 15px; + } + + .chosen-container .chosen-results li em { + font-style: normal; + text-decoration: underline; + } + +.chosen-container-multi .chosen-choices { + position: relative; + overflow: hidden; + margin: 0; + padding: 0 5px; + width: 100%; + height: auto!important; + height: 1%; + border: 1px solid #aaa; + background-color: #fff; + background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff)); + background-image: -webkit-linear-gradient(#eee 1%,#fff 15%); + background-image: -moz-linear-gradient(#eee 1%,#fff 15%); + background-image: -o-linear-gradient(#eee 1%,#fff 15%); + background-image: linear-gradient(#eee 1%,#fff 15%); + cursor: text; +} + + .chosen-container-multi .chosen-choices li { + float: left; + list-style: none; + } + + .chosen-container-multi .chosen-choices li.search-field { + margin: 0; + padding: 0; + white-space: nowrap; + } + + .chosen-container-multi .chosen-choices li.search-field input[type=text] { + margin: 1px 0; + padding: 0; + height: 25px; + outline: 0; + border: 0!important; + background: transparent!important; + box-shadow: none; + color: #999; + font-size: 100%; + font-family: sans-serif; + line-height: normal; + border-radius: 0; + } + + .chosen-container-multi .chosen-choices li.search-choice { + position: relative; + margin: 3px 5px 3px 0; + padding: 3px 20px 3px 5px; + border: 1px solid #aaa; + max-width: 100%; + border-radius: 3px; + background-color: #eee; + background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee)); + background-image: -webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-image: -moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-image: -o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-image: linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-size: 100% 19px; + background-repeat: repeat-x; + background-clip: padding-box; + box-shadow: 0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05); + color: #333; + line-height: 13px; + cursor: default; + } + + .chosen-container-multi .chosen-choices li.search-choice span { + word-wrap: break-word; + } + + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close { + position: absolute; + top: 4px; + right: 3px; + display: block; + width: 12px; + height: 12px; + background: url(chosen-sprite.png) -42px 1px no-repeat; + font-size: 1px; + } + + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover { + background-position: -42px -10px; + } + + .chosen-container-multi .chosen-choices li.search-choice-disabled { + padding-right: 5px; + border: 1px solid #ccc; + background-color: #e4e4e4; + background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee)); + background-image: -webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-image: -moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-image: -o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + background-image: linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%); + color: #666; + } + + .chosen-container-multi .chosen-choices li.search-choice-focus { + background: #d4d4d4; + } + + .chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close { + background-position: -42px -10px; + } + +.chosen-container-multi .chosen-results { + margin: 0; + padding: 0; +} + +.chosen-container-multi .chosen-drop .result-selected { + display: list-item; + color: #ccc; + cursor: default; +} + +.chosen-container-active .chosen-single { + border: 1px solid #5897fb; + box-shadow: 0 0 5px rgba(0,0,0,.3); +} + +.chosen-container-active.chosen-with-drop .chosen-single { + border: 1px solid #aaa; + -moz-border-radius-bottomright: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomleft: 0; + border-bottom-left-radius: 0; + background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff)); + background-image: -webkit-linear-gradient(#eee 20%,#fff 80%); + background-image: -moz-linear-gradient(#eee 20%,#fff 80%); + background-image: -o-linear-gradient(#eee 20%,#fff 80%); + background-image: linear-gradient(#eee 20%,#fff 80%); + box-shadow: 0 1px 0 #fff inset; +} + + .chosen-container-active.chosen-with-drop .chosen-single div { + border-left: 0; + background: transparent; + } + + .chosen-container-active.chosen-with-drop .chosen-single div b { + background-position: -18px 2px; + } + +.chosen-container-active .chosen-choices { + border: 1px solid #5897fb; + box-shadow: 0 0 5px rgba(0,0,0,.3); +} + + .chosen-container-active .chosen-choices li.search-field input[type=text] { + color: #222!important; + } + +.chosen-disabled { + opacity: .5!important; + cursor: default; +} + + .chosen-disabled .chosen-single { + cursor: default; + } + + .chosen-disabled .chosen-choices .search-choice .search-choice-close { + cursor: default; + } + +.chosen-rtl { + text-align: right; +} + + .chosen-rtl .chosen-single { + overflow: visible; + padding: 0 8px 0 0; + } + + .chosen-rtl .chosen-single span { + margin-right: 0; + margin-left: 26px; + direction: rtl; + } + + .chosen-rtl .chosen-single-with-deselect span { + margin-left: 38px; + } + + .chosen-rtl .chosen-single div { + right: auto; + left: 3px; + } + + .chosen-rtl .chosen-single abbr { + right: auto; + left: 26px; + } + + .chosen-rtl .chosen-choices li { + float: right; + } + + .chosen-rtl .chosen-choices li.search-field input[type=text] { + direction: rtl; + } + + .chosen-rtl .chosen-choices li.search-choice { + margin: 3px 5px 3px 0; + padding: 3px 5px 3px 19px; + } + + .chosen-rtl .chosen-choices li.search-choice .search-choice-close { + right: auto; + left: 4px; + } + + .chosen-rtl.chosen-container-single-nosearch .chosen-search, .chosen-rtl .chosen-drop { + left: 9999px; + } + + .chosen-rtl.chosen-container-single .chosen-results { + margin: 0 0 4px 4px; + padding: 0 4px 0 0; + } + + .chosen-rtl .chosen-results li.group-option { + padding-right: 15px; + padding-left: 0; + } + + .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { + border-right: 0; + } + + .chosen-rtl .chosen-search input[type=text] { + padding: 4px 5px 4px 20px; + background: #fff url(chosen-sprite.png) no-repeat -30px -20px; + background: url(chosen-sprite.png) no-repeat -30px -20px; + direction: rtl; + } + + .chosen-rtl.chosen-container-single .chosen-single div b { + background-position: 6px 2px; + } + + .chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b { + background-position: -12px 2px; + } + +@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi),only screen and (min-resolution:1.5dppx) { + .chosen-rtl .chosen-search input[type=text], .chosen-container-single .chosen-single abbr, .chosen-container-single .chosen-single div b, .chosen-container-single .chosen-search input[type=text], .chosen-container-multi .chosen-choices .search-choice .search-choice-close, .chosen-container .chosen-results-scroll-down span, .chosen-container .chosen-results-scroll-up span { + background-image: url(chosen-sprite@2x.png)!important; + background-size: 52px 37px!important; + background-repeat: no-repeat!important; + } +} + +.chosen-container { + width: 100%; +} + + .chosen-container .chosen-drop { + border: 0; + } + + .chosen-container:after { + position: absolute; + z-index: 3; + bottom: 0; + left: 0; + height: 2px; + width: 0; + content: ""; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + background: #2196f3; + } + + .chosen-container .chosen-drop { + margin-top: 1px; + display: block; + left: 0; + width: 100%; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + opacity: 0; + filter: alpha(opacity=0); + } + + .chosen-container:not(.chosen-right) .chosen-drop { + -webkit-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } + + .chosen-container.chosen-right .chosen-drop { + -webkit-transform-origin: 100% 0; + -moz-transform-origin: 100% 0; + -ms-transform-origin: 100% 0; + transform-origin: 100% 0; + } + + .chosen-container.chosen-container-active .chosen-drop { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + opacity: 1; + filter: alpha(opacity=100); + } + + .chosen-container .chosen-results { + padding: 0; + margin: 0; + } + + .chosen-container .chosen-results > li { + padding: 8px 17px; + color: #4C4C4C; + -webkit-transition: background-color; + -o-transition: background-color; + transition: background-color; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + .chosen-container .chosen-results > li:not(.disabled-result):not(.result-selected):not(.group-result) { + color: #262626; + } + + .chosen-container .chosen-results > li:not(.disabled-result):not(.result-selected):not(.group-result):not(:hover) { + background: #fff !important; + } + + .chosen-container .chosen-results > li:not(.disabled-result):not(.result-selected):not(.group-result):hover { + background-color: #e4e4e4; + color: #262626; + } + + .chosen-container .chosen-results > li.disabled-result { + color: #e4e4e4; + } + + .chosen-container .chosen-results > li.result-selected { + background: #2196f3; + color: #fff; + } + + .chosen-container .chosen-results > li.highlighted { + background: #eee; + color: #333; + } + + .chosen-container .chosen-results > li.group-result { + padding: 3px 16px; + margin-top: 10px; + color: #b1b1b1; + font-weight: normal; + } + + .chosen-container .chosen-results > li.group-result:not(:first-child) { + border-top: 1px solid rgba(0, 0, 0, 0.08); + padding-top: 15px; + } + + .chosen-container .chosen-choices { + border-left: 0; + border-top: 0; + border-right: 0; + } + + .chosen-container .chosen-choices .search-field input[type=text] { + height: 34px; + } + + .chosen-container .chosen-choices .chosen-single-with-deselect:before { + font-family: 'Material Design Iconic Font'; + content: "\f29a"; + font-size: 13px; + color: #696969; + margin-right: 8px; + content: ""; + } + +.chosen-container-single:before { + position: absolute; + top: 0; + height: 100%; + width: 13px; + right: 0; + z-index: 1; + background-image: url("img/select.png"); + background-position: right; + background-repeat: no-repeat; + content: ""; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .chosen-container-single:before { + background-image: url("img/select@2x.png"); + background-size: 12px 12px; + } +} + +.chosen-container-single .chosen-single { + padding: 0 16px 0 0; + border-left: 0; + border-top: 0; + border-right: 0; + border-radius: 0; + background: transparent; + border-bottom: 1px solid #e0e0e0; + box-shadow: none; + height: 28px; +} + + .chosen-container-single .chosen-single div b { + background: none; + } + +.chosen-container-single .chosen-search { + padding: 0 18px; + margin: 10px 0 15px; + position: relative; +} + + .chosen-container-single .chosen-search:before { + position: absolute; + left: 14px; + top: 2px; + width: 30px; + height: 100%; + content: "\f05f"; + font-family: 'Material Design Iconic Font'; + font-size: 25px; + } + + .chosen-container-single .chosen-search input[type=text] { + border: 0; + padding-top: 8px; + padding-left: 30px; + } + +.chosen-container-active.chosen-with-drop .chosen-single { + border-top: 0; + border-left: 0; + border-right: 0; + border-color: #e0e0e0; + background: none; +} + +.chosen-container-active:after { + width: 100%; +} + +.chosen-container-active .chosen-choices { + box-shadow: none; +} + +.chosen-container-multi .chosen-choices { + border: 0; + border-bottom: 1px solid #e0e0e0; + background: none; + padding: 0; +} + + .chosen-container-multi .chosen-choices li.search-choice { + border: 0; + padding: 6px 25px 5px 7px; + margin: 0 5px 5px 0; + background: #eee; + border-radius: 2px; + box-shadow: none; + } + + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close { + right: 7px; + top: 6px; + background: none; + } + + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before { + font-family: 'Material Design Iconic Font'; + content: "\f29a"; + font-size: 13px; + color: #696969; + margin-right: 8px; + } + +.chosen-search input[type=text] { + background: none !important; +} + +.noUi-target { + border-radius: 0; + box-shadow: none; + border: 0; +} + +.noUi-background { + background: #d4d4d4; + box-shadow: none; +} + +.noUi-horizontal { + height: 3px; +} + + .noUi-horizontal .noUi-handle { + top: -8px; + } + +.noUi-vertical { + width: 3px; +} + + .noUi-horizontal .noUi-handle, + .noUi-vertical .noUi-handle { + width: 19px; + height: 19px; + border: 0; + border-radius: 100%; + box-shadow: none; + -webkit-transition: box-shadow; + -o-transition: box-shadow; + transition: box-shadow; + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + cursor: pointer; + position: relative; + } + + .noUi-horizontal .noUi-handle:before, + .noUi-vertical .noUi-handle:before, + .noUi-horizontal .noUi-handle:after, + .noUi-vertical .noUi-handle:after { + display: none; + } + + .noUi-horizontal .noUi-handle:active, + .noUi-vertical .noUi-handle:active { + background: #ccc !important; + } + + .noUi-horizontal .noUi-handle .is-tooltip, + .noUi-vertical .noUi-handle .is-tooltip { + position: absolute; + bottom: 32px; + height: 35px; + border-radius: 2px; + color: #fff; + text-align: center; + line-height: 33px; + width: 50px; + left: 50%; + margin-left: -25px; + padding: 0 10px; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + opacity: 0; + filter: alpha(opacity=0); + -webkit-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + } + + .noUi-horizontal .noUi-handle .is-tooltip:after, + .noUi-vertical .noUi-handle .is-tooltip:after { + width: 0; + height: 0; + border-style: solid; + border-width: 15px 10px 0 10px; + position: absolute; + bottom: -8px; + left: 50%; + margin-left: -9px; + content: ""; + } + + .noUi-horizontal .noUi-active, + .noUi-vertical .noUi-active { + box-shadow: 0 0 0 13px rgba(0, 0, 0, 0.1); + } + + .noUi-horizontal .noUi-active .is-tooltip, + .noUi-vertical .noUi-active .is-tooltip { + -webkit-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + bottom: 40px; + opacity: 1; + filter: alpha(opacity=100); + } + +.input-slider:not([data-is-color]) .noUi-handle, +.input-slider-range:not([data-is-color]) .noUi-handle, +.input-slider-values:not([data-is-color]) .noUi-handle, +.input-slider:not([data-is-color]) .noUi-connect, +.input-slider-range:not([data-is-color]) .noUi-connect, +.input-slider-values:not([data-is-color]) .noUi-connect { + background: #009688 !important; +} + +.input-slider:not([data-is-color]) .is-tooltip, +.input-slider-range:not([data-is-color]) .is-tooltip, +.input-slider-values:not([data-is-color]) .is-tooltip { + background: #009688; +} + + .input-slider:not([data-is-color]) .is-tooltip:after, + .input-slider-range:not([data-is-color]) .is-tooltip:after, + .input-slider-values:not([data-is-color]) .is-tooltip:after { + border-color: #009688 transparent transparent transparent; + } + +.input-slider[data-is-color=red] .noUi-handle, +.input-slider-range[data-is-color=red] .noUi-handle, +.input-slider-values[data-is-color=red] .noUi-handle, +.input-slider[data-is-color=red] .noUi-connect, +.input-slider-range[data-is-color=red] .noUi-connect, +.input-slider-values[data-is-color=red] .noUi-connect { + background: #f44336 !important; +} + +.input-slider[data-is-color=blue] .noUi-handle, +.input-slider-range[data-is-color=blue] .noUi-handle, +.input-slider-values[data-is-color=blue] .noUi-handle, +.input-slider[data-is-color=blue] .noUi-connect, +.input-slider-range[data-is-color=blue] .noUi-connect, +.input-slider-values[data-is-color=blue] .noUi-connect { + background: #2196f3 !important; +} + +.input-slider[data-is-color=cyan] .noUi-handle, +.input-slider-range[data-is-color=cyan] .noUi-handle, +.input-slider-values[data-is-color=cyan] .noUi-handle, +.input-slider[data-is-color=cyan] .noUi-connect, +.input-slider-range[data-is-color=cyan] .noUi-connect, +.input-slider-values[data-is-color=cyan] .noUi-connect { + background: #00bcd4 !important; +} + +.input-slider[data-is-color=amber] .noUi-handle, +.input-slider-range[data-is-color=amber] .noUi-handle, +.input-slider-values[data-is-color=amber] .noUi-handle, +.input-slider[data-is-color=amber] .noUi-connect, +.input-slider-range[data-is-color=amber] .noUi-connect, +.input-slider-values[data-is-color=amber] .noUi-connect { + background: #ffc107 !important; +} + +.input-slider[data-is-color=green] .noUi-handle, +.input-slider-range[data-is-color=green] .noUi-handle, +.input-slider-values[data-is-color=green] .noUi-handle, +.input-slider[data-is-color=green] .noUi-connect, +.input-slider-range[data-is-color=green] .noUi-connect, +.input-slider-values[data-is-color=green] .noUi-connect { + background: #4caf50 !important; +} + +.input-slider .noUi-origin { + background: #d4d4d4; +} + +.input-slider:not([data-is-color]) .noUi-base { + background: #009688 !important; +} + +.input-slider[data-is-color=red] .noUi-base { + background: #f44336 !important; +} + +.input-slider[data-is-color=blue] .noUi-base { + background: #2196f3 !important; +} + +.input-slider[data-is-color=cyan] .noUi-base { + background: #00bcd4 !important; +} + +.input-slider[data-is-color=amber] .noUi-base { + background: #ffc107 !important; +} + +.input-slider[data-is-color=green] .noUi-base { + background: #4caf50 !important; +} + +.cp-container { + position: relative; +} + + .cp-container > .input-group input.cp-value { + color: #000 !important; + background: transparent !important; + } + + .cp-container > .input-group .dropdown-menu { + padding: 20px; + margin-left: 10px; + } + + .cp-container i.cp-value { + border-radius: 2px 5px 5px 2px; + height: 30px; + position: absolute; + right: 1px; + top: 1px; + width: 25px; + } + +.note-editor, +.note-popover { + border-color: #e4e4e4; +} + + .note-editor .note-toolbar, + .note-popover .note-toolbar, + .note-editor .popover-content, + .note-popover .popover-content { + background: #fff; + border-color: #e4e4e4; + margin: 0; + padding: 10px 0 15px; + text-align: center; + } + + .note-editor .note-toolbar > .btn-group, + .note-popover .note-toolbar > .btn-group, + .note-editor .popover-content > .btn-group, + .note-popover .popover-content > .btn-group { + display: inline-block; + float: none; + box-shadow: none; + } + + .note-editor .note-toolbar > .btn-group .btn, + .note-popover .note-toolbar > .btn-group .btn, + .note-editor .popover-content > .btn-group .btn, + .note-popover .popover-content > .btn-group .btn { + margin: 0 1px; + } + + .note-editor .note-toolbar > .btn-group > .active, + .note-popover .note-toolbar > .btn-group > .active, + .note-editor .popover-content > .btn-group > .active, + .note-popover .popover-content > .btn-group > .active { + background: #00bcd4; + color: #fff; + } + + .note-editor .note-toolbar .btn, + .note-popover .note-toolbar .btn, + .note-editor .popover-content .btn, + .note-popover .popover-content .btn { + height: 40px; + border-radius: 2px !important; + box-shadow: none !important; + } + + .note-editor .note-toolbar .btn:active, + .note-popover .note-toolbar .btn:active, + .note-editor .popover-content .btn:active, + .note-popover .popover-content .btn:active { + box-shadow: none; + } + + .note-editor .note-toolbar .note-palette-title, + .note-popover .note-toolbar .note-palette-title, + .note-editor .popover-content .note-palette-title, + .note-popover .popover-content .note-palette-title { + margin: 0 !important; + padding: 10px 0 !important; + font-size: 13px !important; + text-align: center !important; + border: 0 !important; + } + + .note-editor .note-toolbar .note-color-reset, + .note-popover .note-toolbar .note-color-reset, + .note-editor .popover-content .note-color-reset, + .note-popover .popover-content .note-color-reset { + padding: 0 0 10px !important; + margin: 0 !important; + background: none; + text-align: center; + } + + .note-editor .note-toolbar .note-color .dropdown-menu, + .note-popover .note-toolbar .note-color .dropdown-menu, + .note-editor .popover-content .note-color .dropdown-menu, + .note-popover .popover-content .note-color .dropdown-menu { + min-width: 335px; + } + + .note-editor .note-statusbar .note-resizebar, + .note-popover .note-statusbar .note-resizebar { + border-color: #E8E8E8; + } + + .note-editor .note-statusbar .note-resizebar .note-icon-bar, + .note-popover .note-statusbar .note-resizebar .note-icon-bar { + border-color: #BCBCBC; + } + + .note-editor .fa, + .note-popover .fa { + font-style: normal; + font-size: 20px; + vertical-align: middle; + } + + .note-editor .fa:before, + .note-popover .fa:before { + font-family: 'Material Design Iconic Font'; + } + + .note-editor .fa.fa-magic:before, + .note-popover .fa.fa-magic:before { + content: "\f11b"; + } + + .note-editor .fa.fa-bold:before, + .note-popover .fa.fa-bold:before { + content: "\f17a"; + } + + .note-editor .fa.fa-italic:before, + .note-popover .fa.fa-italic:before { + content: "\f181"; + } + + .note-editor .fa.fa-underline:before, + .note-popover .fa.fa-underline:before { + content: "\f18b"; + } + + .note-editor .fa.fa-font:before, + .note-popover .fa.fa-font:before { + content: "\f17e"; + } + + .note-editor .fa.fa-list-ul:before, + .note-popover .fa.fa-list-ul:before { + content: "\f183"; + } + + .note-editor .fa.fa-list-ol:before, + .note-popover .fa.fa-list-ol:before { + content: "\f184"; + } + + .note-editor .fa.fa-align-left:before, + .note-popover .fa.fa-align-left:before { + content: "\f178"; + } + + .note-editor .fa.fa-align-left:before, + .note-popover .fa.fa-align-left:before { + content: "\f178"; + } + + .note-editor .fa.fa-align-right:before, + .note-popover .fa.fa-align-right:before { + content: "\f179"; + } + + .note-editor .fa.fa-align-center:before, + .note-popover .fa.fa-align-center:before { + content: "\f176"; + } + + .note-editor .fa.fa-align-justify:before, + .note-popover .fa.fa-align-justify:before { + content: "\f177"; + } + + .note-editor .fa.fa-indent:before, + .note-popover .fa.fa-indent:before { + content: "\f180"; + } + + .note-editor .fa.fa-outdent:before, + .note-popover .fa.fa-outdent:before { + content: "\f17f"; + } + + .note-editor .fa.fa-text-height:before, + .note-popover .fa.fa-text-height:before { + content: "\f182"; + } + + .note-editor .fa.fa-table:before, + .note-popover .fa.fa-table:before { + content: "\f21e"; + } + + .note-editor .fa.fa-link:before, + .note-popover .fa.fa-link:before { + content: "\f10d"; + } + + .note-editor .fa.fa-picture-o:before, + .note-popover .fa.fa-picture-o:before { + content: "\f224"; + } + + .note-editor .fa.fa-minus:before, + .note-popover .fa.fa-minus:before { + content: "\f16e"; + } + + .note-editor .fa.fa-arrows-alt:before, + .note-popover .fa.fa-arrows-alt:before { + content: "\f29f"; + } + + .note-editor .fa.fa-code:before, + .note-popover .fa.fa-code:before { + content: "\f066"; + } + + .note-editor .fa.fa-question:before, + .note-popover .fa.fa-question:before { + content: "\f033"; + } + + .note-editor .fa.fa-eraser:before, + .note-popover .fa.fa-eraser:before { + content: "\f17b"; + } + + .note-editor .fa.fa-square:before, + .note-popover .fa.fa-square:before { + content: "\f1f4"; + } + + .note-editor .fa.fa-circle-o:before, + .note-popover .fa.fa-circle-o:before { + content: "\f2e3"; + } + + .note-editor .fa.fa-times:before, + .note-popover .fa.fa-times:before { + content: "\f29a"; + } + + .note-editor .note-air-popover .arrow, + .note-popover .note-air-popover .arrow { + left: 20px; + } + + .note-editor .note-editable { + padding: 20px 23px; + } + +.bootstrap-datetimepicker-widget { + margin-top: 0 !important; +} + + .bootstrap-datetimepicker-widget.top { + -webkit-transform-origin: 0 100% !important; + -moz-transform-origin: 0 100% !important; + -ms-transform-origin: 0 100% !important; + transform-origin: 0 100% !important; + } + + .bootstrap-datetimepicker-widget:before, + .bootstrap-datetimepicker-widget:after { + display: none !important; + } + + .bootstrap-datetimepicker-widget .picker-switch.accordion-toggle span { + background: #fff; + border-radius: 0; + } + + .bootstrap-datetimepicker-widget .picker-switch.accordion-toggle span:hover { + background: #fff; + } + + .bootstrap-datetimepicker-widget .datepicker-days table { + margin-bottom: 20px; + } + + .bootstrap-datetimepicker-widget .timepicker .md { + font-size: 25px; + } + + .bootstrap-datetimepicker-widget .glyphicon { + color: #333; + } + + .bootstrap-datetimepicker-widget .active { + background: #2196f3 !important; + } + +.fileinput { + position: relative; + padding-right: 35px; +} + + .fileinput .close { + position: absolute; + top: 5px; + font-size: 12px; + float: none; + opacity: 1; + font-weight: 500; + border: 1px solid #ccc; + width: 19px; + text-align: center; + height: 19px; + line-height: 15px; + border-radius: 50%; + right: 0; + } + + .fileinput .close:hover { + background: #eee; + } + + .fileinput .input-group-addon { + padding: 0 10px; + vertical-align: middle; + } + + .fileinput .fileinput-preview { + width: 200px; + height: 150px; + position: relative; + } + + .fileinput .fileinput-preview img { + display: inline-block; + vertical-align: middle; + margin-top: -13px; + } + + .fileinput .fileinput-preview:after { + content: ""; + display: inline-block; + vertical-align: middle; + } + +#lg-outer { + background: rgba(255, 255, 255, 0.95); +} + + #lg-outer .object { + box-shadow: 0 8px 17px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19); + border-radius: 2px; + } + +#lg-close { + display: none; +} + +#lg-action { + top: 0; + width: 100%; + left: 0; + margin-left: 0 !important; + height: 40px; + border-bottom: 1px solid #eee; + text-align: center; +} + + #lg-action > a { + background: transparent; + color: #9D9D9D; + font-size: 18px; + width: 28px; + height: 37px; + } + + #lg-action > a:hover { + background: transparent; + color: #000; + } + + #lg-action .cl-thumb { + position: fixed; + right: 20px; + bottom: 20px; + width: 50px; + height: 50px; + border-radius: 50%; + line-height: 38px; + background: #f44336; + -webkit-transition: all; + -o-transition: all; + transition: all; + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + } + + #lg-action .cl-thumb:after { + text-align: center; + left: 16px !important; + bottom: 6px !important; + color: #fff; + } + + #lg-action .cl-thumb:hover { + background: #f32c1e; + } + +#lg-gallery .thumb-cont { + background: #f44336; + text-align: center; +} + + #lg-gallery .thumb-cont .thumb-info { + background: #f44336; + } + + #lg-gallery .thumb-cont .thumb-info .count { + display: none; + } + + #lg-gallery .thumb-cont .thumb-info .close { + width: 14px; + margin-top: 0; + background: none; + } + + #lg-gallery .thumb-cont .thumb-info .close:hover { + background: none; + } + + #lg-gallery .thumb-cont .thumb { + opacity: 1; + filter: alpha(opacity=100); + } + + #lg-gallery .thumb-cont .thumb-inner { + display: inline-block; + padding: 12px 12px 15px; + } + +.lg-slide { + background: none !important; +} + + .lg-slide:after { + content: ""; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + height: 50px; + width: 50px; + border-radius: 100%; + border: 2px solid #2196f3; + -webkit-animation: ball-scale-ripple 1s 0s infinite cubic-bezier(0.21, 0.53, 0.56, 0.8); + animation: ball-scale-ripple 1s 0s infinite cubic-bezier(0.21, 0.53, 0.56, 0.8); + position: absolute; + left: 50%; + margin-left: -25px; + top: 50%; + margin-top: -25px; + z-index: -1; + } + + .lg-slide em { + font-style: normal; + } + + .lg-slide em h3 { + margin-bottom: 5px; + } + + .lg-slide .video-cont { + box-shadow: 0 8px 17px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19); + } + +@-webkit-keyframes ball-scale-ripple { + 0% { + -webkit-transform: scale(0.1); + transform: scale(0.1); + opacity: 1; + } + + 70% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0.7; + } + + 100% { + opacity: 0.0; + } +} + +@keyframes ball-scale-ripple { + 0% { + -webkit-transform: scale(0.1); + transform: scale(0.1); + opacity: 1; + } + + 70% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0.7; + } + + 100% { + opacity: 0.0; + } +} + +.waves-effect { + position: relative; + cursor: pointer; + overflow: hidden; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; +} + +#loading-bar, +#loading-bar-spinner { + pointer-events: none; + -webkit-pointer-events: none; + -webkit-transition: linear all; + -o-transition: linear all; + transition: linear all; + -webkit-transition-duration: 350ms; + transition-duration: 350ms; +} + +#loading-bar.ng-enter, +#loading-bar.ng-leave.ng-leave-active, +#loading-bar-spinner.ng-enter, +#loading-bar-spinner.ng-leave.ng-leave-active { + opacity: 0; + filter: alpha(opacity=0); +} + +#loading-bar.ng-enter.ng-enter-active, +#loading-bar.ng-leave, +#loading-bar-spinner.ng-enter.ng-enter-active, +#loading-bar-spinner.ng-leave { + opacity: 1; + filter: alpha(opacity=100); +} + +#loading-bar .bar { + -webkit-transition: width; + -o-transition: width; + transition: width; + -webkit-transition-duration: 350ms; + transition-duration: 350ms; + background: rgba(0, 0, 0, 0.15); + position: fixed; + z-index: 10002; + top: 0; + left: 0; + width: 100%; + height: 70px; + border-bottom-right-radius: 1px; + border-top-right-radius: 1px; +} + +/* Fancy blur effect */ + +#loading-bar .peg { + position: absolute; + width: 70px; + right: 0; + top: 0; + height: 2px; + opacity: 0.45; + filter: alpha(opacity=45); + box-shadow: #fff 1px 0 6px 1px; + border-radius: 100%; + z-index: 99999; +} + +#loading-bar-spinner { + width: 56px; + height: 56px; + text-align: center; + padding: 14px; + border-radius: 50%; + position: fixed; + top: 105px; + left: 50%; + margin-left: -28px; + background: #fff; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.16), 0 2px 10px rgba(0, 0, 0, 0.12); +} + +#loading-bar-spinner .spinner-icon { + display: inline-block; + width: 28px; + height: 28px; + margin: 0; + float: left; + background: transparent !important; + border: 2px solid #00bcd4; + border-bottom-color: transparent !important; + border-radius: 100%; + -webkit-animation: ball-clip-rotate 0.75s linear infinite; + -o-animation: ball-clip-rotate 0.75s linear infinite; + animation: ball-clip-rotate 0.75s linear infinite; +} + +#loading-bar-spinner:before, +#loading-bar-spinner:after { + content: " "; + display: table; +} + +#loading-bar-spinner:after { + clear: both; +} + +#loading-bar-spinner:before, +#loading-bar-spinner:after { + content: " "; + display: table; +} + +#loading-bar-spinner:after { + clear: both; +} + + + +.jspContainer { + overflow: hidden; + position: relative; +} + +.jspPane { + position: absolute; +} + +.jspVerticalBar { + position: absolute; + top: 0; + right: 0; + width: 11px; + height: 100%; + background: none; +} + +.jspHorizontalBar { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 11px; + background: none; +} + + .jspVerticalBar *, + .jspHorizontalBar * { + margin: 0; + padding: 0; + } + +.jspCap { + display: none; +} + +.jspHorizontalBar .jspCap { + float: left; +} + +.jspTrack { + background: transparent; + position: relative; +} + +.jspVerticalBar .jspTrack { + width: 5px; + margin: 0 0 0 3px; +} + +.jspHorizontalBar .jspTrack { + height: 5px; + margin: 3px 0 3px 0; +} + +.jspVerticalBar .jspCap { + display: block; + height: 3px; + width: 11px; +} + +.jspHorizontalBar .jspCap { + display: block; + width: 3px; + height: 11px; +} + +.jspDrag { + position: relative; + top: 0; + left: 0; + border-radius: 3px 3px 3px 3px; + -webkit-border-radius: 3px 3px 3px 3px; + opacity: .75; + background: rgba(0, 0, 0, 0.5); + cursor: default; +} + +.jspHorizontalBar .jspTrack, +.jspHorizontalBar .jspDrag { + float: left; + height: 5px; +} + +.clear { + clear:both; +} + +body > #Form.showControlBar { + margin-top: 0 !important; +} + +/* + * Animation + */ + +@-webkit-keyframes ball-clip-rotate { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + + 50% { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-moz-keyframes ball-clip-rotate { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + + 50% { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-o-keyframes ball-clip-rotate { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + + 50% { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes ball-clip-rotate { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + + 50% { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/* Make clicks pass-through */ \ No newline at end of file diff --git a/LiveChat/Templates/Default/images/ar.png b/LiveChat/Templates/Default/images/ar.png new file mode 100644 index 0000000..572e4aa Binary files /dev/null and b/LiveChat/Templates/Default/images/ar.png differ diff --git a/LiveChat/Templates/Default/images/bad-small.png b/LiveChat/Templates/Default/images/bad-small.png new file mode 100644 index 0000000..d2b844f Binary files /dev/null and b/LiveChat/Templates/Default/images/bad-small.png differ diff --git a/LiveChat/Templates/Default/images/bad.png b/LiveChat/Templates/Default/images/bad.png new file mode 100644 index 0000000..83a02e8 Binary files /dev/null and b/LiveChat/Templates/Default/images/bad.png differ diff --git a/LiveChat/Templates/Default/images/good-small.png b/LiveChat/Templates/Default/images/good-small.png new file mode 100644 index 0000000..0fd090a Binary files /dev/null and b/LiveChat/Templates/Default/images/good-small.png differ diff --git a/LiveChat/Templates/Default/images/good.png b/LiveChat/Templates/Default/images/good.png new file mode 100644 index 0000000..e62c72a Binary files /dev/null and b/LiveChat/Templates/Default/images/good.png differ diff --git a/LiveChat/Templates/Default/images/rating.png b/LiveChat/Templates/Default/images/rating.png new file mode 100644 index 0000000..85585d2 Binary files /dev/null and b/LiveChat/Templates/Default/images/rating.png differ diff --git a/LiveChat/Templates/Default/images/seen.png b/LiveChat/Templates/Default/images/seen.png new file mode 100644 index 0000000..cc675f9 Binary files /dev/null and b/LiveChat/Templates/Default/images/seen.png differ diff --git a/LiveChat/Templates/Default/images/tick.png b/LiveChat/Templates/Default/images/tick.png new file mode 100644 index 0000000..7590604 Binary files /dev/null and b/LiveChat/Templates/Default/images/tick.png differ diff --git a/LiveChat/Templates/Default/style.css b/LiveChat/Templates/Default/style.css new file mode 100644 index 0000000..6254cba --- /dev/null +++ b/LiveChat/Templates/Default/style.css @@ -0,0 +1,881 @@ +.mydnn-livechat-widget { + background: #fff none repeat scroll 0 0; + border: 0 none; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + box-sizing: border-box; + box-shadow: 0 0 3px 2px rgba(0, 0, 0, 0.1); + direction: ltr; + display: block; + font-family: Verdana,Geneva,sans-serif; + height: 400px; + padding: 0; + margin: 0; + overflow: hidden; + position: fixed; + bottom: 0; + right: 10px; + z-index: 99999; +} + + .mydnn-livechat-widget.livechat-widget-Small { + height: 350px; + width: 250px; + } + + .mydnn-livechat-widget.livechat-widget-Small .livechat-prechat .prechat-body .livechat-pregreeting { + margin-bottom: 5px; + } + + .mydnn-livechat-widget.livechat-widget-Small .livechat-prechat .prechat-body label { + font-size: 11px; + margin-top: 5px; + } + + .mydnn-livechat-widget.livechat-widget-Small .livechat-prechat .prechat-body .livechat-form-control textarea { + height: 40px; + min-height: 30px; + } + + .mydnn-livechat-widget.livechat-widget-Small .livechat-prechat .prechat-footer { + padding: 5px 20px; + } + + .mydnn-livechat-widget.livechat-widget-Small .livechat-messages { + height: 195px; + } + + .mydnn-livechat-widget.livechat-widget-Medium { + height: 400px; + width: 290px; + } + + .mydnn-livechat-widget.livechat-widget-Large { + height: 500px; + width: 350px; + } + + .mydnn-livechat-widget.livechat-widget-Large .livechat-prechat .prechat-body .livechat-form-control textarea { + height: 150px; + min-height: 150px; + } + + .mydnn-livechat-widget.livechat-widget-Large .livechat-messages { + height: 345px; + } + + .mydnn-livechat-widget.livechat-widget-position-BottomRight { + position: fixed; + top: auto; + bottom: 0; + left: auto; + right: 10px; + } + + .mydnn-livechat-widget.livechat-widget-position-BottomLeft { + position: fixed; + top: auto; + bottom: 0; + left: 10px; + right: auto; + } + +.livechat-top { + height: 24px; + text-align: center; + position: relative; +} + + .livechat-top .livechat-minmax { + cursor: pointer; + font-family: arial; + font-size: 19px; + font-weight: bold; + height: 100%; + line-height: 8px; + overflow: hidden; + position: absolute; + right: 7px; + top: 0; + width: 10px; + } + + .livechat-top .livechat-title { + cursor: default; + font-size: 12px; + font-weight: bold; + line-height: 24px; + white-space: nowrap; + } + +/*Pre Chat */ +.livechat-prechat { + margin: 0; + padding: 0; + width: 100%; +} + + .livechat-prechat .prechat-body { + height: calc(100% - 85px); + overflow-y: auto; + padding: 5px 20px; + } + + .livechat-prechat .prechat-body .livechat-pregreeting { + font-size: 12px; + margin-bottom: 10px; + min-height: 55px; + } + + .livechat-prechat .prechat-body label { + color: #666; + display: block; + font-weight: bold; + margin-top: 10px; + } + + .livechat-prechat .prechat-body .livechat-form-control { + margin-bottom: 5px; + margin-top: 5px; + } + + .livechat-prechat .prechat-body .livechat-form-control input, .livechat-prechat .prechat-body .livechat-form-control textarea, .livechat-prechat .prechat-body .livechat-form-control select { + -moz-appearance: none; + -webkit-appearance: none; + background: #fff none repeat scroll 0 0; + border-color: #ddd; + border-radius: 5px; + border-style: solid; + border-width: 1px; + box-shadow: none; + box-sizing: border-box; + color: #666; + display: block; + font-size: 12px; + font-style: italic; + padding: 6px; + margin: 0; + width: 100%; + } + + .livechat-prechat .prechat-body .livechat-form-control textarea { + height: 50px; + line-height: normal; + min-height: 50px; + resize: vertical; + } + + .livechat-prechat .prechat-body .livechat-form-control select { + background: transparent; + margin: 0 0 0 5px; + } + + .livechat-prechat .prechat-body .livechat-form-control.livechat-form-dropdown { + background: rgba(0, 0, 0, 0) url("images/ar.png") no-repeat scroll right center; + margin-left: -5px; + margin-right: 5px; + } + + .livechat-prechat .prechat-footer { + border-top: 1px solid #eee; + margin-top: 0; + padding: 10px 20px; + } + + .livechat-prechat .prechat-footer .livechat-chat-button { + -moz-appearance: none; + -webkit-appearance: none; + border-radius: 3px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.25) inset; + box-sizing: border-box; + display: inline-block; + cursor: pointer; + font-size: 12px; + font-weight: bold; + overflow: hidden; + padding: 6px 3px; + text-overflow: ellipsis; + text-align: center; + white-space: nowrap; + width: 100%; + word-wrap: normal; + } + + .livechat-prechat .prechat-footer .livechat-chat-button:hover { + font-family: Verdana; + } + + +/*Chat*/ +.livechat { +} + + .livechat .livchat-topinfo { + border-bottom: 1px solid #eee; + box-shadow: 0 1px 3px #f1efef; + box-sizing: border-box; + height: 50px; + padding: 5px 0 0 65px; + position: relative; + width: 100%; + } + + .livechat .livchat-topinfo .agents-image { + border-radius: 3px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + height: 50px; + left: 10px; + overflow: hidden; + position: absolute; + top: -12px; + width: 50px; + } + + .livechat .livchat-topinfo .agents-image .agent-wrapper { + border-radius: 0; + box-shadow: none; + float: left; + left: 0; + position: relative; + top: 0; + } + + .livechat .livchat-topinfo .agents-image.agent-count-1 .agent-wrapper { + width: 100%; + } + + .livechat .livchat-topinfo .agents-image.agent-count-2 .agent-wrapper { + border-left: 1px solid #fff; + width: 49%; + } + + .livechat .livchat-topinfo .agents-image.agent-count-3 .agent-wrapper, .livechat .livchat-topinfo .agents-image.agent-count-4 .agent-wrapper { + border-left: 1px solid #fff; + width: 32%; + } + + .livechat .livchat-topinfo .agents-image .agent-wrapper:first-child { + border: none !important; + } + + .livechat .livchat-topinfo .agent-wrapper { + background: #fff none repeat scroll 0 0; + border-radius: 3px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + height: 50px; + left: 10px; + overflow: hidden; + position: absolute; + top: -12px; + width: 50px; + } + + .livechat .livchat-topinfo .agent-wrapper > img { + height: 100%; + max-width: 120%; + min-width: 100%; + } + + .livechat .livchat-topinfo .display-title { + display: block; + font-size: 13px; + font-weight: bold; + line-height: normal; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre; + width: 150px; + } + + .livechat .livchat-topinfo .byline-title { + color: #aaa; + display: block; + font-size: 12px; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre; + width: 150px; + } + + .livechat .livchat-topinfo .chat-rating { + position: absolute; + right: 10px; + top: 15px; + width: 60px; + } + + .livechat .livchat-topinfo .chat-rating .rating-disable-wrapper { + position: absolute; + border-radius: 15px; + left: 0; + top: 0; + width: 100%; + cursor: not-allowed; + height: 100%; + background: rgba(128, 128, 128, 0.05); + } + + .livechat .livchat-topinfo .chat-rating > span { + background: url("images/rating.png") no-repeat scroll 0 0; + cursor: pointer; + display: block; + float: left; + height: 21px; + width: 20px; + } + + + .livechat .livchat-topinfo .chat-rating .rating-good { + background-position: -1px -1px; + margin-right: 10px; + } + + .livechat .livchat-topinfo .chat-rating .rating-good.active { + background-position: -1px -26px; + } + + .livechat .livchat-topinfo .chat-rating .rating-bad { + background-position: -24px -2px; + } + + .livechat .livchat-topinfo .chat-rating .rating-bad.active { + background-position: -24px -28px; + } + + .livechat .livechat-messages { + box-sizing: border-box; + height: 240px; + list-style: outside none none; + margin: 0; + overflow-x: hidden; + overflow-y: auto; + padding: 10px; + width: 100%; + } + + .livechat .livechat-messages > li { + list-style: outside none none; + } + + .livechat .livechat-messages .message-notify { + border: none; + color: #aaa; + font-size: 11px; + margin-bottom: 10px; + text-align: center; + } + + .livechat .livechat-message { + box-sizing: border-box; + display: inline-block; + margin-bottom: 10px; + position: relative; + width: 100%; + } + + .livechat .livechat-message.speech-bubbles { + padding-left: 7px; + } + + .livechat .livechat-message.show-avatar.speech-bubbles { + padding-left: 42px; + } + + .livechat .livechat-message .sender-avatar { + background: #fff none repeat scroll 0 0; + border: 1px solid #ddd; + border-radius: 3px; + display: block; + height: 32px; + overflow: hidden; + width: 32px; + float: left; + margin-right: 8px; + } + + .livechat .livechat-message.speech-bubbles .sender-avatar { + position: absolute; + left: 0; + bottom: 0; + margin: 0; + } + + .livechat .livechat-message .sender-avatar > img { + max-height: 40px; + width: 100%; + } + + .livechat .livechat-message .message-body { + box-sizing: border-box; + float: left; + padding: 0px; + position: relative; + width: 100%; + } + + .livechat .livechat-message.show-avatar .message-body { + width: calc(100% - 40px); + } + + .livechat .livechat-message.speech-bubbles .message-body { + border-radius: 4px; + border: 1px solid #ddd; + background: #fbfbfb none repeat scroll 0 0; + padding: 5px; + width: 100%; + } + + .livechat .livechat-message.speech-bubbles .message-body::before { + border-color: transparent #ddd transparent transparent; + border-style: solid; + border-width: 6px; + bottom: 5px; + content: ""; + height: 0; + right: 100%; + left: auto; + position: absolute; + width: 0; + z-index: 1000; + } + + .livechat .livechat-message.speech-bubbles .message-body::after { + background: transparent none repeat scroll 0 0; + border-color: transparent #fbfbfb transparent transparent; + border-style: solid; + border-width: 5px; + bottom: 6px; + content: ""; + height: 0; + right: 100%; + left: auto; + position: absolute; + width: 0; + z-index: 1001; + } + + .livechat .livechat-message .message-body .sender-displayname { + box-sizing: border-box; + color: #666; + display: block; + font-size: 12px; + font-weight: bold; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre; + width: 100%; + } + + .livechat .livechat-message .message-body > p { + color: #666; + display: inline-block; + float: left; + font-size: 12px; + font-weight: normal; + line-height: 20px; + margin: 0; + direction: ltr; + text-align: left; + word-wrap: break-word; + } + + .livechat .livechat-message .message-body .message-resend { + color: #ef0505; + cursor: pointer; + float: right; + font-family: Verdana; + font-size: 10px; + font-weight: 300; + } + + .livechat .livechat-message .message-body .message-sent { + background: rgba(0, 0, 0, 0) url("images/tick.png") no-repeat scroll right top; + height: 20px; + float: right; + width: 20px; + } + + .livechat .livechat-message .message-body .message-seen { + background: rgba(0, 0, 0, 0) url("images/seen.png") no-repeat scroll right top; + height: 20px; + float: right; + width: 20px; + } + + .livechat .livechat-message .message-body .message-time { + color: #aaaaaa; + display: inline-block; + float: right; + font-size: 10px; + font-weight: 300; + margin-right: 5px; + } + + .livechat .livechat-message.my-message.speech-bubbles { + padding-left: 0; + padding-right: 7px; + } + + .livechat .livechat-message.my-message.show-avatar.speech-bubbles { + padding-right: 42px; + padding-left: 0; + } + + .livechat .livechat-message.my-message .sender-avatar { + right: 0; + left: auto; + } + + .livechat .livechat-message.my-message .message-body { + float: right; + } + + .livechat .livechat-message.my-message.speech-bubbles .message-body::before { + border-color: transparent transparent transparent #ddd; + border-style: solid; + border-width: 6px; + bottom: 5px; + content: ""; + height: 0; + left: 100%; + right: auto; + position: absolute; + width: 0; + z-index: 1000; + } + + .livechat .livechat-message.my-message.speech-bubbles .message-body::after { + background: transparent none repeat scroll 0 0; + border-color: transparent transparent transparent #fbfbfb; + border-style: solid; + border-width: 5px; + bottom: 6px; + content: ""; + height: 0; + left: 100%; + right: auto; + position: absolute; + width: 0; + z-index: 1001; + } + + .livechat .livechat-message.sender-prevmessage { + margin-top: -5px; + } + + .livechat .livechat-tools { + border-top: 1px solid #eee; + box-sizing: border-box; + height: 85px; + padding: 10px; + position: relative; + width: 100%; + } + + .livechat .livechat-tools .livechat-reconnecting { + background: rgba(44, 43, 43, 0.56) none repeat scroll 0 0; + box-sizing: border-box; + color: #fff; + font-size: 14px; + font-weight: 300; + height: 100%; + left: 0; + line-height: normal; + padding: 10% 0; + position: absolute; + text-align: center; + text-shadow: 0 0 2px #000000; + top: 0; + width: 100%; + z-index: 9999; + } + + .livechat .livechat-tools .livechat-agent-offline { + background: rgba(208, 208, 208, 0.83) none repeat scroll 0 0; + box-sizing: border-box; + color: #9c9b9b; + font-size: 14px; + font-weight: 300; + height: 100%; + left: 0; + line-height: normal; + padding: 10% 0; + position: absolute; + text-align: center; + top: 0; + width: 100%; + z-index: 9998; + } + + .livechat .message-editor { + background: rgba(0, 0, 0, 0) none repeat scroll 0 0; + border: 1px solid #ddd; + border-radius: 5px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset; + box-sizing: border-box; + height: 50px; + margin: 0; + padding: 10px; + resize: none; + transition: height 0.1s ease-in-out 0s; + width: 100%; + } + + .livechat .message-editor:disabled { + background: rgb(229, 229, 229) none repeat scroll 0 0; + } + + .livechat .livechat-popupmenu { + background: #fff none repeat scroll 0 0; + border-color: #ddd; + border-radius: 5px; + border-style: solid; + border-width: 1px; + box-sizing: border-box; + bottom: 24px; + box-shadow: 0 0 3px 2px rgba(0, 0, 0, 0.1); + color: #444; + display: none; + left: 10px; + margin-bottom: -2px; + max-width: 360px; + min-width: 180px; + padding: 5px 10px; + position: absolute; + right: 10px; + z-index: 100; + } + + .livechat .livechat-popupmenu .popup-item { + } + + .livechat .livechat-popupmenu .popup-item a { + box-sizing: border-box; + color: #444; + display: block; + font-size: 13px; + margin-bottom: 5px; + padding: 5px; + width: 100%; + } + + .livechat .livechat-popupmenu .popup-item a:hover { + background: silver none repeat scroll 0 0; + color: #fff; + text-decoration: none; + } + + .livechat .livechat-email-transcript { + background: #fff none repeat scroll 0 0; + border-color: #ddd; + border-radius: 5px; + border-style: solid; + border-width: 1px; + box-sizing: border-box; + bottom: 24px; + box-shadow: 0 0 3px 2px rgba(0, 0, 0, 0.1); + color: #444; + display: none; + left: 10px; + margin-bottom: -2px; + max-width: 360px; + min-width: 180px; + padding: 10px; + position: absolute; + right: 10px; + z-index: 100; + } + + .livechat .livechat-input { + -moz-appearance: none; + -webkit-appearance: none; + background: #fff none repeat scroll 0 0; + border-color: #ddd; + border-radius: 5px; + border-style: solid; + border-width: 1px; + box-shadow: none; + box-sizing: border-box; + color: #666; + display: block; + font-size: 12px; + font-style: italic; + padding: 6px; + margin: 0; + width: 100%; + } + + .livechat button.livechat-btn { + -moz-appearance: none; + -webkit-appearance: none; + background: #247ad7 none repeat scroll 0 0; + border-color: #0062bb; + border-radius: 3px; + border-style: solid; + border-width: 1px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.25) inset; + color: #ffffff; + display: block; + font-weight: bold; + padding: 6px 3px; + text-align: center; + width: 100%; + } + + .livechat button.livechat-btn:hover, .livechat .livechat-popupmenu button.livechat-btn:focus { + background: #438cec none repeat scroll 0 0; + } + + .livechat button.livechat-btn:disabled { + background: #7caceb none repeat scroll 0 0; + cursor: not-allowed; + } + +.err.control-focused, .err.invalid { + border: solid 1px #f00 !important; +} + +@media (max-device-width: 480px) and (orientation: landscape) { + .no-mobile { + display: none; + } +} + +@media (max-width: 767px) { + .no-tablet { + display: none; + } +} + +.livechat-minbutton { + position: fixed; + bottom: 0; + right: 0; + z-index: 999999; +} + + .livechat-minbutton .online-button { + padding: 10px; + } + + .livechat-minbutton .offline-button { + padding: 10px; + } + + + .livechat-minbutton.livechat-minbutton-Left { + left: 1px !important; + right: auto !important; + } + + .livechat-minbutton.livechat-minbutton-Center1 { + left: 50% !important; + right: auto !important; + } + + .livechat-minbutton.livechat-minbutton-Right { + left: auto !important; + right: 1px !important; + } + + .livechat-minbutton.livechat-minbutton-Top { + top: 1px !important; + bottom: auto !important; + } + + .livechat-minbutton.livechat-minbutton-Bottom { + top: auto !important; + bottom: 1px !important; + } + + .livechat-minbutton.livechat-minbutton-Center2 { + top: 50% !important; + bottom: auto !important; + } + + .livechat-minbutton.rotate-90 { + -moz-transform: rotate(90.0deg); + -o-transform: rotate(90.0deg); + -webkit-transform: rotate(90.0deg); + filter: progid: DXImageTransform.Microsoft.BasicImage(rotation=0.083); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; + transform: rotate(90.0deg); + } + + .livechat-minbutton.rotate--90 { + -moz-transform: rotate(-90.0deg); + -o-transform: rotate(-90.0deg); + -webkit-transform: rotate(-90.0deg); + filter: progid: DXImageTransform.Microsoft.BasicImage(rotation=0.083); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; + transform: rotate(-90.0deg); + } + +@keyframes bouncy_left { + 0% { + margin-left: 0; + } + + 7% { + margin-left: 0; + } + + 10.25% { + margin-left: -18px; + } + + 13.5% { + margin-left: 0; + } + + 16% { + margin-left: -9px; + } + + 18.5% { + margin-left: 0; + } + + 19.75% { + margin-left: -4px; + } + + 21% { + margin-left: 0; + } + + 21.5% { + margin-left: -2px; + } + + 22% { + margin-left: 0; + } + + 100% { + margin-left: 0; + } +} + +.livechat-serve-requests { + -webkit-animation: bouncy_left 8s linear 0s 3 normal; + -moz-animation: bouncy_left 8s linear 0s 3 normal; + -ms-animation: bouncy_left 8s linear 0s 3 normal; + -o-animation: bouncy_left 8s linear 0s 3 normal; + animation: bouncy_left 8s linear 0s 3 normal; + background: #f78e3f none repeat scroll 0 0; + border: 1px solid #804500; + border-radius: 0 3px 3px 0; + bottom: 3px; + color: #fff; + cursor: pointer; + display: none; + font-weight: 700; + height: 30px; + left: 0; + line-height: 28px; + position: fixed; + text-align: center; + width: 200px; + z-index: 9999; +} diff --git a/LiveChat/Templates/Default/view.html b/LiveChat/Templates/Default/view.html new file mode 100644 index 0000000..55799ae --- /dev/null +++ b/LiveChat/Templates/Default/view.html @@ -0,0 +1,121 @@ + +
        +
        + _ +
        {{localizeString["Support.Text"]}}
        +
        + +
        +
        +

        {{localizeString["PreGreeting.Text"]}}

        +

        {{localizeString["OfflineMessage.Text"]}}

        + +
        + +
        +
        + +
        + +
        + +
        + +
        + +
        +
        + +
        + +
        +
        +
        + + + +
        + + + + {{localizeString["LiveSupport.Text"]}} + +
        +
        + + +
        +
        +
          +
        • +
          {{localizeString["PleaseWaitUntilAgentAnswer.Text"]}}
          +
        • +
        • +
          + {{message.Message}} +
          +
          + + + +
          + {{message.SenderDisplayName}} +

          {{message.Message}}

          + + + {{localizeString["Resend.Text"]}} + {{message.MsgTime}} +
          +
          +
        • +
        +
        + +
        + {{localizeString["Reconnecting.Text"]}} +
        +
        + {{localizeString["AgentHasOffline.Text"]}} +
        + + +
        + + +
        +
        + +
        + +
        +
        +
        +
        diff --git a/LiveChat/ViewModels/AgentViewModel.cs b/LiveChat/ViewModels/AgentViewModel.cs new file mode 100644 index 0000000..7d7ce74 --- /dev/null +++ b/LiveChat/ViewModels/AgentViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.Modules.Support.LiveChat.ViewModels +{ + public class AgentViewModel + { + public int AgentID { get; set; } + public int UserID { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public bool Enabled { get; set; } + public int Priority { get; set; } + public string ProfilePic + { + get + { + return DotNetNuke.Common.Globals.ResolveUrl("~/dnnimagehandler.ashx?mode=profilepic&userid=" + this.UserID); + } + } + public IEnumerable Departments { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/DeparmentViewModel.cs b/LiveChat/ViewModels/DeparmentViewModel.cs new file mode 100644 index 0000000..399d6db --- /dev/null +++ b/LiveChat/ViewModels/DeparmentViewModel.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; +using MyDnn.Modules.Support.LiveChat.Models; + +namespace MyDnn.Modules.Support.LiveChats.ViewModels +{ + public class DepartmentViewModel + { + public DepartmentViewModel() + { + } + + public DepartmentViewModel(DepartmentInfo info) + { + if (info == null) return; + DepartmentID = info.DepartmentID; + DepartmentName = info.DepartmentName; + Description = info.Description; + } + + public int DepartmentID { get; set; } + public string DepartmentName { get; set; } + public string Description { get; set; } + public bool TicketEnabled { get; set; } + public bool LiveChatEnabled { get; set; } + + public IEnumerable Agents { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/DepartmentAgentViewModel.cs b/LiveChat/ViewModels/DepartmentAgentViewModel.cs new file mode 100644 index 0000000..6f13a68 --- /dev/null +++ b/LiveChat/ViewModels/DepartmentAgentViewModel.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.Modules.Support.LiveChats.ViewModels +{ + public class DepartmentAgentViewModel + { + public int DepartmentID { get; set; } + public int AgentID { get; set; } + public int UserID { get; set; } + public string DisplayName { get; set; } + public string ProfilePic + { + get + { + return DotNetNuke.Common.Globals.ResolveUrl("~/dnnimagehandler.ashx?mode=profilepic&w=35&userid=" + this.UserID); + } + } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/LiveChatAgentViewModel.cs b/LiveChat/ViewModels/LiveChatAgentViewModel.cs new file mode 100644 index 0000000..004d23f --- /dev/null +++ b/LiveChat/ViewModels/LiveChatAgentViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.ViewModels +{ + public class LiveChatAgentViewModel + { + public int AgentID { get; set; } + public int UserID { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public string Avatar { get; set; } + public bool IsOnline { get; set; } + public DateTime JoinDate { get; set; } + public DateTime LeftDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/LiveChatDepartmentViewModel.cs b/LiveChat/ViewModels/LiveChatDepartmentViewModel.cs new file mode 100644 index 0000000..7288148 --- /dev/null +++ b/LiveChat/ViewModels/LiveChatDepartmentViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.ViewModels +{ + public class LiveChatDepartmentViewModel + { + public int DepartmentID { get; set; } + public string DepartmentName { get; set; } + public string AgentOnlineStatus { get; set; } + public DateTime CreateDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/LiveChatViewModel.cs b/LiveChat/ViewModels/LiveChatViewModel.cs new file mode 100644 index 0000000..5a52bd3 --- /dev/null +++ b/LiveChat/ViewModels/LiveChatViewModel.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Collections; +using MyDnn.Modules.Support.LiveChat.Models; +using MyDnn.Modules.Support.LiveChat.Components.Enums; + +namespace MyDnn.Modules.Support.LiveChat.ViewModels +{ + public class LiveChatViewModel + { + /// + /// + /// + public int LiveChatID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public LiveChatVisitorViewModel Visitor { get; set; } + + /// + /// + /// + public IEnumerable Departments { get; set; } + + /// + /// + /// + public IEnumerable Agents { get; set; } + + /// + /// + /// + public string AgentDefaultAvatar { get; set; } + + /// + /// + /// + public string Message { get; set; } + + /// + /// + /// + public IEnumerable Messages { get; set; } + + /// + /// + /// + public LiveChatRating Rate { get; set; } + + /// + /// + /// + public bool ChatStarted { get; set; } + + /// + /// + /// + public bool IsClosed { get; set; } + + /// + /// + /// + public DateTime CreateDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/LiveChatVisitorViewModel.cs b/LiveChat/ViewModels/LiveChatVisitorViewModel.cs new file mode 100644 index 0000000..17aaf96 --- /dev/null +++ b/LiveChat/ViewModels/LiveChatVisitorViewModel.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.Modules.Support.LiveChat.ViewModels +{ + public class LiveChatVisitorViewModel + { + public int VisitorID { get; set; } + public int UserID { get; set; } + public string VisitorGUID { get; set; } + public string Avatar { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public string IP { get; set; } + public string LastURL { get; set; } + public string ReferrerURL { get; set; } + public string UserAgent { get; set; } + public int PastVisits { get; set; } + public int PastChats { get; set; } + public DateTime OnlineDate { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/ViewModels/ModuleConfigStatusViewModel.cs b/LiveChat/ViewModels/ModuleConfigStatusViewModel.cs new file mode 100644 index 0000000..c03a4de --- /dev/null +++ b/LiveChat/ViewModels/ModuleConfigStatusViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.Modules.Support.LiveChat.ViewModels +{ + public class ModuleConfigStatusViewModel + { + public int ModuleID { get; set; } + public int TabID { get; set; } + public bool VisitorsOnlineEnabled { get; set; } + public bool LiveChatEnabled { get; set; } + public bool BasicSettingsUpdated { get; set; } + public bool WidgetSettingsUpdated { get; set; } + } +} \ No newline at end of file diff --git a/LiveChat/Views/AdminPanel/AdminPanel.cshtml b/LiveChat/Views/AdminPanel/AdminPanel.cshtml new file mode 100644 index 0000000..a4d1f61 --- /dev/null +++ b/LiveChat/Views/AdminPanel/AdminPanel.cshtml @@ -0,0 +1,281 @@ +@using DotNetNuke.Web.Mvc.Helpers +@using DotNetNuke.Framework.JavaScriptLibraries +@using DotNetNuke.Web.Client.ClientResourceManagement +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +@{ + //Styles + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/style.css", DotNetNuke.Web.Client.FileOrder.Css.SkinCss); + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/animate.min.css"); + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/material-design-iconic-font.min.css"); + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/socicon.min.css"); + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/custom.css"); + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Styles/livechat-agent.css"); + + //Bootstrap + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap/bootstrap.min.js"); + + //AngularJS & Libraries + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/angular.min.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/angular-route.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/angular-resource.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/angular-sanitize.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/angular-animate.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angularjs/loading-bar.min.js"); + + //Ui Bootstrap For Angularjs + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/ui-bootstrap/ui-bootstrap-tpls.min.js"); + + //sweetalert + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angular-farbtastic/farbtastic.css"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/angular-farbtastic/angular-farbtastic.js"); + + //moment js + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/moment.js/moment.min.js"); + + //Jquery Plugins + + //sweetalert + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/sweetalert/sweetalert.min.css"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/sweetalert/sweetalert.min.js"); + + //nicescroll + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/jquery.nicescroll/jquery.nicescroll.min.js"); + + //jquery jscrollpane + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/jquery.jscrollpane/jquery.jscrollpane.min.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/jquery.jscrollpane/jquery.mousewheel.js"); + + //bootstrap-growl + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-growl/bootstrap-growl.min.js"); + + //waves material effect + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/waves/waves.min.js"); + + //chosen jquery + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/chosen.jquery/chosen.jquery.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/chosen.jquery/chosen.js"); + + //jquery numeric + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/jquery.numeric/jquery.numeric.js"); + + //bootstrap-select + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.css"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-select/bootstrap-select.min.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-select/angular-bootstrap-select.min.js"); + + //ua-parser user agent + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/ua-parser/ua-parser.min.js"); + + //SignalR + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/signalr/jquery.signalR-2.1.0.min.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/signalr/hubs"); + + //Custom AngularJS Services + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Services/ng-mydnn-services.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Services/signalr.service.js"); + + //Custom AngularJS App + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/app.js"); + + ////Custom AngularJS Controllers + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/home-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/visitorlist-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/history-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/department-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/agent-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/setting-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/widgetsetting-controller.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientApp/Controllers/livechat-agent-controller.js"); + + //bootstrap datetime picker + ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js"); + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/ClientComponents/bootstrap-datetimepicker/datetimepickerDirective.js"); + + //Admin Panel UI Custom Scripts + ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Scripts/functions.js"); +} + +@{ +
        + @if (!Model.VisitorsOnlineEnabled) + { + + + @Dnn.LocalizeString("VisitorsEnabledAlert") + + } + @if (!Model.LiveChatEnabled) + { + + + @Dnn.LocalizeString("VisitorsEnabledAlert") + + } + @if (!Model.BasicSettingsUpdated) + { + + + @Dnn.LocalizeString("BasicSettingsUpdatedAlert") + + } + @if (!Model.WidgetSettingsUpdated) + { + + + @Dnn.LocalizeString("BasicSettingsUpdatedAlert") + + } +
        +} + +
        + + + + + + + + + + + + + + + + + + + +
        + +@section scripts +{ + +} diff --git a/LiveChat/Views/AdminPanel/_Agents.cshtml b/LiveChat/Views/AdminPanel/_Agents.cshtml new file mode 100644 index 0000000..793a39d --- /dev/null +++ b/LiveChat/Views/AdminPanel/_Agents.cshtml @@ -0,0 +1,172 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        + +
        +

         @Dnn.LocalizeString("Agents")

        +
        + + + +
        +
        + +
        + + +
        + + +
        + +
        ").addClass("cw").text("#"));c.isBefore(l.clone().endOf("w"));)b.append(a("").addClass("dow").text(c.format("dd"))),c.add(1,"d");o.find(".datepicker-days thead").append(b)},K=function(a){return d.disabledDates[a.format("YYYY-MM-DD")]===!0},L=function(a){return d.enabledDates[a.format("YYYY-MM-DD")]===!0},M=function(a,b){return a.isValid()?d.disabledDates&&K(a)&&"M"!==b?!1:d.enabledDates&&!L(a)&&"M"!==b?!1:d.minDate&&a.isBefore(d.minDate,b)?!1:d.maxDate&&a.isAfter(d.maxDate,b)?!1:"d"===b&&-1!==d.daysOfWeekDisabled.indexOf(a.day())?!1:!0:!1},N=function(){for(var b=[],c=l.clone().startOf("y").hour(12);c.isSame(l,"y");)b.push(a("").attr("data-action","selectMonth").addClass("month").text(c.format("MMM"))),c.add(1,"M");o.find(".datepicker-months td").empty().append(b)},O=function(){var b=o.find(".datepicker-months"),c=b.find("th"),d=b.find("tbody").find("span");b.find(".disabled").removeClass("disabled"),M(l.clone().subtract(1,"y"),"y")||c.eq(0).addClass("disabled"),c.eq(1).text(l.year()),M(l.clone().add(1,"y"),"y")||c.eq(2).addClass("disabled"),d.removeClass("active"),k.isSame(l,"y")&&d.eq(k.month()).addClass("active"),d.each(function(b){M(l.clone().month(b),"M")||a(this).addClass("disabled")})},P=function(){var a=o.find(".datepicker-years"),b=a.find("th"),c=l.clone().subtract(5,"y"),e=l.clone().add(6,"y"),f="";for(a.find(".disabled").removeClass("disabled"),d.minDate&&d.minDate.isAfter(c,"y")&&b.eq(0).addClass("disabled"),b.eq(1).text(c.year()+"-"+e.year()),d.maxDate&&d.maxDate.isBefore(e,"y")&&b.eq(2).addClass("disabled");!c.isAfter(e,"y");)f+=''+c.year()+"",c.add(1,"y");a.find("td").html(f)},Q=function(){var c,e,f,g=o.find(".datepicker-days"),h=g.find("th"),i=[];if(z()){for(g.find(".disabled").removeClass("disabled"),h.eq(1).text(l.format(d.dayViewHeaderFormat)),M(l.clone().subtract(1,"M"),"M")||h.eq(0).addClass("disabled"),M(l.clone().add(1,"M"),"M")||h.eq(2).addClass("disabled"),c=l.clone().startOf("M").startOf("week");!l.clone().endOf("M").endOf("w").isBefore(c,"d");)0===c.weekday()&&(e=a("
        '+c.week()+"'+c.date()+"
        '+c.format(f?"HH":"hh")+"
        '+c.format("mm")+"
        '+c.format("ss")+"
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        @Dnn.LocalizeString("DisplayName")@Dnn.LocalizeString("Email")@Dnn.LocalizeString("Departments")@Dnn.LocalizeString("Enabled")@Dnn.LocalizeString("Priority")
        + + + + {{agent.DisplayName}}{{agent.Email}} + @Dnn.LocalizeString("NoDepartments") +
          +
        • + {{department}} +
        • +
        +
        +
        + +
        +
        {{agent.Priority}} + + +
        + + + + + + + + + diff --git a/LiveChat/Views/AdminPanel/_BasicSettings.cshtml b/LiveChat/Views/AdminPanel/_BasicSettings.cshtml new file mode 100644 index 0000000..965b7e6 --- /dev/null +++ b/LiveChat/Views/AdminPanel/_BasicSettings.cshtml @@ -0,0 +1,130 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        + +
        +

        +  @Dnn.LocalizeString("BasicSettings") + @Dnn.LocalizeString("BasicSettings.Help") +

        + +
        + +
        +
        +
        +
        +

        @Dnn.LocalizeString("BasicSettings")

        +
        +
        +
        + +
        +
        +
        +
        + +
        +
        +
        +
        + +
        +
        +
        +
        + +
        +
        +
        +
        + +
        +
        +
        +
        +
        +

        @Dnn.LocalizeString("FunctionalitySettings")

        +
        +
        +
        +

        @Dnn.LocalizeString("AgentsViewPermission")

        + + + +
        +
        +
        +
        + +
        +
        +
        +
        + +
        +
        +
        +
        +
        +

        @Dnn.LocalizeString("EmailTemplates")

        +
        +
        + + +
        +
        + + +
        + +
        +
        +
        +
        diff --git a/LiveChat/Views/AdminPanel/_Departments.cshtml b/LiveChat/Views/AdminPanel/_Departments.cshtml new file mode 100644 index 0000000..57ad955 --- /dev/null +++ b/LiveChat/Views/AdminPanel/_Departments.cshtml @@ -0,0 +1,157 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        + +
        +

         @Dnn.LocalizeString("Departments")

        +
        + + + +
        + + +
        + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        @Dnn.LocalizeString("Name")@Dnn.LocalizeString("Description")@Dnn.LocalizeString("Agents")@Dnn.LocalizeString("Ticketing")@Dnn.LocalizeString("LiveChat")
        {{department.DepartmentName}}{{department.Description}} + @Dnn.LocalizeString("NoAgents") +
          +
        • + + + + {{agent.DisplayName}} +
        • +
        +
        +
        + +
        +
        +
        + +
        +
        + + +
        + + + + + +
        +
        diff --git a/LiveChat/Views/AdminPanel/_History.cshtml b/LiveChat/Views/AdminPanel/_History.cshtml new file mode 100644 index 0000000..7d1d6ef --- /dev/null +++ b/LiveChat/Views/AdminPanel/_History.cshtml @@ -0,0 +1,205 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        + +
        +

         @Dnn.LocalizeString("Historys")

        +
          +
        • @Dnn.LocalizeString("All")
        • +
        • @Dnn.LocalizeString("Chat")
        • +
        • @Dnn.LocalizeString("Offline")
        • +
        +
        + +
        +
        + +
        +
        + + +
        + + + +
        + +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        + +
        +
        @Dnn.LocalizeString("Name")@Dnn.LocalizeString("Departments")@Dnn.LocalizeString("Agents")@Dnn.LocalizeString("Date")@Dnn.LocalizeString("Messages")
        +
        + +
        +
        {{livechat.Visitor.DisplayName}}{{department.DepartmentName}}{{agent.DisplayName}}{{livechat.CreateDate| cmdate:'MMMM D YY, h:mm a'}}{{livechat.Message}}
        + @Dnn.LocalizeString("NoMessages") +
        +
        +
        + +
        +
        + +
        +
        + +
        +
        @Dnn.LocalizeString("Messages") {{history.Paging.PageIndex*history.Paging.PageSize+1}} @Dnn.LocalizeString("To") {{history.Paging.PageIndex*history.Paging.PageSize+history.LiveChats.length}} @Dnn.LocalizeString("Of") {{history.Paging.TotalCount}}
        +
        +
        +
        +
        +
        + +
        +
        +
          +
        • @Dnn.LocalizeString("Transcript")
        • +
        • @Dnn.LocalizeString("UserInfo")
        • +
        + +
        +
        +
        Rating
        +
        Good
        +
        +
        Comment
        +
        ok bod!
        +
        +
          +
        • + {{message.SenderDisplayName}} +

          {{message.Message}}

          + {{message.Time}} +
        • +
        +
        +
        + + + + {{selectedLiveChat.Visitor.DisplayName}} + {{selectedLiveChat.Visitor.Email}} +
        +
        +
        @Dnn.LocalizeString("Location")
        + {{selectedLiveChat.Visitor.Location.city}}, {{selectedLiveChat.Visitor.Location.region_name}}, {{selectedLiveChat.Visitor.Location.country_name}} +
        @Dnn.LocalizeString("Browser")
        + {{selectedLiveChat.Visitor.UserAgentData.browser.name}} {{selectedLiveChat.Visitor.UserAgentData.browser.version}} +
        @Dnn.LocalizeString("Platform")
        + {{selectedLiveChat.Visitor.UserAgentData.os.name}} {{selectedLiveChat.Visitor.UserAgentData.os.version}} +
        @Dnn.LocalizeString("IpAddress")
        + {{selectedLiveChat.Visitor.IP}} +
        @Dnn.LocalizeString("UserAgent")
        + {{selectedLiveChat.Visitor.UserAgent}} +
        +
        +
        +
        +
        +
        diff --git a/LiveChat/Views/AdminPanel/_Home.cshtml b/LiveChat/Views/AdminPanel/_Home.cshtml new file mode 100644 index 0000000..a5fb2dc --- /dev/null +++ b/LiveChat/Views/AdminPanel/_Home.cshtml @@ -0,0 +1,3 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        \ No newline at end of file diff --git a/LiveChat/Views/AdminPanel/_LiveChats.cshtml b/LiveChat/Views/AdminPanel/_LiveChats.cshtml new file mode 100644 index 0000000..72199a6 --- /dev/null +++ b/LiveChat/Views/AdminPanel/_LiveChats.cshtml @@ -0,0 +1,108 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + + +
        + @Dnn.LocalizeString("ServeRequests") ({{serveRequests.length}}) +
        + + + +
        +
        + + + + {{livechat.Visitor.DisplayName}} + {{livechat.UnReadMessages}} +
        +
        diff --git a/LiveChat/Views/AdminPanel/_VisitorList.cshtml b/LiveChat/Views/AdminPanel/_VisitorList.cshtml new file mode 100644 index 0000000..f694c93 --- /dev/null +++ b/LiveChat/Views/AdminPanel/_VisitorList.cshtml @@ -0,0 +1,108 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        +
        +

         @Dnn.LocalizeString("VisitorList")

        +
        + +
        + +
        +
        +

        @Dnn.LocalizeString("IncomingChats")

        + + + + + + + + + + + + + + + + + + + + + + + + +
        @Dnn.LocalizeString("Visitor")@Dnn.LocalizeString("Online")@Dnn.LocalizeString("Message")@Dnn.LocalizeString("Viewing")@Dnn.LocalizeString("Referrer")
        + + + + + {{visitor.DisplayName}} + + + + + {{visitor.OnlineTime}}{{visitor.Message}}{{visitor.LastURL}}{{visitor.ReferrerURL}}
        +

        @Dnn.LocalizeString("ActiveVisitors")

        + + + + + + + + + + + + + + + + + + + + + + + +
        @Dnn.LocalizeString("Visitor")@Dnn.LocalizeString("Online")@Dnn.LocalizeString("Viewing")@Dnn.LocalizeString("Referrer")
        + + + + + {{visitor.DisplayName}} + + + + + {{visitor.OnlineTime}} + {{visitor.LastURL}} + + {{visitor.ReferrerURL}} + + @Dnn.LocalizeString("VisitorIsChatting") +
        +
        +
        + diff --git a/LiveChat/Views/AdminPanel/_WidgetSettings.cshtml b/LiveChat/Views/AdminPanel/_WidgetSettings.cshtml new file mode 100644 index 0000000..5ca3501 --- /dev/null +++ b/LiveChat/Views/AdminPanel/_WidgetSettings.cshtml @@ -0,0 +1,277 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +
        + +
        +

        +  @Dnn.LocalizeString("WidgetSettings") + @Dnn.LocalizeString("WidgetSettings.Help") +

        + +
        + +
        +
        + + + @Dnn.LocalizeString("Appearance") +
        +
        +

        @Dnn.LocalizeString("ChatWindow")

        +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + +
        + + + +
        +
        +
        + +
        + + +
        +
        +
        + +
        + +
        +
        +
        +
        +
        +

        @Dnn.LocalizeString("Concierge")

        +
        +
        + + +
        +
        + + +
        +
        +
        +
        +

        @Dnn.LocalizeString("MessageStyle")

        +
        +
        + +
        + +
        +
        +
        + +
        + + +
        +
        +
        +
        + + @Dnn.LocalizeString("Forms") +
        +
        +

        @Dnn.LocalizeString("FormItems")

        +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        +
        +
        +

        @Dnn.LocalizeString("OnlineForm")

        +
        +

        @Dnn.LocalizeString("RequireVisitorsForm")

        +
        + + +
        +
        + + +
        +
        +
        +
        +

        @Dnn.LocalizeString("OfflineForm")

        +
        +

        @Dnn.LocalizeString("AllowVisitorsSendMessage")

        +
        + + +
        +
        + + +
        +
        +
        + + @Dnn.LocalizeString("MinButton") +
        +
        +

        @Dnn.LocalizeString("MinimizedChatButton")

        +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + +
        + + + +
        +
        +
        + +
        + + + +
        +
        +
        + +
        + + + +
        +
        +
        + + +
        + +
        +
        + + @Dnn.LocalizeString("HtmlTemplate") + + +
        +
        + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + + + + diff --git a/LiveChat/Views/Home/Index.cshtml b/LiveChat/Views/Home/Index.cshtml new file mode 100644 index 0000000..61d6ff8 --- /dev/null +++ b/LiveChat/Views/Home/Index.cshtml @@ -0,0 +1,27 @@ +@inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage + +@{ + var moduleId = Dnn.ModuleContext.ModuleId; +} + +
        + @{ + string newUrl = string.Empty; + if (Dnn.PortalSettings.EnablePopUps) + { + newUrl = "?popUp=true"; + } + else + { + newUrl = "?SkinSrc=[G]Skins%2f_default%2fNo+Skin&ContainerSrc=[G]Containers%2f_default%2fNo+Container"; + } + } + + @if (DotNetNuke.Security.Permissions.ModulePermissionController.CanEditModuleContent(Dnn.ActiveModule)) + { + + + } +
        diff --git a/LiveChat/Views/Shared/_Layout.cshtml b/LiveChat/Views/Shared/_Layout.cshtml new file mode 100644 index 0000000..9da9faf --- /dev/null +++ b/LiveChat/Views/Shared/_Layout.cshtml @@ -0,0 +1,2 @@ +@RenderBody() +@RenderSection("scripts", required: false) diff --git a/LiveChat/Views/_ViewStart.cshtml b/LiveChat/Views/_ViewStart.cshtml new file mode 100644 index 0000000..184108f --- /dev/null +++ b/LiveChat/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "~/DesktopModules/MVC/MyDnnSupport/LiveChat/Views/Shared/_Layout.cshtml"; +} diff --git a/LiveChat/bin/Microsoft.AspNet.SignalR.Core.dll b/LiveChat/bin/Microsoft.AspNet.SignalR.Core.dll new file mode 100644 index 0000000..8062d21 Binary files /dev/null and b/LiveChat/bin/Microsoft.AspNet.SignalR.Core.dll differ diff --git a/LiveChat/bin/Microsoft.AspNet.SignalR.SystemWeb.dll b/LiveChat/bin/Microsoft.AspNet.SignalR.SystemWeb.dll new file mode 100644 index 0000000..870c15f Binary files /dev/null and b/LiveChat/bin/Microsoft.AspNet.SignalR.SystemWeb.dll differ diff --git a/LiveChat/bin/Microsoft.Owin.Host.SystemWeb.dll b/LiveChat/bin/Microsoft.Owin.Host.SystemWeb.dll new file mode 100644 index 0000000..98984ba Binary files /dev/null and b/LiveChat/bin/Microsoft.Owin.Host.SystemWeb.dll differ diff --git a/LiveChat/bin/Microsoft.Owin.Security.dll b/LiveChat/bin/Microsoft.Owin.Security.dll new file mode 100644 index 0000000..73e2f02 Binary files /dev/null and b/LiveChat/bin/Microsoft.Owin.Security.dll differ diff --git a/LiveChat/bin/Microsoft.Owin.dll b/LiveChat/bin/Microsoft.Owin.dll new file mode 100644 index 0000000..deb18a4 Binary files /dev/null and b/LiveChat/bin/Microsoft.Owin.dll differ diff --git a/LiveChat/bin/Microsoft.Web.Infrastructure.dll b/LiveChat/bin/Microsoft.Web.Infrastructure.dll new file mode 100644 index 0000000..85f1138 Binary files /dev/null and b/LiveChat/bin/Microsoft.Web.Infrastructure.dll differ diff --git a/LiveChat/bin/Owin.dll b/LiveChat/bin/Owin.dll new file mode 100644 index 0000000..ba6e21e Binary files /dev/null and b/LiveChat/bin/Owin.dll differ diff --git a/LiveChat/bin/System.Net.Http.Formatting.dll b/LiveChat/bin/System.Net.Http.Formatting.dll new file mode 100644 index 0000000..2471549 Binary files /dev/null and b/LiveChat/bin/System.Net.Http.Formatting.dll differ diff --git a/LiveChat/bin/System.Net.Http.WebRequest.dll b/LiveChat/bin/System.Net.Http.WebRequest.dll new file mode 100644 index 0000000..be46943 Binary files /dev/null and b/LiveChat/bin/System.Net.Http.WebRequest.dll differ diff --git a/LiveChat/bin/System.Net.Http.dll b/LiveChat/bin/System.Net.Http.dll new file mode 100644 index 0000000..78a383c Binary files /dev/null and b/LiveChat/bin/System.Net.Http.dll differ diff --git a/LiveChat/bin/System.Web.Http.WebHost.dll b/LiveChat/bin/System.Web.Http.WebHost.dll new file mode 100644 index 0000000..1dfa8d2 Binary files /dev/null and b/LiveChat/bin/System.Web.Http.WebHost.dll differ diff --git a/LiveChat/bin/System.Web.Http.dll b/LiveChat/bin/System.Web.Http.dll new file mode 100644 index 0000000..206c331 Binary files /dev/null and b/LiveChat/bin/System.Web.Http.dll differ diff --git a/LiveChat/bin/System.Web.Mvc.dll b/LiveChat/bin/System.Web.Mvc.dll new file mode 100644 index 0000000..2dfddfe Binary files /dev/null and b/LiveChat/bin/System.Web.Mvc.dll differ diff --git a/LiveChat/bin/System.Web.Optimization.dll b/LiveChat/bin/System.Web.Optimization.dll new file mode 100644 index 0000000..8d143e5 Binary files /dev/null and b/LiveChat/bin/System.Web.Optimization.dll differ diff --git a/LiveChat/bin/System.Web.Razor.dll b/LiveChat/bin/System.Web.Razor.dll new file mode 100644 index 0000000..8d5870d Binary files /dev/null and b/LiveChat/bin/System.Web.Razor.dll differ diff --git a/LiveChat/bin/System.Web.WebPages.Deployment.dll b/LiveChat/bin/System.Web.WebPages.Deployment.dll new file mode 100644 index 0000000..0ac2066 Binary files /dev/null and b/LiveChat/bin/System.Web.WebPages.Deployment.dll differ diff --git a/LiveChat/bin/System.Web.WebPages.Razor.dll b/LiveChat/bin/System.Web.WebPages.Razor.dll new file mode 100644 index 0000000..7fcae43 Binary files /dev/null and b/LiveChat/bin/System.Web.WebPages.Razor.dll differ diff --git a/LiveChat/bin/System.Web.WebPages.dll b/LiveChat/bin/System.Web.WebPages.dll new file mode 100644 index 0000000..76c6d94 Binary files /dev/null and b/LiveChat/bin/System.Web.WebPages.dll differ diff --git a/LiveChat/obj/Debug/DesignTimeResolveAssemblyReferences.cache b/LiveChat/obj/Debug/DesignTimeResolveAssemblyReferences.cache new file mode 100644 index 0000000..3952ee3 Binary files /dev/null and b/LiveChat/obj/Debug/DesignTimeResolveAssemblyReferences.cache differ diff --git a/LiveChat/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/LiveChat/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..b52167d Binary files /dev/null and b/LiveChat/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.csproj.FileListAbsolute.txt b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..fbc254b --- /dev/null +++ b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.csproj.FileListAbsolute.txt @@ -0,0 +1,50 @@ +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\MyDnn.Modules.Support.LiveChat.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\MyDnn.Modules.Support.LiveChat.pdb +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\ClientDependency.Core.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.Instrumentation.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.Web.Client.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.Web.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.Web.Mvc.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.Web.Razor.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.AspNet.SignalR.Core.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.AspNet.SignalR.SystemWeb.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.Owin.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.Owin.Host.SystemWeb.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.Owin.Security.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.Web.Infrastructure.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\MyDnn.VisitorsOnline.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Owin.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Net.Http.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Net.Http.Formatting.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Net.Http.WebRequest.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.Http.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.Mvc.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.Optimization.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.Razor.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.WebPages.Deployment.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.WebPages.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.WebPages.Razor.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.WebControls.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\CountryListBox.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.WebUtility.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\SharpZipLib.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Telerik.Web.UI.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.Services.Syndication.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Lucene.Net.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Lucene.Net.Contrib.FastVectorHighlighter.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\PetaPoco.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\SchwabenCode.QuickIO.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.ApplicationBlocks.Data.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\dotnetnuke.log4net.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\WebFormsMvp.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\DotNetNuke.HttpModules.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\MyDnn.VisitorsOnline.pdb +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.Razor.xml +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\Microsoft.Web.Infrastructure.xml +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.WebPages.xml +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.WebPages.Deployment.xml +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\bin\System.Web.WebPages.Razor.xml +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\obj\Debug\MyDnn.Modules.Support.LiveChat.csprojResolveAssemblyReference.cache +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\obj\Debug\MyDnn.Modules.Support.LiveChat.dll +F:\MyDnnPackage\dnn8contest\Website\DesktopModules\MVC\MyDnnSupport\LiveChat\obj\Debug\MyDnn.Modules.Support.LiveChat.pdb diff --git a/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.csprojResolveAssemblyReference.cache b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.csprojResolveAssemblyReference.cache new file mode 100644 index 0000000..4abb3eb Binary files /dev/null and b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.csprojResolveAssemblyReference.cache differ diff --git a/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.dll b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.dll new file mode 100644 index 0000000..17fefe4 Binary files /dev/null and b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.dll differ diff --git a/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.pdb b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.pdb new file mode 100644 index 0000000..3a3fc55 Binary files /dev/null and b/LiveChat/obj/Debug/MyDnn.Modules.Support.LiveChat.pdb differ diff --git a/LiveChat/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/LiveChat/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 0000000..e69de29 diff --git a/LiveChat/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/LiveChat/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 0000000..e69de29 diff --git a/LiveChat/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/LiveChat/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 0000000..e69de29 diff --git a/MyDnn.Modules.Support.LiveChat.sln b/MyDnn.Modules.Support.LiveChat.sln new file mode 100644 index 0000000..eae0339 --- /dev/null +++ b/MyDnn.Modules.Support.LiveChat.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyDnn.Modules.Support.LiveChat", "LiveChat\MyDnn.Modules.Support.LiveChat.csproj", "{0341E00F-4C86-40DD-9434-9C5FCD8A7801}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyDnn.SignalRStartup", "MyDnnSignalRStartup\MyDnn.SignalRStartup.csproj", "{B48F0D30-EDBB-4082-8AD7-F5E88C699270}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyDnn.VisitorsOnline", "MyDnnVisitorsOnline\MyDnn.VisitorsOnline.csproj", "{AA9FE893-27C4-494A-9287-FE235ACB9EBF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0341E00F-4C86-40DD-9434-9C5FCD8A7801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0341E00F-4C86-40DD-9434-9C5FCD8A7801}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0341E00F-4C86-40DD-9434-9C5FCD8A7801}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0341E00F-4C86-40DD-9434-9C5FCD8A7801}.Release|Any CPU.Build.0 = Release|Any CPU + {B48F0D30-EDBB-4082-8AD7-F5E88C699270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B48F0D30-EDBB-4082-8AD7-F5E88C699270}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B48F0D30-EDBB-4082-8AD7-F5E88C699270}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B48F0D30-EDBB-4082-8AD7-F5E88C699270}.Release|Any CPU.Build.0 = Release|Any CPU + {AA9FE893-27C4-494A-9287-FE235ACB9EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA9FE893-27C4-494A-9287-FE235ACB9EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA9FE893-27C4-494A-9287-FE235ACB9EBF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA9FE893-27C4-494A-9287-FE235ACB9EBF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MyDnnSignalRStartup/MyDnn.SignalRStartup.csproj b/MyDnnSignalRStartup/MyDnn.SignalRStartup.csproj new file mode 100644 index 0000000..4bf52dc --- /dev/null +++ b/MyDnnSignalRStartup/MyDnn.SignalRStartup.csproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + + + 2.0 + {B48F0D30-EDBB-4082-8AD7-F5E88C699270} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + MyDnn.SignalRStartup + MyDnn.SignalRStartup + v4.5 + false + + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\ + TRACE + prompt + 4 + false + + + + ..\MyDnnVisitorsOnline\bin\Microsoft.AspNet.SignalR.Core.dll + + + + ..\MyDnnVisitorsOnline\bin\Microsoft.Owin.dll + + + ..\MyDnnVisitorsOnline\bin\Owin.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + False + True + 48352 + / + + + False + False + + + False + + + + + + + + + + \ No newline at end of file diff --git a/MyDnnSignalRStartup/MyDnn.SignalRStartup.csproj.user b/MyDnnSignalRStartup/MyDnn.SignalRStartup.csproj.user new file mode 100644 index 0000000..dedb3c9 --- /dev/null +++ b/MyDnnSignalRStartup/MyDnn.SignalRStartup.csproj.user @@ -0,0 +1,28 @@ + + + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + False + True + + + + + \ No newline at end of file diff --git a/MyDnnSignalRStartup/Properties/AssemblyInfo.cs b/MyDnnSignalRStartup/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..50f4e1b --- /dev/null +++ b/MyDnnSignalRStartup/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MyDnn.Modules.ChatRom")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MyDnn.Modules.ChatRom")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3df8f730-3fb8-482b-8315-32a7c4534664")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MyDnnSignalRStartup/Startup.cs b/MyDnnSignalRStartup/Startup.cs new file mode 100644 index 0000000..7f2f9d4 --- /dev/null +++ b/MyDnnSignalRStartup/Startup.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNet.SignalR; +using Microsoft.Owin; +using MyDnn.SignalRStartup; +using Owin; +using System; + + +[assembly: OwinStartup(typeof(Startup))] +namespace MyDnn.SignalRStartup +{ + public class Startup + { + public void Configuration(IAppBuilder app) + { + app.MapSignalR(); + } + } +} \ No newline at end of file diff --git a/MyDnnSignalRStartup/bin/Microsoft.AspNet.SignalR.Core.dll b/MyDnnSignalRStartup/bin/Microsoft.AspNet.SignalR.Core.dll new file mode 100644 index 0000000..8062d21 Binary files /dev/null and b/MyDnnSignalRStartup/bin/Microsoft.AspNet.SignalR.Core.dll differ diff --git a/MyDnnSignalRStartup/bin/Microsoft.Owin.Security.dll b/MyDnnSignalRStartup/bin/Microsoft.Owin.Security.dll new file mode 100644 index 0000000..73e2f02 Binary files /dev/null and b/MyDnnSignalRStartup/bin/Microsoft.Owin.Security.dll differ diff --git a/MyDnnSignalRStartup/bin/Microsoft.Owin.dll b/MyDnnSignalRStartup/bin/Microsoft.Owin.dll new file mode 100644 index 0000000..deb18a4 Binary files /dev/null and b/MyDnnSignalRStartup/bin/Microsoft.Owin.dll differ diff --git a/MyDnnSignalRStartup/bin/MyDnn.SignalRStartup.dll b/MyDnnSignalRStartup/bin/MyDnn.SignalRStartup.dll new file mode 100644 index 0000000..e6aa95c Binary files /dev/null and b/MyDnnSignalRStartup/bin/MyDnn.SignalRStartup.dll differ diff --git a/MyDnnSignalRStartup/bin/Owin.dll b/MyDnnSignalRStartup/bin/Owin.dll new file mode 100644 index 0000000..ba6e21e Binary files /dev/null and b/MyDnnSignalRStartup/bin/Owin.dll differ diff --git a/MyDnnSignalRStartup/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/MyDnnSignalRStartup/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..e3d5739 Binary files /dev/null and b/MyDnnSignalRStartup/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/MyDnnSignalRStartup/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/MyDnnSignalRStartup/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 0000000..e69de29 diff --git a/MyDnnSignalRStartup/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/MyDnnSignalRStartup/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 0000000..e69de29 diff --git a/MyDnnSignalRStartup/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/MyDnnSignalRStartup/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 0000000..e69de29 diff --git a/MyDnnSignalRStartup/packages.config b/MyDnnSignalRStartup/packages.config new file mode 100644 index 0000000..f542a44 --- /dev/null +++ b/MyDnnSignalRStartup/packages.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Api/VisitorsOnlineApi.cs b/MyDnnVisitorsOnline/Api/VisitorsOnlineApi.cs new file mode 100644 index 0000000..0dd7804 --- /dev/null +++ b/MyDnnVisitorsOnline/Api/VisitorsOnlineApi.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using MyDnn.VisitorsOnline.Models; +using MyDnn.VisitorsOnline.Components; + +namespace MyDnn.VisitorsOnline.Api +{ + /// + /// + /// + public class VisitorsOnlineApi + { + /// + /// + /// + public static VisitorsOnlineApi Instance + { + get + { + return new VisitorsOnlineApi(); + } + } + + /// + /// + /// + /// + /// + public IEnumerable GetVisitorsOnline(int portalID) + { + return VisitorOnlineManager.Instance.GetVisitorsOnline(portalID); + } + /// + /// + /// + /// + /// + /// + public OnlineVisitorInfo GetVisitorByUserID(int portalID, int userID) + { + return VisitorOnlineManager.Instance.GetVisitorByUserID(portalID, userID); + } + + /// + /// + /// + /// + /// + /// + public OnlineVisitorInfo GetVisitorByGUID(int portalID, string visitorGUID) + { + return VisitorOnlineManager.Instance.GetVisitorByGUID(portalID, visitorGUID); + } + + /// + /// + /// + /// + /// + /// + public bool IsVisitorOnline(int portalID, int userID) + { + return VisitorOnlineManager.Instance.IsVisitorOnline(portalID, userID); + } + + /// + /// + /// + /// + /// + public int AddListener(ListenerInfo objListenerInfo) + { + return ListenerManager.Instance.AddListener(objListenerInfo); + } + + /// + /// + /// + /// + /// + public IEnumerable GetListeners(int portalID) + { + return ListenerManager.Instance.GetListeners(portalID); + } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/App_Start/PreApplicationStartCode.cs b/MyDnnVisitorsOnline/App_Start/PreApplicationStartCode.cs new file mode 100644 index 0000000..45b303f --- /dev/null +++ b/MyDnnVisitorsOnline/App_Start/PreApplicationStartCode.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using Microsoft.Web.Infrastructure.DynamicModuleHelper; +using MyDnn.VisitorsOnline.App_Start; + +[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")] +namespace MyDnn.VisitorsOnline.App_Start +{ + public class PreApplicationStartCode + { + public static void Start() + { + // Register our module + DynamicModuleUtility.RegisterModule(typeof(MyDnnVisitorsOnlineHttpModule)); + } + } + + public class MyDnnVisitorsOnlineHttpModule : IHttpModule + { + #region IHttpModule Members + + public void Dispose() + { + } + + public void Init(HttpApplication context) + { + context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute); + } + + #endregion + + protected void context_PreRequestHandlerExecute(object sender, EventArgs e) + { + try + { + HttpContext currentContext = HttpContext.Current; + Page page = currentContext.CurrentHandler as Page; + + if (page != null) + { + page.LoadComplete += new EventHandler(page_LoadComplete); + } + } + catch (Exception) + { + } + } + + protected void page_LoadComplete(object sender, EventArgs e) + { + try + { + Page page = sender as Page; + + if (page.IsCallback == false && page.IsPostBack == false) + { + if (!page.ClientScript.IsClientScriptIncludeRegistered("MydnnVisitorsOnlineInit")) + { + page.ClientScript.RegisterClientScriptInclude("MydnnVisitorsOnlineInit", DotNetNuke.Common.Globals.ResolveUrl("~/DesktopModules/MVC/MyDnnSupport/LiveChat/Scripts/visitors-online.js")); + } + } + } + catch (Exception) + { + } + } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/App_Start/RouteMapper.cs b/MyDnnVisitorsOnline/App_Start/RouteMapper.cs new file mode 100644 index 0000000..fc4d26a --- /dev/null +++ b/MyDnnVisitorsOnline/App_Start/RouteMapper.cs @@ -0,0 +1,14 @@ +using System.Web.Routing; +using DotNetNuke.Web.Api; +using System; + +namespace MyDnn.VisitorsOnline.App_Start +{ + public class RouteMapper : IServiceRouteMapper + { + public void RegisterRoutes(IMapRoute mapRouteManager) + { + mapRouteManager.MapHttpRoute("MyDnnVisitorsOnline", "default", "{controller}/{action}", new[] { "MyDnn.VisitorsOnline.Services" }); + } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Bin/Microsoft.AspNet.SignalR.Core.dll b/MyDnnVisitorsOnline/Bin/Microsoft.AspNet.SignalR.Core.dll new file mode 100644 index 0000000..8062d21 Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Microsoft.AspNet.SignalR.Core.dll differ diff --git a/MyDnnVisitorsOnline/Bin/Microsoft.AspNet.SignalR.SystemWeb.dll b/MyDnnVisitorsOnline/Bin/Microsoft.AspNet.SignalR.SystemWeb.dll new file mode 100644 index 0000000..870c15f Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Microsoft.AspNet.SignalR.SystemWeb.dll differ diff --git a/MyDnnVisitorsOnline/Bin/Microsoft.Owin.Host.SystemWeb.dll b/MyDnnVisitorsOnline/Bin/Microsoft.Owin.Host.SystemWeb.dll new file mode 100644 index 0000000..98984ba Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Microsoft.Owin.Host.SystemWeb.dll differ diff --git a/MyDnnVisitorsOnline/Bin/Microsoft.Owin.Security.dll b/MyDnnVisitorsOnline/Bin/Microsoft.Owin.Security.dll new file mode 100644 index 0000000..73e2f02 Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Microsoft.Owin.Security.dll differ diff --git a/MyDnnVisitorsOnline/Bin/Microsoft.Owin.dll b/MyDnnVisitorsOnline/Bin/Microsoft.Owin.dll new file mode 100644 index 0000000..deb18a4 Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Microsoft.Owin.dll differ diff --git a/MyDnnVisitorsOnline/Bin/Microsoft.Web.Infrastructure.dll b/MyDnnVisitorsOnline/Bin/Microsoft.Web.Infrastructure.dll new file mode 100644 index 0000000..85f1138 Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Microsoft.Web.Infrastructure.dll differ diff --git a/MyDnnVisitorsOnline/Bin/Owin.dll b/MyDnnVisitorsOnline/Bin/Owin.dll new file mode 100644 index 0000000..ba6e21e Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/Owin.dll differ diff --git a/MyDnnVisitorsOnline/Bin/System.Net.Http.Formatting.dll b/MyDnnVisitorsOnline/Bin/System.Net.Http.Formatting.dll new file mode 100644 index 0000000..9e3f6ef Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/System.Net.Http.Formatting.dll differ diff --git a/MyDnnVisitorsOnline/Bin/System.Web.Http.WebHost.dll b/MyDnnVisitorsOnline/Bin/System.Web.Http.WebHost.dll new file mode 100644 index 0000000..1dfa8d2 Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/System.Web.Http.WebHost.dll differ diff --git a/MyDnnVisitorsOnline/Bin/System.Web.Http.dll b/MyDnnVisitorsOnline/Bin/System.Web.Http.dll new file mode 100644 index 0000000..edd9922 Binary files /dev/null and b/MyDnnVisitorsOnline/Bin/System.Web.Http.dll differ diff --git a/MyDnnVisitorsOnline/Components/Enums/LoginState.cs b/MyDnnVisitorsOnline/Components/Enums/LoginState.cs new file mode 100644 index 0000000..6e2f076 --- /dev/null +++ b/MyDnnVisitorsOnline/Components/Enums/LoginState.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.VisitorsOnline.Components.Enums +{ + public enum LoginState + { + LoggedIn, + LoggedOff, + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Components/IListenerManager.cs b/MyDnnVisitorsOnline/Components/IListenerManager.cs new file mode 100644 index 0000000..79a4acf --- /dev/null +++ b/MyDnnVisitorsOnline/Components/IListenerManager.cs @@ -0,0 +1,52 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Linq; +using DotNetNuke.Collections; +using System.Collections.Generic; +using MyDnn.VisitorsOnline.Models; + +namespace MyDnn.VisitorsOnline.Components +{ + /// + /// + /// + interface IListenerManager + { + /// + /// + /// + /// + /// + int AddListener(ListenerInfo objListenerInfo); + + /// + /// + /// + /// + void UpdateListener(ListenerInfo objListenerInfo); + + /// + /// + /// + /// + void DeleteListener(ListenerInfo objListenerInfo); + + /// + /// + /// + /// + /// + /// + ListenerInfo GetListener(int listenerID, int portalID); + + /// + /// + /// + /// + /// + IEnumerable GetListeners(int portalID); + } +} + + diff --git a/MyDnnVisitorsOnline/Components/IRoleOnlineManager.cs b/MyDnnVisitorsOnline/Components/IRoleOnlineManager.cs new file mode 100644 index 0000000..a9ddcbd --- /dev/null +++ b/MyDnnVisitorsOnline/Components/IRoleOnlineManager.cs @@ -0,0 +1,61 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Linq; +using DotNetNuke.Collections; +using System.Collections.Generic; +using MyDnn.VisitorsOnline.Models; + +namespace MyDnn.VisitorsOnline.Components +{ + /// + /// + /// + interface IRoleOnlineManager + { + /// + /// + /// + /// + void AddRoleOnline(OnlineRoleInfo objOnlineRoleInfo); + + /// + /// + /// + /// + void DeleteRoleOnline(OnlineRoleInfo objOnlineRoleInfo); + + /// + /// + /// + /// + /// + /// + OnlineRoleInfo GetRoleOnline(int portalID, string roleName); + + /// + /// + /// + /// + /// + /// + bool IsRoleOnline(int portalID, string roleName); + + /// + /// + /// + /// + /// + IEnumerable GetRolesOnline(int portalID); + + /// + /// + /// + /// + /// + /// + IEnumerable GetSuperUserRoles(int portalID, int userID); + } +} + + diff --git a/MyDnnVisitorsOnline/Components/IVisitorManager.cs b/MyDnnVisitorsOnline/Components/IVisitorManager.cs new file mode 100644 index 0000000..5c6a42c --- /dev/null +++ b/MyDnnVisitorsOnline/Components/IVisitorManager.cs @@ -0,0 +1,88 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Linq; +using DotNetNuke.Collections; +using System.Collections.Generic; +using MyDnn.VisitorsOnline.Models; + +namespace MyDnn.VisitorsOnline.Components +{ + /// + /// + /// + interface IVisitorOnlineManager + { + /// + /// + /// + /// + /// + void AddVisitorOnline(OnlineVisitorInfo objOnlineVisitorInfo, string connectionID); + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + void UpdateVisitorOnline(int portalID, string visitorGUID, string userName, string displayName, string email, string lastUrl, string connectionID, bool isUpdateInfo); + + /// + /// + /// + /// + void Ping(string visitorGUID); + + /// + /// + /// + /// + void DeleteConnection(string connectionId); + + /// + /// + /// + /// + /// + IEnumerable PurgeVisitorsOnline(int portalID); + + /// + /// + /// + /// + /// + /// + OnlineVisitorInfo GetVisitorByUserID(int portalID, int userID); + + /// + /// + /// + /// + /// + /// + OnlineVisitorInfo GetVisitorByGUID(int portalID, string visitorGUID); + + /// + /// + /// + /// + /// + /// + bool IsVisitorOnline(int portalID, int userid); + + /// + /// + /// + /// + /// + IEnumerable GetVisitorsOnline(int portalID); + } +} + + diff --git a/MyDnnVisitorsOnline/Components/ListenerManager.cs b/MyDnnVisitorsOnline/Components/ListenerManager.cs new file mode 100644 index 0000000..71ffe25 --- /dev/null +++ b/MyDnnVisitorsOnline/Components/ListenerManager.cs @@ -0,0 +1,111 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Xml.Linq; +using DotNetNuke.Framework; +using DotNetNuke.Common; +using DotNetNuke.Data; +using MyDnn.VisitorsOnline.Models; + +namespace MyDnn.VisitorsOnline.Components +{ + /// + /// + /// + internal class ListenerManager : ServiceLocator, IListenerManager + { + protected override Func GetFactory() + { + return () => new ListenerManager(); + } + + /// + /// + /// + private const string CachePrefix = "MyDnnListener_"; + + /// + /// + /// + /// + /// + public int AddListener(ListenerInfo objListenerInfo) + { + Requires.NotNull(objListenerInfo); + Requires.PropertyNotNegative(objListenerInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objListenerInfo); + return objListenerInfo.ListenerID; + } + } + + /// + /// + /// + /// + public void UpdateListener(ListenerInfo objListenerInfo) + { + Requires.NotNull(objListenerInfo); + Requires.PropertyNotNegative(objListenerInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objListenerInfo); + } + } + + /// + /// + /// + /// + public void DeleteListener(ListenerInfo objListenerInfo) + { + Requires.NotNull(objListenerInfo); + Requires.PropertyNotNegative(objListenerInfo, "ListenerID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Update(objListenerInfo); + } + } + + /// + /// + /// + /// + /// + /// + public ListenerInfo GetListener(int portalID,int listenerID) + { + Requires.NotNegative("listenerID", listenerID); + Requires.NotNegative("portalID", portalID); + + return GetListeners(portalID).SingleOrDefault(l => l.ListenerID == listenerID); + } + + /// + /// + /// + /// + /// + public IEnumerable GetListeners(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(portalID); + } + } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Components/RoleOnlineManager.cs b/MyDnnVisitorsOnline/Components/RoleOnlineManager.cs new file mode 100644 index 0000000..2f2cca9 --- /dev/null +++ b/MyDnnVisitorsOnline/Components/RoleOnlineManager.cs @@ -0,0 +1,143 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.Common.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Xml.Linq; +using DotNetNuke.Framework; +using DotNetNuke.Common; +using DotNetNuke.Data; +using MyDnn.VisitorsOnline.Models; + +namespace MyDnn.VisitorsOnline.Components +{ + /// + /// + /// + internal class RoleOnlineManager : ServiceLocator, IRoleOnlineManager + { + protected override Func GetFactory() + { + return () => new RoleOnlineManager(); + } + + /// + /// + /// + private const string CachePrefix = "MyDnnRoleOnline_"; + + /// + /// + /// + public string DatabaseOwner + { + get + { + return DataProvider.Instance().DatabaseOwner; + } + } + + /// + /// + /// + public string ObjectQualifier + { + get + { + return DataProvider.Instance().ObjectQualifier; + } + } + + /// + /// + /// + /// + public void AddRoleOnline(OnlineRoleInfo objOnlineRoleInfo) + { + Requires.NotNull(objOnlineRoleInfo); + Requires.PropertyNotNegative(objOnlineRoleInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Insert(objOnlineRoleInfo); + } + } + + /// + /// + /// + /// + public void DeleteRoleOnline(OnlineRoleInfo objOnlineRoleInfo) + { + Requires.NotNull(objOnlineRoleInfo); + Requires.PropertyNotNegative(objOnlineRoleInfo, "PortalID"); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + rep.Delete(objOnlineRoleInfo); + } + } + + /// + /// + /// + /// + /// + /// + public OnlineRoleInfo GetRoleOnline(int portalID, string roleName) + { + Requires.NotNegative("portalID", portalID); + + return GetRolesOnline(portalID).SingleOrDefault(l => l.PortalID == portalID && l.RoleName == roleName); + } + + /// + /// + /// + /// + /// + /// + public bool IsRoleOnline(int portalID, string roleName) + { + Requires.NotNegative("portalID", portalID); + + return GetRolesOnline(portalID).Where(l => l.PortalID == portalID && l.RoleName == roleName).Any(); + } + + /// + /// + /// + /// + /// + public IEnumerable GetRolesOnline(int portalID) + { + Requires.NotNegative("portalID", portalID); + + using (IDataContext ctx = DataContext.Instance()) + { + var rep = ctx.GetRepository(); + return rep.Get(portalID); + } + } + + /// + /// + /// + /// + /// + /// + public IEnumerable GetSuperUserRoles(int portalID, int userID) + { + using (IDataContext ctx = DataContext.Instance()) + { + var roles = ctx.ExecuteQuery(System.Data.CommandType.Text, string.Format("Select Distinct [RoleID] From {0}[{1}UserRoles] Where [UserID]={2}", DatabaseOwner, ObjectQualifier, userID)); + return DotNetNuke.Security.Roles.RoleController.Instance.GetRoles(portalID).Join(roles, r => r.RoleID, ur => ur, (r, ur) => r.RoleName); + } + } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Components/VisitorOnlineManager.cs b/MyDnnVisitorsOnline/Components/VisitorOnlineManager.cs new file mode 100644 index 0000000..3227c70 --- /dev/null +++ b/MyDnnVisitorsOnline/Components/VisitorOnlineManager.cs @@ -0,0 +1,180 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Framework; +using MyDnn.VisitorsOnline.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace MyDnn.VisitorsOnline.Components +{ + /// + /// + /// + internal class VisitorOnlineManager : ServiceLocator, IVisitorOnlineManager + { + protected override Func GetFactory() + { + return () => new VisitorOnlineManager(); + } + + /// + /// + /// + private const string CachePrefix = "VisitorsOnline_"; + + /// + /// + /// + /// + /// + public void AddVisitorOnline(OnlineVisitorInfo objOnlineVisitorInfo, string connectionID) + { + Requires.NotNull(objOnlineVisitorInfo); + + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnVisitorsOnline_Add", objOnlineVisitorInfo.PortalID, + objOnlineVisitorInfo.VisitorGUID, + objOnlineVisitorInfo.UserName, + objOnlineVisitorInfo.DisplayName, + objOnlineVisitorInfo.Email, + objOnlineVisitorInfo.OnlineDate, + objOnlineVisitorInfo.IP, + objOnlineVisitorInfo.UserAgent, + objOnlineVisitorInfo.LastURL, + objOnlineVisitorInfo.ReferrerURL, + connectionID); + } + + string cacheKey = CachePrefix + objOnlineVisitorInfo.PortalID; + DataCache.ClearCache(cacheKey); + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void UpdateVisitorOnline(int portalID, string visitorGUID, string userName, string displayName, string email, string lastUrl, string connectionID, bool isUpdateInfo) + { + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnVisitorsOnline_Update", portalID, visitorGUID, userName, displayName, email, lastUrl, connectionID, isUpdateInfo); + } + + string cacheKey = CachePrefix + portalID; + DataCache.ClearCache(cacheKey); + } + + /// + /// + /// + /// + public void Ping(string visitorGUID) + { + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnVisitorsOnline_Ping", visitorGUID); + } + } + + /// + /// + /// + /// + public void DeleteConnection(string connectionId) + { + using (IDataContext ctx = DataContext.Instance()) + { + ctx.Execute(System.Data.CommandType.StoredProcedure, "MyDnnVisitorsOnline_DeleteConnection", connectionId); + } + } + + /// + /// + /// + /// + /// + public IEnumerable PurgeVisitorsOnline(int portalID) + { + IEnumerable result; + using (IDataContext ctx = DataContext.Instance()) + { + result = ctx.ExecuteQuery(System.Data.CommandType.StoredProcedure, "MyDnnVisitorsOnline_PurgeVisitorsOnline"); + + string cacheKey = CachePrefix + portalID; + DataCache.ClearCache(cacheKey); + + return result; + } + } + + /// + /// + /// + /// + /// + /// + public OnlineVisitorInfo GetVisitorByUserID(int portalID, int userID) + { + var visitors = GetVisitorsOnline(portalID); + return visitors.SingleOrDefault(u => u.UserID == userID); + } + + /// + /// + /// + /// + /// + /// + public OnlineVisitorInfo GetVisitorByGUID(int portalID, string visitorGUID) + { + var visitors = GetVisitorsOnline(portalID); + return visitors.SingleOrDefault(u => u.VisitorGUID == visitorGUID); + } + + /// + /// + /// + /// + /// + /// + public bool IsVisitorOnline(int portalID, int userID) + { + var visitors = GetVisitorsOnline(portalID); + return (visitors != null ? visitors.Any(v => v.UserID == userID) : false); + } + + /// + /// + /// + /// + /// + public IEnumerable GetVisitorsOnline(int portalID) + { + string cacheKey = CachePrefix + portalID; + var result = DataCache.GetCache>(cacheKey); + if (result == null) + { + using (IDataContext ctx = DataContext.Instance()) + { + result = ctx.ExecuteQuery(System.Data.CommandType.StoredProcedure, "MyDnnVisitorsOnline_GetAll", portalID); + DataCache.SetCache(cacheKey, result); + } + } + return result; + } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Hubs/VisitorsOnlineHub.cs b/MyDnnVisitorsOnline/Hubs/VisitorsOnlineHub.cs new file mode 100644 index 0000000..b9d771b --- /dev/null +++ b/MyDnnVisitorsOnline/Hubs/VisitorsOnlineHub.cs @@ -0,0 +1,328 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Microsoft.AspNet.SignalR; +using System.Threading.Tasks; +using Microsoft.AspNet.SignalR.Hubs; +using DotNetNuke.Entities.Portals; +using System.Threading; +using MyDnn.VisitorsOnline.Components; +using MyDnn.VisitorsOnline.Models; +using DotNetNuke.Entities.Users; +using MyDnn.VisitorsOnline.Components.Enums; + +namespace MyDnn.VisitorsOnline.Hubs +{ + /// + /// + /// + [HubName("MyDnnVisitorsOnlineHub")] + public class VisitorsOnlineHub : Hub + { + #region Variable && Properties + + /// + /// + /// + private string UserName + { + get + { + if (Context.User.Identity.IsAuthenticated) + { + return Context.User.Identity.Name; + } + else + return string.Empty; + } + } + + /// + /// + /// + private static Timer PurgeVisitorOnlineTimer { get; set; } + + #endregion + + #region Override Methods + + /// + /// + /// + /// + public override Task OnConnected() + { + return base.OnConnected(); + } + + /// + /// + /// + /// + public override Task OnReconnected() + { + return base.OnReconnected(); + } + + /// + /// + /// + /// + /// + public override Task OnDisconnected(bool stopCalled) + { + VisitorOnlineManager.Instance.DeleteConnection(Context.ConnectionId); + return base.OnDisconnected(stopCalled); + } + + #endregion + + #region Hub Methods + + /// + /// + /// + /// + /// + /// + /// + /// + public void JoinVisitor(int portalID, string visitorGUID, string name, string email, string referrerDomain) + { + if (PurgeVisitorOnlineTimer == null) + PurgeVisitorOnlineTimer = new Timer(new TimerCallback(this.PurgeVisitorOnline), portalID, 59000, 59000); + + bool isUpdated = false; + bool checkRoles = true; + + var visitor = VisitorOnlineManager.Instance.GetVisitorByGUID(portalID, visitorGUID); + string lastUrl = this.getURL(); + string userName = this.UserName; + + if (visitor == null) + { + visitor = new OnlineVisitorInfo() + { + VisitorGUID = visitorGUID, + PortalID = portalID, + UserName = userName, + DisplayName = name, + Email = email, + OnlineDate = DateTime.Now, + IP = getIpAddress(), + UserAgent = getVisitorAgent(), + LastURL = lastUrl, + ReferrerURL = referrerDomain, + }; + VisitorOnlineManager.Instance.AddVisitorOnline(visitor, Context.ConnectionId); + } + else + { + VisitorOnlineManager.Instance.UpdateVisitorOnline(portalID, visitorGUID, userName, visitor.DisplayName, visitor.Email, lastUrl, Context.ConnectionId, false); + isUpdated = true; + } + + if (isUpdated) + { + if (!string.IsNullOrEmpty(visitor.UserName) && string.IsNullOrEmpty(userName)) // in yani user login bode va logoff shode + OfflineRoles(portalID); + else if (!string.IsNullOrEmpty(visitor.UserName) && !string.IsNullOrEmpty(userName)) // in yani user az ghabl login bode va niazi be check kardane role haye an nist + checkRoles = false; + + //in ghesmat ro baraye in neveshtam ke agar visitor faghat urlesh taghir karde kole visitor ro dobare fetch nakone va faghat urlesh taghir kone + if (visitor.UserName == userName) // in yani user login bode va logoff shode + visitor.LastURL = lastUrl; + else + visitor = VisitorOnlineManager.Instance.GetVisitorByGUID(portalID, visitorGUID); + + Clients.Group("MyDnnVisitorsOnline").updateVisitorInfo(visitor); + } + else + { + if (!string.IsNullOrEmpty(visitor.UserName)) // agar user login shod visitor dobare bayad get shavad ta displayname va emailash ham biayad + visitor = VisitorOnlineManager.Instance.GetVisitorByGUID(portalID, visitorGUID); + + Clients.Group("MyDnnVisitorsOnline").populateVisitorsOnline(visitor); + } + + if (!string.IsNullOrEmpty(visitor.UserName) && checkRoles) //zamani ke yek karbar login mikonad bayad naghshhaye karbar baresi shavad va chenanche naghshe karbar joze listener ha bod script marbote ejra shavad + { + var user = UserController.GetUserByName(visitor.UserName); + + var rolesOnline = RoleOnlineManager.Instance.GetRolesOnline(portalID); + + IEnumerable roles; + if (user.IsSuperUser) + roles = RoleOnlineManager.Instance.GetSuperUserRoles(portalID, user.UserID); + else + roles = user.Roles; + + if (!rolesOnline.Where(r => roles.Contains(r.RoleName)).Any()) + { + foreach (var role in roles) + { + RoleOnlineManager.Instance.AddRoleOnline(new OnlineRoleInfo() + { + PortalID = portalID, + RoleName = role, + OnlineDate = DateTime.Now + }); + } + } + + var listeners = ListenerManager.Instance.GetListeners(portalID).Where(l => l.LoginState == LoginState.LoggedIn); + + foreach (var item in listeners.Join(roles, l => l.RoleName, r => r, (l, r) => l)) + { + Clients.All.invokeScript(item.InvokeScript); + } + } + } + + /// + /// + /// + /// + /// + public async Task JoinGroup(string groupName) + { + await Groups.Add(Context.ConnectionId, groupName); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void Ping(int portalID, string visitorGUID, string name, string email, string referrerDomain) + { + var visitor = VisitorOnlineManager.Instance.GetVisitorByGUID(portalID, visitorGUID); + if (visitor != null) + VisitorOnlineManager.Instance.Ping(visitorGUID); + else + JoinVisitor(portalID, visitorGUID, name, email, referrerDomain); + } + + #endregion + + #region Private Methods + + /// + /// + /// + /// + private void PurgeVisitorOnline(object state) + { + int portalID = (int)state; + + var hasOfflineVisitors = VisitorOnlineManager.Instance.PurgeVisitorsOnline(portalID); + if (hasOfflineVisitors.Any()) + { + Clients.Group("MyDnnVisitorsOnline").populateVisitorsOffline(hasOfflineVisitors.Select(o => o.VisitorGUID).ToArray()); + } + + if (hasOfflineVisitors.Where(v => !string.IsNullOrEmpty(v.UserName)).Any()) + OfflineRoles(portalID); + + var visitors = VisitorOnlineManager.Instance.GetVisitorsOnline(portalID); + + //check kardan baraye inke agar karbari digar online nist timer motovaghef shavad + if ((visitors == null || !visitors.Any()) && PurgeVisitorOnlineTimer != null) + { + PurgeVisitorOnlineTimer.Dispose(); + PurgeVisitorOnlineTimer = null; + } + } + + /// + /// + /// + /// + private void OfflineRoles(int portalID) + { + var visitors = VisitorOnlineManager.Instance.GetVisitorsOnline(portalID); + + var rolesOnline = RoleOnlineManager.Instance.GetRolesOnline(portalID); + if (rolesOnline.Any()) + { + //get online roles + var visitorsRoles = new List(); + foreach (OnlineVisitorInfo onlineVisitor in visitors.Where(v => !string.IsNullOrEmpty(v.UserName))) + { + var user = UserController.GetUserByName(onlineVisitor.UserName); + if (user != null) + { + IEnumerable roles; + if (user.IsSuperUser) + roles = RoleOnlineManager.Instance.GetSuperUserRoles(portalID, user.UserID); + else + roles = user.Roles; + + visitorsRoles.AddRange(roles); + } + } + + var listeners = ListenerManager.Instance.GetListeners(portalID).Where(l => l.LoginState == LoginState.LoggedOff); + + foreach (OnlineRoleInfo item in rolesOnline.Where(r => !visitorsRoles.Contains(r.RoleName))) + { + RoleOnlineManager.Instance.DeleteRoleOnline(item); + + var listener = listeners.SingleOrDefault(l => l.RoleName == item.RoleName); + if (listener != null) + Clients.All.invokeScript(listener.InvokeScript); + } + } + } + + /// + /// + /// + /// + private string getVisitorAgent() + { + return Context.Request.Headers["User-Agent"]; + } + + /// + /// + /// + /// + private string getURL() + { + return Context.Request.Headers["Referer"]; + } + + /// + /// + /// + /// + private string getIpAddress() + { + string ipAddress; + object tempObject; + + Context.Request.Environment.TryGetValue("server.RemoteIpAddress", out tempObject); + + if (tempObject != null) + { + ipAddress = (string)tempObject; + } + else + { + ipAddress = string.Empty; + } + + return ipAddress; + } + + #endregion + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Models/ListenerInfo.cs b/MyDnnVisitorsOnline/Models/ListenerInfo.cs new file mode 100644 index 0000000..8fec6d8 --- /dev/null +++ b/MyDnnVisitorsOnline/Models/ListenerInfo.cs @@ -0,0 +1,58 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using MyDnn.VisitorsOnline.Components.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.VisitorsOnline.Models +{ + /// + /// + /// + [TableName("MyDnnVisitorsOnline_Listeners")] + [PrimaryKey("ListenerID", AutoIncrement = true)] + [Cacheable("MyDnnListener", CacheItemPriority.Default, 20)] + [Scope("PortalID")] + public class ListenerInfo + { + /// + /// + /// + public int ListenerID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public string RoleName { get; set; } + + /// + /// + /// + public LoginState LoginState { get; set; } + + /// + /// + /// + public string InvokeScript { get; set; } + + /// + /// + /// + public string CreatedByModuleName { get; set; } + + /// + /// + /// + public DateTime CreatedOnDate { get; set; } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Models/OfflineVisitorInfo.cs b/MyDnnVisitorsOnline/Models/OfflineVisitorInfo.cs new file mode 100644 index 0000000..773ede1 --- /dev/null +++ b/MyDnnVisitorsOnline/Models/OfflineVisitorInfo.cs @@ -0,0 +1,29 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace MyDnn.VisitorsOnline.Models +{ + /// + /// + /// + [Serializable] + public class OfflineVisitorInfo + { + /// + /// + /// + public string VisitorGUID { get; set; } + + /// + /// + /// + public string UserName { get; set; } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Models/OnlineRoleInfo.cs b/MyDnnVisitorsOnline/Models/OnlineRoleInfo.cs new file mode 100644 index 0000000..f8db0a9 --- /dev/null +++ b/MyDnnVisitorsOnline/Models/OnlineRoleInfo.cs @@ -0,0 +1,43 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.VisitorsOnline.Models +{ + /// + /// + /// + [Serializable] + [TableName("MyDnnVisitorsOnline_RolesOnline")] + [PrimaryKey("ItemID", AutoIncrement = true)] + [Cacheable("MyDnnRolesOnline", CacheItemPriority.Default, 20)] + [Scope("PortalID")] + public class OnlineRoleInfo + { + /// + /// + /// + public int ItemID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public string RoleName { get; set; } + + /// + /// + /// + public DateTime OnlineDate { get; set; } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Models/OnlineVisitorInfo.cs b/MyDnnVisitorsOnline/Models/OnlineVisitorInfo.cs new file mode 100644 index 0000000..cde4462 --- /dev/null +++ b/MyDnnVisitorsOnline/Models/OnlineVisitorInfo.cs @@ -0,0 +1,101 @@ +// Copyright (c) MyDnn Group. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using DotNetNuke.ComponentModel.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Caching; + +namespace MyDnn.VisitorsOnline.Models +{ + /// + /// + /// + [TableName("MyDnnVisitorsOnline")] + [PrimaryKey("VisitorID", AutoIncrement = true)] + [Scope("PortalID")] + public class OnlineVisitorInfo + { + /// + /// + /// + public int VisitorID { get; set; } + + /// + /// + /// + public string VisitorGUID { get; set; } + + /// + /// + /// + public int PortalID { get; set; } + + /// + /// + /// + public string UserName { get; set; } + + /// + /// + /// + public int UserID { get; set; } + + /// + /// + /// + public string DisplayName { get; set; } + + /// + /// + /// + public string Email { get; set; } + + /// + /// + /// + public DateTime OnlineDate { get; set; } + + /// + /// + /// + public string IP { get; set; } + + /// + /// + /// + public string UserAgent { get; set; } + + /// + /// + /// + public string LastURL { get; set; } + + /// + /// + /// + public string ReferrerURL { get; set; } + + /// + /// + /// + public int TotalConnections { get; set; } + + /// + /// + /// + public string Connections { get; set; } + + /// + /// + /// + public int Ping { get; set; } + + /// + /// + /// + public string PingDate { get; set; } + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/MyDnn.VisitorsOnline.csproj b/MyDnnVisitorsOnline/MyDnn.VisitorsOnline.csproj new file mode 100644 index 0000000..6de728e --- /dev/null +++ b/MyDnnVisitorsOnline/MyDnn.VisitorsOnline.csproj @@ -0,0 +1,173 @@ + + + + + Debug + AnyCPU + + + 2.0 + {AA9FE893-27C4-494A-9287-FE235ACB9EBF} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + MyDnn.VisitorsOnline + MyDnn.VisitorsOnline + v4.5 + false + + + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\ + TRACE + prompt + 4 + false + + + + False + ..\..\bin\DotNetNuke.dll + False + + + False + ..\..\bin\DotNetNuke.Web.dll + False + + + ..\..\..\..\Modules\DotNetNuke Modules\All\DnnChat_01.01.00_Source\bin\Microsoft.AspNet.SignalR.Core.dll + + + ..\..\..\..\Modules\DotNetNuke Modules\All\DnnChat_01.01.00_Source\bin\Microsoft.AspNet.SignalR.SystemWeb.dll + + + + ..\..\..\..\Modules\DotNetNuke Modules\All\DnnChat_01.01.00_Source\bin\Microsoft.Owin.dll + + + ..\..\..\..\Modules\DotNetNuke Modules\All\DnnChat_01.01.00_Source\bin\Microsoft.Owin.Host.SystemWeb.dll + + + ..\..\..\..\Modules\DotNetNuke Modules\All\DnnChat_01.01.00_Source\bin\Microsoft.Owin.Security.dll + + + False + ..\..\bin\Microsoft.Web.Infrastructure.dll + + + ..\..\..\packages\Newtonsoft.Json.4.5.6\lib\net40\Newtonsoft.Json.dll + + + ..\..\..\..\Modules\DotNetNuke Modules\All\DnnChat_01.01.00_Source\bin\Owin.dll + + + + + False + ..\..\..\..\8.0.0\Beta\Test1\bin\System.Net.Http.Formatting.dll + + + + + + + + + + + + + False + ..\..\..\..\8.0.0\Beta\Test1\bin\System.Web.Http.dll + + + True + ..\..\..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.20710.0\lib\net40\System.Web.Http.WebHost.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + False + True + 48342 + / + + + False + False + + + False + + + + + + IF NOT ($(ConfigurationName)) == (Debug) GOTO END +cd $(ProjectDir) +copy /y obj\debug\MyDnn.VisitorsOnline.dll F:\MyDnnPackage\dnn8contest\Website\bin +:END + + + \ No newline at end of file diff --git a/MyDnnVisitorsOnline/MyDnn.VisitorsOnline.csproj.user b/MyDnnVisitorsOnline/MyDnn.VisitorsOnline.csproj.user new file mode 100644 index 0000000..cee1650 --- /dev/null +++ b/MyDnnVisitorsOnline/MyDnn.VisitorsOnline.csproj.user @@ -0,0 +1,31 @@ + + + + ProjectFiles + + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + False + True + + + + + \ No newline at end of file diff --git a/MyDnnVisitorsOnline/Properties/AssemblyInfo.cs b/MyDnnVisitorsOnline/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a8e7d7e --- /dev/null +++ b/MyDnnVisitorsOnline/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MyDnn.VisitorsOnline")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MyDnn.VisitorsOnline")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5cfbb6da-1bfb-4a00-a7f8-1bd3486a408f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MyDnnVisitorsOnline/Scripts/init - Copy.js b/MyDnnVisitorsOnline/Scripts/init - Copy.js new file mode 100644 index 0000000..aaa4b95 --- /dev/null +++ b/MyDnnVisitorsOnline/Scripts/init - Copy.js @@ -0,0 +1,124 @@ +(function ($, Sys) { + window.onload = __MVO; + function __MVO() { + if (getParameterByName("popUp") == "true") return; + if (typeof dnn == "undefined") return; + var __rootUrl = "/"; + var __visitorGUID; + __rootUrl = dnn.getVar("sf_siteRoot", "/"); + var __url = __rootUrl + "DesktopModules/MyDnnVisitorsOnline/API/Service/DetectVisitorsOnline" + $.ajax({ + type: "GET", + url: __url, + }).done(function (data) { + if (data.VisitorsOnlineEnabled) { + if (!localStorage["MyDnnVisitorsOnline_VisitorGUID"]) { + localStorage["MyDnnVisitorsOnline_VisitorGUID"] = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + __visitorGUID = localStorage["MyDnnVisitorsOnline_VisitorGUID"]; + var _mydnnVisitorsOnline; + if (!$.signalR || !$.connection.MyDnnVisitorsOnlineHub) { + $.getScript(data.RootUrl + "DesktopModules/MyDnnVisitorsOnline/Scripts/jquery.signalR-2.1.0.min.js", function () { + if (!$.connection.MyDnnVisitorsOnlineHub) + $.getScript(data.RootUrl + "signalr/hubs", function () { + _mydnnVisitorsOnline = new MyDnnVisitorsOnline(data); + _mydnnVisitorsOnline.joinVisitor(); + }); + else { + _mydnnVisitorsOnline = new MyDnnVisitorsOnline(data); + _mydnnVisitorsOnline.joinVisitor(); + } + }); + } + else { + _mydnnVisitorsOnline = new MyDnnVisitorsOnline(data); + _mydnnVisitorsOnline.joinVisitor(); + } + } + }); + + function MyDnnVisitorsOnline(data) { + var hub; + var portalID = data.PortalID; + var key; + var referrerDomain; + var name = getCookie("MyDnnSupportLiveChatName"); + var email = getCookie("MyDnnSupportLiveChatEmail"); + + if (document.referrer) + referrerDomain = document.referrer.match(/:\/\/(.[^/]+)/)[1]; + + this.joinVisitor = function () { + hub = $.connection.MyDnnVisitorsOnlineHub; + + if (hub.connection.state == 0 || hub.connection.state == 4) + $.connection.hub.start({ transport: 'longPolling' }).done(function () { + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + }); + else if (hub.connection.state == 1) + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + + setInterval(function () { + hub.invoke('Ping', portalID, __visitorGUID, name, email, referrerDomain); + }, 45000); + }; + + $.connection.hub.reconnected(function () { + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + }); + + $.connection.hub.disconnected(function () { + setTimeout(function () { + $.connection.hub.start({ transport: 'longPolling' }).done(function () { + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + }); + }, 5000); + }); + + $.connection.hub.stateChanged(function (change) { + if (change.newState === $.connection.connectionState.connecting) { + console.log('connecting...'); + } + else if (change.newState === $.connection.connectionState.connected) { + console.log('connected'); + } + if (change.newState === $.connection.connectionState.reconnecting) { + console.log('reconnecting...'); + } + else if (change.newState === $.connection.connectionState.disconnected) { + console.log('disconnected'); + } + }); + + $.connection.hub.connectionSlow(function () { + console.log('connection slow'); + }); + + $.connection.MyDnnVisitorsOnlineHub.client.invokeScript = function (script) { + eval(script); + }; + + + } + + function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name) == 0) return c.substring(name.length, c.length); + } + return ""; + } + + function getParameterByName(name) { + name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); + var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), + results = regex.exec(location.search); + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); + } + } +}(jQuery, window.Sys)); diff --git a/MyDnnVisitorsOnline/Scripts/init.js b/MyDnnVisitorsOnline/Scripts/init.js new file mode 100644 index 0000000..0b19381 --- /dev/null +++ b/MyDnnVisitorsOnline/Scripts/init.js @@ -0,0 +1,122 @@ +(function ($, Sys) { + window.onload = __MVO; + function __MVO() { + if (getParameterByName("popUp") == "true") return; + if (typeof dnn == "undefined") return; + var __rootUrl = "/"; + var __visitorGUID; + __rootUrl = dnn.getVar("sf_siteRoot", "/"); + var __url = __rootUrl + "DesktopModules/MyDnnVisitorsOnline/API/Service/DetectVisitorsOnline" + $.ajax({ + type: "GET", + url: __url, + }).done(function (data) { + if (data.VisitorsOnlineEnabled) { + if (!localStorage["MyDnnVisitorsOnline_VisitorGUID"]) { + localStorage["MyDnnVisitorsOnline_VisitorGUID"] = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + __visitorGUID = localStorage["MyDnnVisitorsOnline_VisitorGUID"]; + var _mydnnVisitorsOnline; + if (!$.signalR || !$.connection.MyDnnVisitorsOnlineHub) { + $.getScript(data.RootUrl + "DesktopModules/MyDnnVisitorsOnline/Scripts/jquery.signalR-2.1.0.min.js", function () { + if (!$.connection.MyDnnVisitorsOnlineHub) + $.getScript(data.RootUrl + "signalr/hubs", function () { + _mydnnVisitorsOnline = new MyDnnVisitorsOnline(data); + _mydnnVisitorsOnline.joinVisitor(); + }); + else { + _mydnnVisitorsOnline = new MyDnnVisitorsOnline(data); + _mydnnVisitorsOnline.joinVisitor(); + } + }); + } + else { + _mydnnVisitorsOnline = new MyDnnVisitorsOnline(data); + _mydnnVisitorsOnline.joinVisitor(); + } + } + }); + + function MyDnnVisitorsOnline(data) { + var hub; + var portalID = data.PortalID; + var key; + var referrerDomain; + var name = getCookie("MyDnnSupportLiveChatName"); + var email = getCookie("MyDnnSupportLiveChatEmail"); + + if (document.referrer) + referrerDomain = document.referrer.match(/:\/\/(.[^/]+)/)[1]; + + this.joinVisitor = function () { + hub = $.connection.MyDnnVisitorsOnlineHub; + + if (hub.connection.state == 0 || hub.connection.state == 4) + $.connection.hub.start({ transport: 'longPolling' }).done(function () { + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + }); + else if (hub.connection.state == 1) + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + + setInterval(function () { + hub.invoke('Ping', portalID, __visitorGUID, name, email, referrerDomain); + }, 45000); + }; + + $.connection.hub.reconnected(function () { + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + }); + + $.connection.hub.disconnected(function () { + setTimeout(function () { + $.connection.hub.start({ transport: 'longPolling' }).done(function () { + hub.invoke('JoinVisitor', portalID, __visitorGUID, name, email, referrerDomain); + }); + }, 5000); + }); + + $.connection.hub.stateChanged(function (change) { + if (change.newState === $.connection.connectionState.connecting) { + console.log('connecting...'); + } + else if (change.newState === $.connection.connectionState.connected) { + console.log('connected'); + } + if (change.newState === $.connection.connectionState.reconnecting) { + console.log('reconnecting...'); + } + else if (change.newState === $.connection.connectionState.disconnected) { + console.log('disconnected'); + } + }); + + $.connection.hub.connectionSlow(function () { + console.log('connection slow'); + }); + + $.connection.MyDnnVisitorsOnlineHub.client.invokeScript = function (script) { + eval(script); + }; + } + + function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name) == 0) return c.substring(name.length, c.length); + } + return ""; + } + + function getParameterByName(name) { + name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); + var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), + results = regex.exec(location.search); + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); + } + } +}(jQuery, window.Sys)); diff --git a/MyDnnVisitorsOnline/Scripts/jquery.signalR-2.1.0.min.js b/MyDnnVisitorsOnline/Scripts/jquery.signalR-2.1.0.min.js new file mode 100644 index 0000000..dc3cf2d --- /dev/null +++ b/MyDnnVisitorsOnline/Scripts/jquery.signalR-2.1.0.min.js @@ -0,0 +1,8 @@ +/*! + * ASP.NET SignalR JavaScript Library v2.1.0 + * http://signalr.net/ + * + * Copyright (C) Microsoft Corporation. All rights reserved. + * + */ +(function(n,t,i){function w(t,i){var u,f;if(n.isArray(t)){for(u=t.length-1;u>=0;u--)f=t[u],n.type(f)==="string"&&r.transports[f]||(i.log("Invalid transport: "+f+", removing it from the transports list."),t.splice(u,1));t.length===0&&(i.log("No transports remain within the specified transport array."),t=null)}else if(r.transports[t]||t==="auto"){if(t==="auto"&&r._.ieVersion<=8)return["longPolling"]}else i.log("Invalid transport: "+t.toString()+"."),t=null;return t}function b(n){return n==="http:"?80:n==="https:"?443:void 0}function a(n,t){return t.match(/:\d+$/)?t:t+":"+b(n)}function k(t,i){var u=this,r=[];u.tryBuffer=function(i){return t.state===n.signalR.connectionState.connecting?(r.push(i),!0):!1};u.drain=function(){if(t.state===n.signalR.connectionState.connected)while(r.length>0)i(r.shift())};u.clear=function(){r=[]}}var f={nojQuery:"jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.",noTransportOnInit:"No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.",errorOnNegotiate:"Error during negotiation request.",stoppedWhileLoading:"The connection was stopped during page load.",stoppedWhileNegotiating:"The connection was stopped during the negotiate request.",errorParsingNegotiateResponse:"Error parsing negotiate response.",errorDuringStartRequest:"Error during start request. Stopping the connection.",stoppedDuringStartRequest:"The connection was stopped during the start request.",errorParsingStartResponse:"Error parsing start response: '{0}'. Stopping the connection.",invalidStartResponse:"Invalid start response: '{0}'. Stopping the connection.",protocolIncompatible:"You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.",sendFailed:"Send failed.",parseFailed:"Failed at parsing response: {0}",longPollFailed:"Long polling request failed.",eventSourceFailedToConnect:"EventSource failed to connect.",eventSourceError:"Error raised by EventSource",webSocketClosed:"WebSocket closed.",pingServerFailedInvalidResponse:"Invalid ping response when pinging server: '{0}'.",pingServerFailed:"Failed to ping server.",pingServerFailedStatusCode:"Failed to ping server. Server responded with status code {0}, stopping the connection.",pingServerFailedParse:"Failed to parse ping server response, stopping the connection.",noConnectionTransport:"Connection is in an invalid state, there is no transport active.",webSocketsInvalidState:"The Web Socket transport is in an invalid state, transitioning into reconnecting.",reconnectTimeout:"Couldn't reconnect within the configured timeout of {0} ms, disconnecting.",reconnectWindowTimeout:"The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection."};if(typeof n!="function")throw new Error(f.nojQuery);var r,h,s=t.document.readyState==="complete",e=n(t),c="__Negotiate Aborted__",u={onStart:"onStart",onStarting:"onStarting",onReceived:"onReceived",onError:"onError",onConnectionSlow:"onConnectionSlow",onReconnecting:"onReconnecting",onReconnect:"onReconnect",onStateChanged:"onStateChanged",onDisconnect:"onDisconnect"},v=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},o=function(t,i,r){return i===t.state?(t.state=r,n(t).triggerHandler(u.onStateChanged,[{oldState:i,newState:r}]),!0):!1},y=function(n){return n.state===r.connectionState.disconnected},l=function(n){return n._.keepAliveData.activated&&n.transport.supportsKeepAlive(n)},p=function(i){var f,e;i._.configuredStopReconnectingTimeout||(e=function(t){var i=r._.format(r.resources.reconnectTimeout,t.disconnectTimeout);t.log(i);n(t).triggerHandler(u.onError,[r._.error(i,"TimeoutException")]);t.stop(!1,!1)},i.reconnecting(function(){var n=this;n.state===r.connectionState.reconnecting&&(f=t.setTimeout(function(){e(n)},n.disconnectTimeout))}),i.stateChanged(function(n){n.oldState===r.connectionState.reconnecting&&t.clearTimeout(f)}),i._.configuredStopReconnectingTimeout=!0)};r=function(n,t,i){return new r.fn.init(n,t,i)};r._={defaultContentType:"application/x-www-form-urlencoded; charset=UTF-8",ieVersion:function(){var i,n;return t.navigator.appName==="Microsoft Internet Explorer"&&(n=/MSIE ([0-9]+\.[0-9]+)/.exec(t.navigator.userAgent),n&&(i=t.parseFloat(n[1]))),i}(),error:function(n,t,i){var r=new Error(n);return r.source=t,typeof i!="undefined"&&(r.context=i),r},transportError:function(n,t,r,u){var f=this.error(n,r,u);return f.transport=t?t.name:i,f},format:function(){for(var t=arguments[0],n=0;n<\/script>.");}};e.load(function(){s=!0});r.fn=r.prototype={init:function(t,i,r){var f=n(this);this.url=t;this.qs=i;this.lastError=null;this._={keepAliveData:{},connectingMessageBuffer:new k(this,function(n){f.triggerHandler(u.onReceived,[n])}),onFailedTimeoutHandle:null,lastMessageAt:(new Date).getTime(),lastActiveAt:(new Date).getTime(),beatInterval:5e3,beatHandle:null,totalTransportConnectTimeout:0};typeof r=="boolean"&&(this.logging=r)},_parseResponse:function(n){var t=this;return n?typeof n=="string"?t.json.parse(n):n:n},_originalJson:t.JSON,json:t.JSON,isCrossDomain:function(i,r){var u;return(i=n.trim(i),r=r||t.location,i.indexOf("http")!==0)?!1:(u=t.document.createElement("a"),u.href=i,u.protocol+a(u.protocol,u.host)!==r.protocol+a(r.protocol,r.host))},ajaxDataType:"text",contentType:"application/json; charset=UTF-8",logging:!1,state:r.connectionState.disconnected,clientProtocol:"1.4",reconnectDelay:2e3,transportConnectTimeout:0,disconnectTimeout:3e4,reconnectWindow:3e4,keepAliveWarnAt:2/3,start:function(i,h){var a=this,v={pingInterval:3e5,waitForPageLoad:!0,transport:"auto",jsonp:!1},d,y=a._deferral||n.Deferred(),b=t.document.createElement("a"),k,g;if(a.lastError=null,a._deferral=y,!a.json)throw new Error("SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.");if(n.type(i)==="function"?h=i:n.type(i)==="object"&&(n.extend(v,i),n.type(v.callback)==="function"&&(h=v.callback)),v.transport=w(v.transport,a),!v.transport)throw new Error("SignalR: Invalid transport(s) specified, aborting start.");return(a._.config=v,!s&&v.waitForPageLoad===!0)?(a._.deferredStartHandler=function(){a.start(i,h)},e.bind("load",a._.deferredStartHandler),y.promise()):a.state===r.connectionState.connecting?y.promise():o(a,r.connectionState.disconnected,r.connectionState.connecting)===!1?(y.resolve(a),y.promise()):(p(a),b.href=a.url,b.protocol&&b.protocol!==":"?(a.protocol=b.protocol,a.host=b.host):(a.protocol=t.document.location.protocol,a.host=b.host||t.document.location.host),a.baseUrl=a.protocol+"//"+a.host,a.wsProtocol=a.protocol==="https:"?"wss://":"ws://",v.transport==="auto"&&v.jsonp===!0&&(v.transport="longPolling"),a.url.indexOf("//")===0&&(a.url=t.location.protocol+a.url,a.log("Protocol relative URL detected, normalizing it to '"+a.url+"'.")),this.isCrossDomain(a.url)&&(a.log("Auto detected cross domain url."),v.transport==="auto"&&(v.transport=["webSockets","serverSentEvents","longPolling"]),typeof v.withCredentials=="undefined"&&(v.withCredentials=!0),v.jsonp||(v.jsonp=!n.support.cors,v.jsonp&&a.log("Using jsonp because this browser doesn't support CORS.")),a.contentType=r._.defaultContentType),a.withCredentials=v.withCredentials,a.ajaxDataType=v.jsonp?"jsonp":"text",n(a).bind(u.onStart,function(){n.type(h)==="function"&&h.call(a);y.resolve(a)}),d=function(i,s){var p=r._.error(f.noTransportOnInit);if(s=s||0,s>=i.length){n(a).triggerHandler(u.onError,[p]);y.reject(p);a.stop();return}if(a.state!==r.connectionState.disconnected){var w=i[s],h=r.transports[w],c=!1,v=function(){c||(c=!0,t.clearTimeout(a._.onFailedTimeoutHandle),h.stop(a),d(i,s+1))};a.transport=h;try{a._.onFailedTimeoutHandle=t.setTimeout(function(){a.log(h.name+" timed out when trying to connect.");v()},a._.totalTransportConnectTimeout);h.start(a,function(){var i=r._.firefoxMajorVersion(t.navigator.userAgent)>=11,f=!!a.withCredentials&&i;a.state!==r.connectionState.disconnected&&(c||(c=!0,t.clearTimeout(a._.onFailedTimeoutHandle),l(a)&&r.transports._logic.monitorKeepAlive(a),r.transports._logic.startHeartbeat(a),r._.configurePingInterval(a),o(a,r.connectionState.connecting,r.connectionState.connected),a._.connectingMessageBuffer.drain(),n(a).triggerHandler(u.onStart),e.bind("unload",function(){a.log("Window unloading, stopping the connection.");a.stop(f)}),i&&e.bind("beforeunload",function(){t.setTimeout(function(){a.stop(f)},0)})))},v)}catch(b){a.log(h.name+" transport threw '"+b.message+"' when attempting to start.");v()}}},k=a.url+"/negotiate",g=function(t,i){var e=r._.error(f.errorOnNegotiate,t,i._.negotiateRequest);n(i).triggerHandler(u.onError,e);y.reject(e);i.stop()},n(a).triggerHandler(u.onStarting),k=r.transports._logic.prepareQueryString(a,k),a.log("Negotiating with '"+k+"'."),a._.negotiateRequest=r.transports._logic.ajax(a,{url:k,error:function(n,t){t!==c?g(n,a):y.reject(r._.error(f.stoppedWhileNegotiating,null,a._.negotiateRequest))},success:function(t){var i,e,h,o=[],s=[];try{i=a._parseResponse(t)}catch(c){g(r._.error(f.errorParsingNegotiateResponse,c),a);return}if(e=a._.keepAliveData,a.appRelativeUrl=i.Url,a.id=i.ConnectionId,a.token=i.ConnectionToken,a.webSocketServerUrl=i.WebSocketServerUrl,a._.longPollDelay=i.LongPollDelay*1e3,a.disconnectTimeout=i.DisconnectTimeout*1e3,a._.totalTransportConnectTimeout=a.transportConnectTimeout+i.TransportConnectTimeout*1e3,i.KeepAliveTimeout?(e.activated=!0,e.timeout=i.KeepAliveTimeout*1e3,e.timeoutWarning=e.timeout*a.keepAliveWarnAt,a._.beatInterval=(e.timeout-e.timeoutWarning)/3):e.activated=!1,a.reconnectWindow=a.disconnectTimeout+(e.timeout||0),!i.ProtocolVersion||i.ProtocolVersion!==a.clientProtocol){h=r._.error(r._.format(f.protocolIncompatible,a.clientProtocol,i.ProtocolVersion));n(a).triggerHandler(u.onError,[h]);y.reject(h);return}n.each(r.transports,function(n){if(n.indexOf("_")===0||n==="webSockets"&&!i.TryWebSockets)return!0;s.push(n)});n.isArray(v.transport)?n.each(v.transport,function(t,i){n.inArray(i,s)>=0&&o.push(i)}):v.transport==="auto"?o=s:n.inArray(v.transport,s)>=0&&o.push(v.transport);d(o)}}),y.promise())},starting:function(t){var i=this;return n(i).bind(u.onStarting,function(){t.call(i)}),i},send:function(n){var t=this;if(t.state===r.connectionState.disconnected)throw new Error("SignalR: Connection must be started before data can be sent. Call .start() before .send()");if(t.state===r.connectionState.connecting)throw new Error("SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.");return t.transport.send(t,n),t},received:function(t){var i=this;return n(i).bind(u.onReceived,function(n,r){t.call(i,r)}),i},stateChanged:function(t){var i=this;return n(i).bind(u.onStateChanged,function(n,r){t.call(i,r)}),i},error:function(t){var i=this;return n(i).bind(u.onError,function(n,r,u){i.lastError=r;t.call(i,r,u)}),i},disconnected:function(t){var i=this;return n(i).bind(u.onDisconnect,function(){t.call(i)}),i},connectionSlow:function(t){var i=this;return n(i).bind(u.onConnectionSlow,function(){t.call(i)}),i},reconnecting:function(t){var i=this;return n(i).bind(u.onReconnecting,function(){t.call(i)}),i},reconnected:function(t){var i=this;return n(i).bind(u.onReconnect,function(){t.call(i)}),i},stop:function(i,h){var a=this,v=a._deferral;if(a._.deferredStartHandler&&e.unbind("load",a._.deferredStartHandler),delete a._.config,delete a._.deferredStartHandler,!s&&(!a._.config||a._.config.waitForPageLoad===!0)){a.log("Stopping connection prior to negotiate.");v&&v.reject(r._.error(f.stoppedWhileLoading));return}if(a.state!==r.connectionState.disconnected)return a.log("Stopping connection."),o(a,a.state,r.connectionState.disconnected),t.clearTimeout(a._.beatHandle),t.clearTimeout(a._.onFailedTimeoutHandle),t.clearInterval(a._.pingIntervalId),a.transport&&(a.transport.stop(a),h!==!1&&a.transport.abort(a,i),l(a)&&r.transports._logic.stopMonitoringKeepAlive(a),a.transport=null),a._.negotiateRequest&&(a._.negotiateRequest.abort(c),delete a._.negotiateRequest),r.transports._logic.tryAbortStartRequest(a),n(a).triggerHandler(u.onDisconnect),delete a._deferral,delete a.messageId,delete a.groupsToken,delete a.id,delete a._.pingIntervalId,delete a._.lastMessageAt,delete a._.lastActiveAt,delete a._.longPollDelay,a._.connectingMessageBuffer.clear(),a},log:function(n){v(n,this.logging)}};r.fn.init.prototype=r.fn;r.noConflict=function(){return n.connection===r&&(n.connection=h),r};n.connection&&(h=n.connection);n.connection=n.signalR=r})(window.jQuery,window),function(n,t){function o(n){n._.keepAliveData.monitoring&&h(n);r.markActive(n)&&(n._.beatHandle=t.setTimeout(function(){o(n)},n._.beatInterval))}function h(t){var r=t._.keepAliveData,f;t.state===i.connectionState.connected&&(f=(new Date).getTime()-t._.lastMessageAt,f>=r.timeout?(t.log("Keep alive timed out. Notifying transport that connection has been lost."),t.transport.lostConnection(t)):f>=r.timeoutWarning?r.userNotified||(t.log("Keep alive has been missed, connection may be dead/slow."),n(t).triggerHandler(u.onConnectionSlow),r.userNotified=!0):r.userNotified=!1)}function f(n,t){var i=n.url+t;return n.transport&&(i+="?transport="+n.transport.name),r.prepareQueryString(n,i)}var i=n.signalR,u=n.signalR.events,s=n.signalR.changeState,e="__Start Aborted__",r;i.transports={};r=i.transports._logic={ajax:function(t,i){return n.ajax(n.extend(!0,{},n.signalR.ajaxDefaults,{type:"GET",data:{},xhrFields:{withCredentials:t.withCredentials},contentType:t.contentType,dataType:t.ajaxDataType},i))},pingServer:function(t){var e,f,u=n.Deferred();return t.transport?(e=t.url+"/ping",e=r.addQs(e,t.qs),f=r.ajax(t,{url:e,success:function(n){var r;try{r=t._parseResponse(n)}catch(e){u.reject(i._.transportError(i.resources.pingServerFailedParse,t.transport,e,f));t.stop();return}r.Response==="pong"?u.resolve():u.reject(i._.transportError(i._.format(i.resources.pingServerFailedInvalidResponse,n),t.transport,null,f))},error:function(n){n.status===401||n.status===403?(u.reject(i._.transportError(i._.format(i.resources.pingServerFailedStatusCode,n.status),t.transport,n,f)),t.stop()):u.reject(i._.transportError(i.resources.pingServerFailed,t.transport,n,f))}})):u.reject(i._.transportError(i.resources.noConnectionTransport,t.transport)),u.promise()},prepareQueryString:function(n,i){var u;return u=r.addQs(i,"clientProtocol="+n.clientProtocol),u=r.addQs(u,n.qs),n.token&&(u+="&connectionToken="+t.encodeURIComponent(n.token)),n.data&&(u+="&connectionData="+t.encodeURIComponent(n.data)),u},addQs:function(t,i){var r=t.indexOf("?")!==-1?"&":"?",u;if(!i)return t;if(typeof i=="object")return t+r+n.param(i);if(typeof i=="string")return u=i.charAt(0),(u==="?"||u==="&")&&(r=""),t+r+i;throw new Error("Query string property must be either a string or object.");},getUrl:function(n,i,u,f){var s=i==="webSockets"?"":n.baseUrl,e=s+n.appRelativeUrl,o="transport="+i;return n.groupsToken&&(o+="&groupsToken="+t.encodeURIComponent(n.groupsToken)),u?(e+=f?"/poll":"/reconnect",n.messageId&&(o+="&messageId="+t.encodeURIComponent(n.messageId))):e+="/connect",e+="?"+o,e=r.prepareQueryString(n,e),e+("&tid="+Math.floor(Math.random()*11))},maximizePersistentResponse:function(n){return{MessageId:n.C,Messages:n.M,Initialized:typeof n.S!="undefined"?!0:!1,Disconnect:typeof n.D!="undefined"?!0:!1,ShouldReconnect:typeof n.T!="undefined"?!0:!1,LongPollDelay:n.L,GroupsToken:n.G}},updateGroups:function(n,t){t&&(n.groupsToken=t)},stringifySend:function(n,t){return typeof t=="string"||typeof t=="undefined"||t===null?t:n.json.stringify(t)},ajaxSend:function(t,e){var h=r.stringifySend(t,e),c=f(t,"/send"),o,s=function(t,r){n(r).triggerHandler(u.onError,[i._.transportError(i.resources.sendFailed,r.transport,t,o),e])};return o=r.ajax(t,{url:c,type:t.ajaxDataType==="jsonp"?"GET":"POST",contentType:i._.defaultContentType,data:{data:h},success:function(n){var i;if(n){try{i=t._parseResponse(n)}catch(u){s(u,t);t.stop();return}r.triggerReceived(t,i)}},error:function(n,i){i!=="abort"&&i!=="parsererror"&&s(n,t)}})},ajaxAbort:function(n,t){if(typeof n.transport!="undefined"){t=typeof t=="undefined"?!0:t;var i=f(n,"/abort");r.ajax(n,{url:i,async:t,timeout:1e3,type:"POST"});n.log("Fired ajax abort async = "+t+".")}},tryInitialize:function(t,o,s){var l,h,a=function(n){var i=t._deferral;i&&i.reject(n)},c=function(i){n(t).triggerHandler(u.onError,[i]);a(i);t.stop()};o.Initialized&&(l=f(t,"/start"),h=r.ajax(t,{url:l,success:function(n){var r;try{r=t._parseResponse(n)}catch(u){c(i._.error(i._.format(i.resources.errorParsingStartResponse,n),u,h));return}r.Response==="started"?s():c(i._.error(i._.format(i.resources.invalidStartResponse,n),null,h))},error:function(n,t){t!==e?c(i._.error(i.resources.errorDuringStartRequest,n,h)):a(i._.error(i.resources.stoppedDuringStartRequest,null,h))}}),t._.startRequest=h)},tryAbortStartRequest:function(n){n._.startRequest&&(n._.startRequest.abort(e),delete n._.startRequest)},triggerReceived:function(t,i){t._.connectingMessageBuffer.tryBuffer(i)||n(t).triggerHandler(u.onReceived,[i])},processMessages:function(t,i,u){var f;r.markLastMessage(t);i&&(f=r.maximizePersistentResponse(i),r.updateGroups(t,f.GroupsToken),f.MessageId&&(t.messageId=f.MessageId),f.Messages&&(n.each(f.Messages,function(n,i){r.triggerReceived(t,i)}),r.tryInitialize(t,f,u)))},monitorKeepAlive:function(t){var i=t._.keepAliveData;i.monitoring?t.log("Tried to monitor keep alive but it's already being monitored."):(i.monitoring=!0,r.markLastMessage(t),t._.keepAliveData.reconnectKeepAliveUpdate=function(){r.markLastMessage(t)},n(t).bind(u.onReconnect,t._.keepAliveData.reconnectKeepAliveUpdate),t.log("Now monitoring keep alive with a warning timeout of "+i.timeoutWarning+" and a connection lost timeout of "+i.timeout+"."))},stopMonitoringKeepAlive:function(t){var i=t._.keepAliveData;i.monitoring&&(i.monitoring=!1,n(t).unbind(u.onReconnect,t._.keepAliveData.reconnectKeepAliveUpdate),t._.keepAliveData={},t.log("Stopping the monitoring of the keep alive."))},startHeartbeat:function(n){n._.lastActiveAt=(new Date).getTime();o(n)},markLastMessage:function(n){n._.lastMessageAt=(new Date).getTime()},markActive:function(n){return r.verifyLastActive(n)?(n._.lastActiveAt=(new Date).getTime(),!0):!1},isConnectedOrReconnecting:function(n){return n.state===i.connectionState.connected||n.state===i.connectionState.reconnecting},ensureReconnectingState:function(t){return s(t,i.connectionState.connected,i.connectionState.reconnecting)===!0&&n(t).triggerHandler(u.onReconnecting),t.state===i.connectionState.reconnecting},clearReconnectTimeout:function(n){n&&n._.reconnectTimeout&&(t.clearTimeout(n._.reconnectTimeout),delete n._.reconnectTimeout)},verifyLastActive:function(t){if((new Date).getTime()-t._.lastActiveAt>=t.reconnectWindow){var r=i._.format(i.resources.reconnectWindowTimeout,new Date(t._.lastActiveAt),t.reconnectWindow);return t.log(r),n(t).triggerHandler(u.onError,[i._.error(r,"TimeoutException")]),t.stop(!1,!1),!1}return!0},reconnect:function(n,u){var f=i.transports[u];if(r.isConnectedOrReconnecting(n)&&!n._.reconnectTimeout){if(!r.verifyLastActive(n))return;n._.reconnectTimeout=t.setTimeout(function(){r.verifyLastActive(n)&&(f.stop(n),r.ensureReconnectingState(n)&&(n.log(u+" reconnecting."),f.start(n)))},n.reconnectDelay)}},handleParseFailure:function(t,r,f,e,o){t.state===i.connectionState.connecting?(t.log("Failed to parse server response while attempting to connect."),e()):(n(t).triggerHandler(u.onError,[i._.transportError(i._.format(i.resources.parseFailed,r),t.transport,f,o)]),t.stop())},foreverFrame:{count:0,connections:{}}}}(window.jQuery,window),function(n,t){var r=n.signalR,u=n.signalR.events,f=n.signalR.changeState,i=r.transports._logic;r.transports.webSockets={name:"webSockets",supportsKeepAlive:function(){return!0},send:function(t,f){var e=i.stringifySend(t,f);try{t.socket.send(e)}catch(o){n(t).triggerHandler(u.onError,[r._.transportError(r.resources.webSocketsInvalidState,t.transport,o,t.socket),f])}},start:function(e,o,s){var h,c=!1,l=this,a=!o,v=n(e);if(!t.WebSocket){s();return}e.socket||(h=e.webSocketServerUrl?e.webSocketServerUrl:e.wsProtocol+e.host,h+=i.getUrl(e,this.name,a),e.log("Connecting to websocket endpoint '"+h+"'."),e.socket=new t.WebSocket(h),e.socket.onopen=function(){c=!0;e.log("Websocket opened.");i.clearReconnectTimeout(e);f(e,r.connectionState.reconnecting,r.connectionState.connected)===!0&&v.triggerHandler(u.onReconnect)},e.socket.onclose=function(t){if(this===e.socket){if(c)typeof t.wasClean!="undefined"&&t.wasClean===!1?(n(e).triggerHandler(u.onError,[r._.transportError(r.resources.webSocketClosed,e.transport,t)]),e.log("Unclean disconnect from websocket: "+t.reason||"[no reason given].")):e.log("Websocket closed.");else{s?s():a&&l.reconnect(e);return}l.reconnect(e)}},e.socket.onmessage=function(t){var r;try{r=e._parseResponse(t.data)}catch(u){i.handleParseFailure(e,t.data,u,s,t);return}r&&(n.isEmptyObject(r)||r.M?i.processMessages(e,r,o):i.triggerReceived(e,r))})},reconnect:function(n){i.reconnect(n,this.name)},lostConnection:function(n){this.reconnect(n)},stop:function(n){i.clearReconnectTimeout(n);n.socket&&(n.log("Closing the Websocket."),n.socket.close(),n.socket=null)},abort:function(n,t){i.ajaxAbort(n,t)}}}(window.jQuery,window),function(n,t){var i=n.signalR,u=n.signalR.events,e=n.signalR.changeState,r=i.transports._logic,f=function(n){t.clearTimeout(n._.reconnectAttemptTimeoutHandle);delete n._.reconnectAttemptTimeoutHandle};i.transports.serverSentEvents={name:"serverSentEvents",supportsKeepAlive:function(){return!0},timeOut:3e3,start:function(o,s,h){var c=this,l=!1,a=n(o),v=!s,y;if(o.eventSource&&(o.log("The connection already has an event source. Stopping it."),o.stop()),!t.EventSource){h&&(o.log("This browser doesn't support SSE."),h());return}y=r.getUrl(o,this.name,v);try{o.log("Attempting to connect to SSE endpoint '"+y+"'.");o.eventSource=new t.EventSource(y,{withCredentials:o.withCredentials})}catch(p){o.log("EventSource failed trying to connect with error "+p.Message+".");h?h():(a.triggerHandler(u.onError,[i._.transportError(i.resources.eventSourceFailedToConnect,o.transport,p)]),v&&c.reconnect(o));return}v&&(o._.reconnectAttemptTimeoutHandle=t.setTimeout(function(){l===!1&&o.eventSource.readyState!==t.EventSource.OPEN&&c.reconnect(o)},c.timeOut));o.eventSource.addEventListener("open",function(){o.log("EventSource connected.");f(o);r.clearReconnectTimeout(o);l===!1&&(l=!0,e(o,i.connectionState.reconnecting,i.connectionState.connected)===!0&&a.triggerHandler(u.onReconnect))},!1);o.eventSource.addEventListener("message",function(n){var t;if(n.data!=="initialized"){try{t=o._parseResponse(n.data)}catch(i){r.handleParseFailure(o,n.data,i,h,n);return}r.processMessages(o,t,s)}},!1);o.eventSource.addEventListener("error",function(n){if(this===o.eventSource){if(!l){h&&h();return}o.log("EventSource readyState: "+o.eventSource.readyState+".");n.eventPhase===t.EventSource.CLOSED?(o.log("EventSource reconnecting due to the server connection ending."),c.reconnect(o)):(o.log("EventSource error."),a.triggerHandler(u.onError,[i._.transportError(i.resources.eventSourceError,o.transport,n)]))}},!1)},reconnect:function(n){r.reconnect(n,this.name)},lostConnection:function(n){this.reconnect(n)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){f(n);r.clearReconnectTimeout(n);n&&n.eventSource&&(n.log("EventSource calling close()."),n.eventSource.close(),n.eventSource=null,delete n.eventSource)},abort:function(n,t){r.ajaxAbort(n,t)}}}(window.jQuery,window),function(n,t){var r=n.signalR,e=n.signalR.events,o=n.signalR.changeState,i=r.transports._logic,u=function(){var n=t.document.createElement("iframe");return n.setAttribute("style","position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;"),n},f=function(){var i=null,f=1e3,n=0;return{prevent:function(){r._.ieVersion<=8&&(n===0&&(i=t.setInterval(function(){var n=u();t.document.body.appendChild(n);t.document.body.removeChild(n);n=null},f)),n++)},cancel:function(){n===1&&t.clearInterval(i);n>0&&n--}}}();r.transports.foreverFrame={name:"foreverFrame",supportsKeepAlive:function(){return!0},iframeClearThreshold:50,start:function(n,r,e){var l=this,s=i.foreverFrame.count+=1,h,o=u(),c=function(){n.log("Forever frame iframe finished loading and is no longer receiving messages.");l.reconnect(n)};if(t.EventSource){e&&(n.log("This browser supports SSE, skipping Forever Frame."),e());return}o.setAttribute("data-signalr-connection-id",n.id);f.prevent();h=i.getUrl(n,this.name);h+="&frameId="+s;t.document.body.appendChild(o);n.log("Binding to iframe's load event.");o.addEventListener?o.addEventListener("load",c,!1):o.attachEvent&&o.attachEvent("onload",c);o.src=h;i.foreverFrame.connections[s]=n;n.frame=o;n.frameId=s;r&&(n.onSuccess=function(){n.log("Iframe transport started.");r()})},reconnect:function(n){var r=this;i.isConnectedOrReconnecting(n)&&i.verifyLastActive(n)&&t.setTimeout(function(){if(i.verifyLastActive(n)&&n.frame&&i.ensureReconnectingState(n)){var u=n.frame,t=i.getUrl(n,r.name,!0)+"&frameId="+n.frameId;n.log("Updating iframe src to '"+t+"'.");u.src=t}},n.reconnectDelay)},lostConnection:function(n){this.reconnect(n)},send:function(n,t){i.ajaxSend(n,t)},receive:function(t,u){var f,e,o;if(t.json!==t._originalJson&&(u=t._originalJson.stringify(u)),o=t._parseResponse(u),i.processMessages(t,o,t.onSuccess),t.state===n.signalR.connectionState.connected&&(t.frameMessageCount=(t.frameMessageCount||0)+1,t.frameMessageCount>r.transports.foreverFrame.iframeClearThreshold&&(t.frameMessageCount=0,f=t.frame.contentWindow||t.frame.contentDocument,f&&f.document&&f.document.body)))for(e=f.document.body;e.firstChild;)e.removeChild(e.firstChild)},stop:function(n){var r=null;if(f.cancel(),n.frame){if(n.frame.stop)n.frame.stop();else try{r=n.frame.contentWindow||n.frame.contentDocument;r.document&&r.document.execCommand&&r.document.execCommand("Stop")}catch(u){n.log("Error occured when stopping foreverFrame transport. Message = "+u.message+".")}n.frame.parentNode===t.document.body&&t.document.body.removeChild(n.frame);delete i.foreverFrame.connections[n.frameId];n.frame=null;n.frameId=null;delete n.frame;delete n.frameId;delete n.onSuccess;delete n.frameMessageCount;n.log("Stopping forever frame.")}},abort:function(n,t){i.ajaxAbort(n,t)},getConnection:function(n){return i.foreverFrame.connections[n]},started:function(t){o(t,r.connectionState.reconnecting,r.connectionState.connected)===!0&&n(t).triggerHandler(e.onReconnect)}}}(window.jQuery,window),function(n,t){var r=n.signalR,u=n.signalR.events,e=n.signalR.changeState,f=n.signalR.isDisconnecting,i=r.transports._logic,o=function(){try{return"onprogress"in new t.XMLHttpRequest}catch(n){return!1}}();r.transports.longPolling={name:"longPolling",supportsKeepAlive:function(n){return o&&n.ajaxDataType!=="jsonp"&&n._.longPollDelay===0},reconnectDelay:3e3,start:function(o,s,h){var a=this,v=function(){v=n.noop;h=null;o.log("LongPolling connected.");s()},y=function(){return h?(h(),h=null,o.log("LongPolling failed to connect."),!0):!1},c=o._,l=0,p=function(i){t.clearTimeout(c.reconnectTimeoutId);c.reconnectTimeoutId=null;e(i,r.connectionState.reconnecting,r.connectionState.connected)===!0&&(i.log("Raising the reconnect event"),n(i).triggerHandler(u.onReconnect))},w=36e5;o.pollXhr&&(o.log("Polling xhr requests already exists, aborting."),o.stop());o.messageId=null;c.reconnectTimeoutId=null;c.pollTimeoutId=t.setTimeout(function(){(function e(s,h){var d=s.messageId,g=d===null,b=!g,nt=!h,k=i.getUrl(s,a.name,b,nt);f(s)!==!0&&(o.log("Opening long polling request to '"+k+"'."),s.pollXhr=i.ajax(o,{xhrFields:{onprogress:function(){i.markLastMessage(o)}},url:k,success:function(r){var h,w=0,u,a;o.log("Long poll complete.");l=0;try{h=o._parseResponse(r)}catch(b){i.handleParseFailure(s,r,b,y,s.pollXhr);return}(c.reconnectTimeoutId!==null&&p(s),h&&(u=i.maximizePersistentResponse(h)),i.processMessages(s,h,v),u&&n.type(u.LongPollDelay)==="number"&&(w=u.LongPollDelay),u&&u.Disconnect)||f(s)!==!0&&(a=u&&u.ShouldReconnect,!a||i.ensureReconnectingState(s))&&(w>0?c.pollTimeoutId=t.setTimeout(function(){e(s,a)},w):e(s,a))},error:function(f,h){if(t.clearTimeout(c.reconnectTimeoutId),c.reconnectTimeoutId=null,h==="abort"){o.log("Aborted xhr request.");return}if(!y()){if(l++,o.state!==r.connectionState.reconnecting&&(o.log("An error occurred using longPolling. Status = "+h+". Response = "+f.responseText+"."),n(s).triggerHandler(u.onError,[r._.transportError(r.resources.longPollFailed,o.transport,f,s.pollXhr)])),(o.state===r.connectionState.connected||o.state===r.connectionState.reconnecting)&&!i.verifyLastActive(o))return;if(!i.ensureReconnectingState(s))return;c.pollTimeoutId=t.setTimeout(function(){e(s,!0)},a.reconnectDelay)}}}),b&&h===!0&&(c.reconnectTimeoutId=t.setTimeout(function(){p(s)},Math.min(1e3*(Math.pow(2,l)-1),w))))})(o)},250)},lostConnection:function(n){n.pollXhr&&n.pollXhr.abort("lostConnection")},send:function(n,t){i.ajaxSend(n,t)},stop:function(n){t.clearTimeout(n._.pollTimeoutId);t.clearTimeout(n._.reconnectTimeoutId);delete n._.pollTimeoutId;delete n._.reconnectTimeoutId;n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr)},abort:function(n,t){i.ajaxAbort(n,t)}}}(window.jQuery,window),function(n){function r(n){return n+e}function s(n,t,i){for(var f=n.length,u=[],r=0;r + /// + /// + public class ServiceController : DnnApiController + { + #region WebApi Methods + + /// + /// + /// + /// + [HttpGet] + [AllowAnonymous] + public HttpResponseMessage DetectVisitorsOnline() + { + var visitorsOnlineEnabled = bool.Parse(PortalController.GetPortalSetting("MyDnnEnableVisitorsOnline", PortalSettings.PortalId, "false")); + + return Request.CreateResponse(HttpStatusCode.OK, new + { + RootUrl = DotNetNuke.Common.Globals.ResolveUrl("~/"), + VisitorsOnlineEnabled = visitorsOnlineEnabled, + PortalID = PortalSettings.PortalId, + }); + } + + #endregion + } +} \ No newline at end of file diff --git a/MyDnnVisitorsOnline/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/MyDnnVisitorsOnline/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..5d296c3 Binary files /dev/null and b/MyDnnVisitorsOnline/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/MyDnnVisitorsOnline/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/MyDnnVisitorsOnline/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 0000000..e69de29 diff --git a/MyDnnVisitorsOnline/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/MyDnnVisitorsOnline/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 0000000..e69de29 diff --git a/MyDnnVisitorsOnline/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/MyDnnVisitorsOnline/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 0000000..e69de29