'use strict'; /* jshint eqnull: true, shadow: false, quotmark: single, undef: true, eqeqeq: true, unused: true, strict: true, curly: false, funcscope: true, globalstrict: true */ /* global HTMLElement, console, window, document, StaticLib */ window.LoadingScreenTaskTypes = { 'app': 1, 'api': 2 }; window.LoadingTaskSTRUCT = function(obj) { /*this.__Props = { Type: new window.Framework.DataTypes.IntPropStruct ({name: propName({Type:0}) }), TaskID: new window.Framework.DataTypes.StringPropStruct ({name: propName({TaskID:0}) }), IsStub: new window.Framework.DataTypes.BooleanPropStruct ({name: propName({IsStub:0}) }), IsComplete: new window.Framework.DataTypes.BooleanPropStruct ({name: propName({IsComplete:0}) }), TaskDescription: new window.Framework.DataTypes.StringPropStruct ({name: propName({TaskDescription:0}) }), Priority: new window.Framework.DataTypes.IntPropStruct ({name: propName({Priority:0}) }) }; this.Setup(null, obj);*/ this.Type = 0; this.TaskID = ''; this.IsStub = false; this.IsComplete = false; this.TaskDescription = ''; this.Priority = 0; if ((typeof(obj) !== 'undefined') && (obj !== null)) { if ((typeof(obj.Type) !== 'undefined') && (typeof(obj.Type) !== 'number')) throw new Error('LoadingTaskSTRUCT.Type expects an Integer'); if ((typeof(obj.TaskID) !== 'undefined') && (typeof(obj.TaskID) !== 'string')) throw new Error('LoadingTaskSTRUCT.TaskID expects a String'); if ((typeof(obj.IsStub) !== 'undefined') && (typeof(obj.IsStub) !== 'boolean')) throw new Error('LoadingTaskSTRUCT.IsStub expects a Boolean'); if ((typeof(obj.IsComplete) !== 'undefined') && (typeof(obj.IsComplete) !== 'boolean')) throw new Error('LoadingTaskSTRUCT.IsComplete expects a Boolean'); if ((typeof(obj.TaskDescription) !== 'undefined') && (typeof(obj.TaskDescription) !== 'string')) throw new Error('LoadingTaskSTRUCT.TaskDescription expects a String'); if ((typeof(obj.Priority) !== 'undefined') && (typeof(obj.Priority) !== 'number')) throw new Error('LoadingTaskSTRUCT.Priority expects an Integer'); StaticLib.SetProps(this, obj); } }; /*window.LoadingTaskSTRUCT.prototype = new window.Framework.Lib.PropsBaseV3(true); window.LoadingTaskSTRUCT.prototype.constructor = window.LoadingTaskSTRUCT; StaticLib.DeepSealInheritable(window.LoadingTaskSTRUCT);*/ window.LoadingScreenPropSTRUCT = function(obj) { /*this.__Props = { TaskList: new window.Framework.DataTypes.ArrayOfPropStructs ({name: propName({TaskList:0}), DataType: window.LoadingTaskSTRUCT, defaultValue: null, allownull: true}), UncompletedTaskIndex: new window.Framework.DataTypes.ArrayPropStruct ({name: propName({UncompletedTaskIndex:0}) }), CompletedTaskIndex: new window.Framework.DataTypes.ArrayPropStruct ({name: propName({CompletedTaskIndex:0}) }), AllTasksIndex: new window.Framework.DataTypes.ArrayPropStruct ({name: propName({AllTasksIndex:0}) }), TotalTasks: new window.Framework.DataTypes.IntPropStruct ({name: propName({TotalTasks:0}) }), TasksRemaining: new window.Framework.DataTypes.IntPropStruct ({name: propName({TasksRemaining:0}) }), TaskStatuses: new window.Framework.DataTypes.ArrayPropStruct ({name: propName({TaskStatuses:0}) }), CurrentTask: new window.Framework.DataTypes.ChildPropStruct ({name: propName({CurrentTask:0}), DataType: window.LoadingTaskSTRUCT, defaultValue: null, allownull: true}), IsDisplayed: new window.Framework.DataTypes.BooleanPropStruct ({name: propName({IsDisplayed:0}) }), ParentContainer: new window.Framework.DataTypes.ObjectPropStruct ({name: propName({ParentContainer:0}), defaultValue: null, allownull: true }) }; this.Setup(null, obj);*/ this.TaskList = []; this.UncompletedTaskIndex = []; this.CompletedTaskIndex = []; this.AllTasksIndex = {}; this.TotalTasks = 0; this.TasksRemaining = 0; this.TaskStatuses = {}; this.CurrentTask = null; this.IsDisplayed = false; this.ParentContainer = null; if ((typeof(obj) !== 'undefined') && (obj !== null)) { if ((typeof(obj.TaskList) !== 'undefined') && (typeof(obj.TaskList) !== 'object') && (obj.TaskList !== null)) throw new Error('LoadingScreenPropSTRUCT.TaskList expects an Object'); if ((typeof(obj.UncompletedTaskIndex) !== 'undefined') && (typeof(obj.UncompletedTaskIndex) !== 'object') && (obj.UncompletedTaskIndex !== null)) throw new Error('LoadingScreenPropSTRUCT.UncompletedTaskIndex expects an Object'); if ((typeof(obj.CompletedTaskIndex) !== 'undefined') && (typeof(obj.CompletedTaskIndex) !== 'object') && (obj.CompletedTaskIndex !== null)) throw new Error('LoadingScreenPropSTRUCT.CompletedTaskIndex expects an Object'); if ((typeof(obj.AllTasksIndex) !== 'undefined') && (typeof(obj.AllTasksIndex) !== 'object') && (obj.AllTasksIndex !== null)) throw new Error('LoadingScreenPropSTRUCT.AllTasksIndex expects an Object'); if ((typeof(obj.TotalTasks) !== 'undefined') && (typeof(obj.TotalTasks) !== 'number')) throw new Error('LoadingScreenPropSTRUCT.TotalTasks expects an Integer'); if ((typeof(obj.TasksRemaining) !== 'undefined') && (typeof(obj.TasksRemaining) !== 'number')) throw new Error('LoadingScreenPropSTRUCT.TasksRemaining expects an Integer'); if ((typeof(obj.TaskStatuses) !== 'undefined') && (typeof(obj.TaskStatuses) !== 'object') && (obj.TaskStatuses !== null)) throw new Error('LoadingScreenPropSTRUCT.TaskStatuses expects an Object'); if ((typeof(obj.CurrentTask) !== 'undefined') && (typeof(obj.CurrentTask) !== 'object') && (obj.CurrentTask !== null)) throw new Error('LoadingScreenPropSTRUCT.CurrentTask expects an Object'); if ((typeof(obj.IsDisplayed) !== 'undefined') && (typeof(obj.IsDisplayed) !== 'boolean')) throw new Error('LoadingScreenPropSTRUCT.IsDisplayed expects a Boolean'); if ((typeof(obj.ParentContainer) !== 'undefined') && (typeof(obj.ParentContainer) !== 'object') && (obj.ParentContainer !== null)) throw new Error('LoadingScreenPropSTRUCT.ParentContainer expects an Object'); StaticLib.SetProps(this, obj); } }; /*window.LoadingScreenPropSTRUCT.prototype = new window.Framework.Lib.PropsBaseV3(true); window.LoadingScreenPropSTRUCT.prototype.constructor = window.LoadingScreenPropSTRUCT; StaticLib.DeepSealInheritable(window.LoadingScreenPropSTRUCT);*/ window.LoadingScreen = function(LoadingStruct) { if ((typeof(LoadingStruct) !== 'undefined') && (StaticLib.Empty(LoadingStruct))) { /* developer code start */ if (typeof(window.Framework) !== 'undefined') { if (typeof(window.Framework.prop) !== 'undefined') { if (window.Framework.prop.developer) { console.log('LoadingStruct is undefined'); } } } /* developer code end */ return null; } /****************************************************************/ // // Form Objects // /****************************************************************/ this.FormObjects = { OuterDiv: null, TaskDescription: null, CompletionBar: null, CompletionNum: null }; /****************************************************************/ // // props // /****************************************************************/ this.prop = new window.LoadingScreenPropSTRUCT(LoadingStruct, {autobind: true, parent: this}); /****************************************************************/ // // props // /****************************************************************/ this.vars = {IsLoading: true}; /****************************************************************/ // // constructor // /****************************************************************/ this.ctorInternal = function() { if (this.prop.TaskList !== null) { if (this.prop.TaskList.length > 0) { var tasks = this.prop.TaskList; this.prop.TaskList = []; for (var count = 0; count < tasks.length; count++) { this.AddTask(tasks[count]); } this.vars.IsLoading = false; this.ShowLoadingScreen(); } } this.vars.IsLoading = false; }; this.ShowLoadingScreen = function() { if (this.prop.IsDisplayed !== true) { this.prop.IsDisplayed = true; if (this.prop.ParentContainer === null) { this.prop.ParentContainer = document.body; } else if (!(this.prop.ParentContainer instanceof HTMLElement)) { throw new Error('Can\'t pass a ParentContainer that is not a DOM element'); } this.FormObjects.OuterDiv = document.createElement('div'); this.FormObjects.OuterDiv.setAttribute('id', 'LoadingScreen'); this.FormObjects.OuterDiv.setAttribute('class', 'LoadingScreen'); this.FormObjects.TaskDescription = document.createElement('h1'); this.FormObjects.TaskDescription.setAttribute('class', 'TaskDescription'); this.FormObjects.OuterDiv.appendChild(this.FormObjects.TaskDescription); var completionContainer = document.createElement('div'); completionContainer.setAttribute('class', 'CompletionContainer'); this.FormObjects.OuterDiv.appendChild(completionContainer); this.FormObjects.CompletionBar = document.createElement('div'); this.FormObjects.CompletionBar.setAttribute('class', 'CompletionBar'); completionContainer.appendChild(this.FormObjects.CompletionBar); this.FormObjects.CompletionNum = document.createElement('div'); this.FormObjects.CompletionNum.setAttribute('class', 'CompletionNum'); completionContainer.appendChild(this.FormObjects.CompletionNum); this.prop.ParentContainer.appendChild(this.FormObjects.OuterDiv); this.ShowCurrentTask(); } }; this.ClearLoadingScreen = function() { try { this.prop.ParentContainer.removeChild(this.FormObjects.OuterDiv); this.prop.IsDisplayed = false; } catch(e) { if (typeof(window.Framework) !== 'undefined') { if (typeof(window.Framework.prop) !== 'undefined') { if (window.Framework.prop.developer) { console.log('Developer Warning: Failed to ClearLoadingScreen... because it was already removed?'); } } } } }; this.AddTask = function(task) { var newTask = new window.LoadingTaskSTRUCT(task); var orderedTasks = null; var currentTaskLocation = 0; var currentTask = null; var tasks = this.prop.AllTasksIndex; if ((tasks !== null) && (typeof(tasks[newTask.TaskID]) !== 'undefined')) { //if (this.prop.TaskList[tasks[newTask.TaskID]].IsStub !== true) throw new Error('Can\'t call AddTask for a task that already exists and is not a Stub.'); currentTaskLocation = tasks[newTask.TaskID]; tasks = this.prop.TaskList; var uncompleted = null; var completed = null; var oldIndex = null; var statuses = null; if (tasks[currentTaskLocation].IsComplete) { //OLD TASK IS COMPLETE if (!newTask.IsComplete) { uncompleted = this.prop.UncompletedTaskIndex; uncompleted.push(currentTaskLocation); this.prop.UncompletedTaskIndex = uncompleted; this.prop.TasksRemaining++; completed = this.prop.CompletedTaskIndex; oldIndex = completed.indexOf(currentTaskLocation); completed.splice(oldIndex, 1); this.prop.CompletedTaskIndex = completed; statuses = this.prop.TaskStatuses; statuses[newTask.TaskID] = false; this.prop.TaskStatuses = statuses; } } else { //OLD TASK IS NOT COMPLETE if (newTask.IsComplete) { completed = this.prop.CompletedTaskIndex; completed.push(currentTaskLocation); this.prop.CompletedTaskIndex = completed; this.prop.TasksRemaining--; uncompleted = this.prop.UncompletedTaskIndex; oldIndex = uncompleted.indexOf(currentTaskLocation); uncompleted.splice(oldIndex, 1); this.prop.UncompletedTaskIndex = uncompleted; statuses = this.prop.TaskStatuses; statuses[newTask.TaskID] = true; this.prop.TaskStatuses = statuses; } } tasks[currentTaskLocation] = newTask; this.prop.TaskList = tasks; if(this.prop.UncompletedTaskIndex.length > 0) { if (this.prop.IsDisplayed !== true) { this.ShowLoadingScreen(); } else { this.ShowCurrentTask(); } } return; } if (this.prop.CompletedTaskIndex === null) this.prop.CompletedTaskIndex = []; if (this.prop.UncompletedTaskIndex === null) this.prop.UncompletedTaskIndex = []; if (newTask.IsComplete) { orderedTasks = this.prop.CompletedTaskIndex; } else { orderedTasks = this.prop.UncompletedTaskIndex; } for (var count = 0; count <= orderedTasks.length; count++) { if (count < orderedTasks.length) { //Not done testing rows currentTaskLocation = orderedTasks[count]; currentTask = this.prop.TaskList[currentTaskLocation]; if (newTask.Priority > currentTask.Priority) { break; } } else { //tested all rows, add to end currentTaskLocation = orderedTasks.length; } } //add to list of tasks tasks = this.prop.TaskList; if (tasks === null) tasks = []; var newIndex = tasks.length; tasks.push(newTask); this.prop.TaskList = tasks; this.prop.TotalTasks++; //add it to the list of statuses tasks = this.prop.TaskStatuses; if (tasks === null) tasks = []; tasks[newTask.TaskID] = newTask.IsComplete; this.prop.TaskStatuses = tasks; //Add it to the sorted index list of tasks tasks = this.prop.AllTasksIndex; if (tasks === null) tasks = {}; tasks[newTask.TaskID] = newIndex; this.prop.AllTasksIndex = tasks; if (newTask.IsComplete) { //OPTIONAL: Add it to the sorted index list of Completed tasks tasks = this.prop.CompletedTaskIndex; if (tasks === null) tasks = []; tasks.splice(count, 0, newIndex); this.prop.CompletedTaskIndex = tasks; } else { //OPTIONAL: Add it to the sorted index list of Uncompleted tasks tasks = this.prop.UncompletedTaskIndex; if (tasks === null) tasks = []; tasks.splice(count, 0, newIndex); this.prop.UncompletedTaskIndex = tasks; //It is now another task we are waiting on this.prop.TasksRemaining++; if (this.vars.IsLoading !== true) { if (this.prop.IsDisplayed !== true) { this.ShowLoadingScreen(); } } } }; this.HasTask = function(TaskID) { var index = this.prop.AllTasksIndex[TaskID]; return (index !== -1); }; this.CompleteTask = function(TaskID) { var index = this.prop.AllTasksIndex[TaskID]; if (index === -1) return;//throw new Error('Cannot complete Task:' + TaskID + ', because this Loading Screen isn\'t waiting on it'); if (typeof(index) === 'undefined') return; if (this.prop.TaskStatuses[TaskID] === true) { //Task Already Complete return true; } var tasks = this.prop.UncompletedTaskIndex; var uncompletedIndex = tasks.indexOf(index); this.prop.TaskStatuses[TaskID] = true; this.prop.TaskList[index].IsComplete = true; //Remove the one task tasks.splice(uncompletedIndex, 1); this.prop.UncompletedTaskIndex = tasks; this.prop.TasksRemaining = tasks.length; if (this.prop.TasksRemaining > 0) { if (this.prop.CurrentTask.TaskID === TaskID) { this.ShowCurrentTask(); } else { this.ShowCurrentCompletion(); } } else { this.ClearLoadingScreen(); } }; this.ShowCurrentTask = function() { var orderedTasks = this.prop.UncompletedTaskIndex; if (orderedTasks.length <= 0) { //throw new Error('Cannot ShowCurrentTask, there are no uncompleted tasks left'); return; } var count = 0; var nextIndex = orderedTasks[count]; var nextTask = this.prop.TaskList[nextIndex]; while ((nextTask.IsStub) && (count < orderedTasks.length)) { count++; nextIndex = orderedTasks[count]; nextTask = this.prop.TaskList[nextIndex]; } this.prop.CurrentTask = nextTask; this.FormObjects.TaskDescription.innerHTML = this.prop.CurrentTask.TaskDescription; var completePercent = ((1 - (this.prop.TasksRemaining / this.prop.TotalTasks)) * 100); this.SetComplete(completePercent); }; this.ShowCurrentCompletion = function() { var completePercent = ((1 - (this.prop.TasksRemaining / this.prop.TotalTasks)) * 100); this.SetComplete(completePercent); }; this.SetComplete = function(percent) { if (this.prop.IsDisplayed !== true) throw new Error('Cannot SetComplete, the LoadingScreen is not visible'); this.FormObjects.CompletionBar.style.width = (percent + '%'); this.FormObjects.CompletionNum.innerHTML = (Math.round(percent) + '%'); }; //this.Setup(null, null); this.ctorInternal(); return this; }; //window.Framework.Controls.LoadingScreen.prototype = new window.Framework.Lib.PropsBaseV3(true); //window.Framework.Controls.LoadingScreen.prototype.constructor = window.Framework.Controls.LoadingScreen; StaticLib.DeepSeal(window.Framework.Controls.LoadingScreen); StaticLib.DeepFreeze(window.Framework.Controls.LoadingScreen);