AngularJS and QUnit: Unknown provider: LocalDataProvider <- LocalData <- FileLogger - angularjs

Anyone who can help me fix this? I'm such a beginner in unit testing scripts.
Here's my html code.
<html>
<head>
<meta charset = "utf-8">
<title>QUnit and AngularJS</title>
<link rel = "stylesheet" href = "https://code.jquery.com/qunit/qunit-1.22.0.css">
<script src = "https://code.angularjs.org/1.1.0/angular.js"></script>
<script src = "https://code.angularjs.org/1.1.0/angular-mocks.js"></script>
<script src = "https://code.jquery.com/qunit/qunit-1.22.0.js"></script>
<script src = "OfflineStorage/local-storage.service.js"></script>
<script src = "AppLogging/file-logger.service.js"></script>
<script src = "basic.js"></script>
<script src = "qunit.js"></script>
</head>
<body>
<div id = "qunit"></div>
<div id = "qunit-fixture"></div>
</body>
</html>
here's qunit js.
var injector = angular.injector(['ng', 'FileLoggerManager']);
module("File Logger Test", function () {
var svc = injector.get('FileLogger');
});
and here's the one that needed to be tested.
(function() {
'use strict';
angular
.module('FileLoggerManager', [])
.service('FileLogger', Body);
function Body(LocalData, $q, $timeout) {
var service = {
writeLog: writeLog,
SetLogLevel: SetLogLevel,
SetFilePath: SetFilePath,
SetMaxLogSize: SetMaxLogSize,
DeleteLogFiles: DeleteLogFiles,
SendLogsToEmail: SendLogsToEmail
};
// LOG WRITER
var logOb;
var logDirOb;
var logLocation;
var curlogsize = 0;
var logStrings = [];
var loggingStopped = true;
// DEFAULT CURRENT LOG FILE NAME
var logfilename = "MPC";
var appObj = null;
var maxlogsize = 1000000;
var customlogfolder = "sdcard/";
var maxloglevel = 2;
console.log("File Logger initialized.");
// SETTINGS
if (LocalData.loadData('application')) {
appObj = JSON.parse(LocalData.loadData('application'));
// MAX LOGFILE SIZE (BYTES)
maxlogsize = 1000000 * ( appObj.maxLogFileSize ? appObj.maxLogFileSize : 1 );
// LOG SAVE PATH CUSTOM FOLDER NAME
customlogfolder = appObj.logFilePath ? appObj.logFilePath + '/' : 'sdcard/';
// MAX LOG LEVEL (everything below will be logged)
maxloglevel = appObj.logLevel ? appObj.logLevel : 2;
}
// DEVICE READY
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady(){
// WRITE AND GET LOG FILE READY
SetFilePath(customlogfolder);
}
// SET LOG LEVEL
function SetLogLevel(logLevel) {
console.log("File Logger: Set log level to " + logLevel);
maxloglevel = logLevel;
}
// SET FILE PATH
function SetFilePath(filePath) {
while (filePath.indexOf('//') > -1) {
filePath = filePath.replace('//','/');
}
while(filePath[0] == '/') {
filePath = filePath.substring(1);
}
if (filePath[filePath.length-1] != '/') {
filePath = filePath + '/';
}
if (filePath.indexOf('sdcard') == 0) {
filePath = filePath.substring(7);
}
customlogfolder = filePath;
logLocation = cordova.file.externalRootDirectory + customlogfolder;
console.log("File Logger: Log Path = " + customlogfolder);
if (customlogfolder == "") {
initializeLogFile(logLocation);
}
else {
checkIfDirectoryExist(customlogfolder, cordova.file.externalRootDirectory);
}
}
/*
CHECK IF DIRECTORY EXISTS
*/
function checkIfDirectoryExist(filePath, rootDirLoc) {
window.resolveLocalFileSystemURL(filePath, function(dir) {
console.log("File Logger: Path found = " + filePath);
},
function (dir) {
var curFolder = filePath;
var withSubDir = false;
if ((filePath.indexOf('/') > 0) &&
(filePath.indexOf('/') != filePath.length-1)) {
withSubDir = true;
curFolder = filePath.substring(0, filePath.indexOf('/'));
}
window.resolveLocalFileSystemURL(rootDirLoc, function(dir) {
dir.getDirectory(curFolder, { create: true }, function (dirEntry) {
console.log("File Logger: New Directory = " + curFolder );
if(withSubDir == false) {
initializeLogFile(logLocation);
}
},
function(dirEntry) {
console.log("File Logger: Create Dir failed = " + curFolder);
});
},
function(dir){
console.log("File Logger: Root directory not found = " + rootDirLoc);
});
if (withSubDir) {
filePath = filePath.substring(filePath.indexOf('/')+1);
checkIfDirectoryExist(filePath, rootDirLoc + curFolder + '/');
}
});
}
// INITIALIZE AND CREATE LOG FILE
function initializeLogFile(logLocation) {
window.resolveLocalFileSystemURL(logLocation, function(dir) {
logDirOb = dir;
dir.getFile(logfilename + ".txt", { create:true }, function(file) {
logOb = file;
writeToLog();
});
});
}
// SET MAX SIZE
function SetMaxLogSize (maxSize) {
maxlogsize = 1000000 * ( maxSize? maxSize : 1 );
console.log("File Logger: Max File size = " + maxlogsize);
}
// WRITE LOG
function writeToLog() {
if(!logOb){
console.log("File Logger: No log added.");
return;
}
if(logStrings.length == 0) {
return;
}
loggingStopped = false;
logOb.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
logStrings.splice(0,1);
if(logStrings.length == 0) {
loggingStopped = true;
}
else {
loggingStopped = false;
writeToLog();
}
};
var log = logStrings[0];
fileWriter.seek(fileWriter.length);
var blob = new Blob([log], {type:'text/plain'});
fileWriter.write(blob);
}, ReadLogfail);
CheckLogSize();
}
function writeLog(logLevel, str) {
if (maxloglevel == 0) return;
if (maxloglevel>=logLevel && logLevel>0){
var level;
if(logLevel == 4)
level = "DEBUG";
else if(logLevel == 3)
level = "INFO";
else if(logLevel == 2)
level = "WARNING";
else if(logLevel == 1)
level = "ERROR";
var log = "[" + GetLogDate() + "] " + level + " : " + str + "\n";
logStrings.push(log);
if(loggingStopped){
writeToLog();
}
}
}
// CHECK LOG SIZE
function CheckLogSize(){
logOb.file(function(file) {
curlogsize = file.size;
if (parseFloat(curlogsize)>parseFloat(maxlogsize)) {
DeleteLogFiles();
initializeLogFile(logLocation);
}
}, ReadLogfail);
}
function ReadLogfail(e) {
console.log("File Logger: FileSystem Error");
console.dir(e);
}
// GET DATE (SERIAL/NORMAL)
function GetLogDate(){
//var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var date = new Date();
var dateYear = date.getFullYear();
var dateMonth = LogPad(date.getMonth()+1);
var dateDay = LogPad(date.getDate());
var dateHour = LogPad(date.getHours());
var dateMinute = LogPad(date.getMinutes());
var dateSeconds = LogPad(date.getSeconds());
return dateYear + '.' + dateMonth + '.' + dateDay + ' ' + dateHour + ':' + dateMinute + ':' + dateSeconds;
}
// ADD 0 if number is below 9
function LogPad(n){
return n<10 ? '0'+n : n;
}
// DELETE LOG FILE
function DeleteLogFiles(){
if (!logOb) return 0;
window.resolveLocalFileSystemURL(logLocation, function(dir) {
logDirOb = dir;
dir.getFile(logfilename+".txt", {create:true}, function(file) {
file.remove(function() {
console.log('File logger: File removed = ' + logfilename + ".txt");
});
});
});
}
function SendLogsToEmail() {
cordova.plugins.email.isAvailable( function (isAvailable) {
if(isAvailable) {
cordova.plugins.email.open({
to: '',
subject: 'MSCM MPC Logs',
body: '',
attachments: [logLocation+'MPC.txt',logLocation+'MPC_COMM.txt']
});
} else {
console.log("No email account is setup in this device.");
var confirmPopup = $ionicPopup.alert({
cssClass: 'custom-popup',
template: '<div>{{ "confirm_no_email_setup" | translate }}</div>'
});
};
});
}
return service;
}})();
However while writing QUnit test an error occurs. "Unknown provider: LocalDataProvider <- LocalData <- FileLogger".
Thanks in advance!

Related

How to configure Vzaar Video Tracking in Tealium

I am trying to configure Vzaar video tracking in Tealium. There is very little documentation on how to go about.
here is a link to the documentation
https://community.tealiumiq.com/t5/iQ-Tag-Management/Vzaar-Video-Tracking/ta-p/5934
here is the custom javascript code provided by the documentation mentioned in the above link
var video_events = ["playState","progress","interaction"]; // Possible values are "playState", "progress" and/or "integration"
var milestone_percentages = ["10","20","30","40","90"]; // These must be rounded to the nearest 10
var player_element_id = "vzvd-1556961";
var player_type = "iframe"; // Possible values are "iframe" or "html"
var played = false;
var m1 = false;
var m2 = false;
var m3 = false;
var m4 = false;
// Call utag.link in Vzaar event listeners
window._tealium_VZ = {
name : "Vzaar",
init_tries : 0,
eventsAdded : false,
events : video_events,
milestone_percentages : milestone_percentages,
mediaEventHandler : function (pEvent) {
pos = _tealium_VZ.player_object.getTime();
dur = _tealium_VZ.player_object.getTotalTime();
if (pEvent=="mediaStarted" || pEvent=="started") {
alert('I am here');
played = true;
utag.DB("**** video started ****");
utag.link({event_type:"video",event_name:"play"})
////s.Media.open(video_name, video_duration, video_player);
////s.Media.play(video_name, 0);
//s.Media.track(video_name);
} else if(pEvent=="resume"){
//s.Media.play(video_name, 0);
//s.Media.track(video_name);
_tealium_VZ.pause = false;
utag.link({event_type:"video",event_name:"resume",video_position:pos,video_duration:dur})
utag.DB("**** video resumed ****");
}else if(pEvent=="pause"){
//s.Media.stop(video_name, video_position);
//s.Media.track(video_name);
_tealium_VZ.pause = true;
utag.link({event_type:"video",event_name:"pause",video_position:pos,video_duration:dur})
utag.DB("**** video paused****");
utag.DB("**** Position: " + pos);
utag.DB("**** Total Duration: " + dur);
}else if(pEvent=="mediaEnded"){
//s.Media.complete(video_name, video_position);
//s.Media.stop(video_name, video_position);
//s.Media.track(video_name);
played = false;
//_tealium_VZ.resetMilestones();
utag.link({event_type:"video",event_name:"complete",video_position:pos,video_duration:dur})
utag.DB("**** video complete****");
}else{
var ms = pEvent.replace(/[^0-9]/g, "")
for(var i=0;i<_tealium_VZ.milestone_percentages.length;i++){
if(ms==_tealium_VZ.milestone_percentages[i]){
var ms_num =(i+1);
utag.link({event_type:"video",event_name:"milestone",video_milestone:"M:"+ms_num+":"+_tealium_VZ.milestone_percentages[i],video_position:pos,video_duration:dur})
utag.DB("**** "+_tealium_VZ.milestone_percentages[i]+"% viwed****");
}
}
}
},
// Attaching Event Listeners for Begin, Play, Stop, and Video Completion
// Each Event Handler has a callback function attached to it (mediaEventHandler) which will be called when the event occurs
addEvents : function(a){
utag.DB("***** Adding Events ******");
if(a=="iframe"){
for(var i=0;i<video_events.length;i++){
_tealium_VZ.player_object.addEventListener(_tealium_VZ.events[i],_tealium_VZ.mediaEventHandler);
}
}else{
for(var i=0;i<video_events.length;i++){
_tealium_VZ.player_object.addEventListener(_tealium_VZ.events[i],"_tealium_VZ.mediaEventHandler");
}
}
},
init : function(){
// utag.DB("Connecting Tealium with Vzaar object");
if(typeof vzPlayer!="undefined"){
if(player_type=="iframe"){
vz_player = new vzPlayer(player_element_id)
vz_player.ready(function(e){
utag.DB("TEALIUM: Connecting Tealium with Oyala Player - SUCCESS");
_tealium_VZ.player_object = vz_player;
_tealium_VZ.addEvents(player_type)
utag.DB("****** Events Added ******");
_tealium_VZ.eventsAdded = true;
})
}else{
window.vzaarPlayerReady = function() {
utag.DB("*********** Video Ready **************");
utag.DB("TEALIUM: Connecting Tealium with Oyala Player - SUCCESS");
vzPlayer = document.getElementById(player_element_id);
_tealium_VZ.player_object = vzPlayer;
_tealium_VZ.addEvents(player_type)
utag.DB("****** Events Added ******");
_tealium_VZ.eventsAdded = true;
_tealium_VZ.readyFunction = true;
}
}
}else if(!_tealium_VZ.eventsAdded){
// If Vzaar object is not defined we will increment the number of tries by 1
_tealium_VZ.init_tries += 1;
//Stop trying to connect to the Video Player if tried 100 times
if(_tealium_VZ.init_tries>100){
utag.DB("TEALIUM: Cannot connect to Vzaar Video");
return;
}
// Calls init function repeatedly either 100 times or Vzaar Object is defined
setTimeout(function(){_tealium_VZ.init()}, 100);
}
}
}
if(typeof _tealium_VZ.videoPlayer == "undefined"){
_tealium_VZ.init();
}
I start this script off with this snippet I wrote to append to the iframe url, and I also set the custom javascript code extension to the preloader function
window.addEventListener('load', function(){
var ifrm = document.getElementsByTagName('iframe')[0];
ifrm.src += '&apiOn=true';
}, false);
I am still not seeing any events being fired when I press play on the video. What do I need to do to this script to start receiving tracking data? I am guessing I need to take out some comment blocks in the script provided by the Tealium Learning Community Docs however, I'm trying and still not seeing results. Any help would be appreciated!
There a couple of things you should check, and due to the lack of processing order context I will assume, so apologies if you already took that into consideration.
The pre loader extension
You are copy/pasting the extension content here, but did you consider the 3rd line where the id needs to be specified?
var player_element_id = "vzvd-1556961";
Im just mentioning because in your custom script you are fetching the element based on TAG type
var ifrm = document.getElementsByTagName('iframe')[0];
On the custom script it would be advisable to check if the query parameter is already there.
window.addEventListener('load', function(){
var ifrm = document.getElementsByTagName('iframe')[0];
if (ifrm.src.indexOf("apiOn=true") === -1)
if (ifrm.src.indexOf("?") === -1)
ifrm.src += '?apiOn=true';
else
ifrm.src += '&apiOn=true';
}, false);
Because with Tealium everything is async, there is always the possibility that the "pre-loader" extension runs the code before the iframe is ready on DOM. Therefore to make sure the extension code is only initialized when the document is ready, I would move the extension object initializing instruction to the body of the custom script.
Something like this:
window.addEventListener('load', function(){
var ifrm = document.getElementsByTagName('iframe')[0];
if (ifrm.src.indexOf("apiOn=true") === -1)
if (ifrm.src.indexOf("?") === -1)
ifrm.src += '?apiOn=true';
else
ifrm.src += '&apiOn=true';
if (typeof _tealium_VZ.videoPlayer == "undefined") {
_tealium_VZ.init();
}
}, false);
Finally make sure the vzaar client.js script is also loaded on the page as per your refered Tealium document
Here is a snippet to add it dinamically if the dev's didnt add it to the page. You can add it to the top of the "pre-loader" extension code
(function (a, b, c, d) {
a = '//player.vzaar.net/libs/flashtakt/client.js';
b = document;
c = 'script';
d = b.createElement(c);
d.src = a;
d.type = 'text/java' + c;
d.async = true;
a = b.getElementsByTagName(c)[0];
a.parentNode.insertBefore(d, a)
})();
So following your custom code logic, here is a full tracking code snippet for vzaar for a pre-loader extension in Tealium.
(function (a, b, c, d) {
a = '//player.vzaar.net/libs/flashtakt/client.js';
b = document;
c = 'script';
d = b.createElement(c);
d.src = a;
d.type = 'text/java' + c;
d.async = true;
a = b.getElementsByTagName(c)[0];
a.parentNode.insertBefore(d, a)
})();
var video_events = ["playState", "progress", "interaction"]; // Possible values are "playState", "progress" and/or "integration"
var milestone_percentages = ["10", "20", "30", "40", "90"]; // These must be rounded to the nearest 10
var player_element_id = "video";
var player_type = "iframe"; // Possible values are "iframe" or "html"
var fireEvent = true;
var played = false;
var m1 = false;
var m2 = false;
var m3 = false;
var m4 = false;
window._tealium_VZ = {
name: "Vzaar",
init_tries: 0,
eventsAdded: false,
events: video_events,
milestone_percentages: milestone_percentages,
mediaEventHandler: function (pEvent) {
pos = _tealium_VZ.player_object.getTime();
dur = _tealium_VZ.player_object.getTotalTime();
if (pEvent == "mediaStarted" || pEvent == "started") {
played = true;
var data = {event_type: "video", event_name: "play"};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else if (pEvent == "resume") {
_tealium_VZ.pause = false;
var data = {event_type: "video", event_name: "resume", video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else if (pEvent == "pause") {
_tealium_VZ.pause = true;
var data = {event_type: "video", event_name: "pause", video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else if (pEvent == "mediaEnded") {
played = false;
//_tealium_VZ.resetMilestones();
var data = {event_type: "video", event_name: "complete", video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else {
var ms = pEvent.replace(/[^0-9]/g, "")
for (var i = 0; i < _tealium_VZ.milestone_percentages.length; i++) {
if (ms == _tealium_VZ.milestone_percentages[i]) {
var ms_num = (i + 1);
var data = {event_type: "video", event_name: "milestone", video_milestone: "M:" + ms_num + ":" + _tealium_VZ.milestone_percentages[i], video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
}
}
}
},
addEvents: function (a) {
console.log("***** Adding Events ******");
if (a == "iframe") {
for (var i = 0; i < video_events.length; i++) {
_tealium_VZ.player_object.addEventListener(_tealium_VZ.events[i], _tealium_VZ.mediaEventHandler);
}
} else {
for (var i = 0; i < video_events.length; i++) {
_tealium_VZ.player_object.addEventListener(_tealium_VZ.events[i], "_tealium_VZ.mediaEventHandler");
}
}
},
init: function () {
if (typeof vzPlayer != "undefined") {
if (player_type == "iframe") {
vz_player = new vzPlayer(player_element_id)
vz_player.ready(function (e) {
console.log("TEALIUM: Connecting Tealium with Oyala Player - SUCCESS");
_tealium_VZ.player_object = vz_player;
_tealium_VZ.addEvents(player_type)
console.log("****** Events Added ******");
_tealium_VZ.eventsAdded = true;
})
} else {
window.vzaarPlayerReady = function () {
console.log("*********** Video Ready **************");
console.log("TEALIUM: Connecting Tealium with Oyala Player - SUCCESS");
vzPlayer = document.getElementById(player_element_id);
_tealium_VZ.player_object = vzPlayer;
_tealium_VZ.addEvents(player_type)
console.log("****** Events Added ******");
_tealium_VZ.eventsAdded = true;
_tealium_VZ.readyFunction = true;
}
}
} else if (!_tealium_VZ.eventsAdded) {
// If Vzaar object is not defined we will increment the number of tries by 1
_tealium_VZ.init_tries += 1;
//Stop trying to connect to the Video Player if tried 100 times
if (_tealium_VZ.init_tries > 100) {
console.log("TEALIUM: Cannot connect to Vzaar Video");
return;
}
// Calls init function repeatedly either 100 times or Vzaar Object is defined
setTimeout(function () {
_tealium_VZ.init()
}, 100);
}
}
}
window.addEventListener('load', function(){
var ifrm = document.getElementsByTagName('iframe')[0];
if (ifrm.src.indexOf("apiOn=true") === -1)
if (ifrm.src.indexOf("?") === -1)
ifrm.src += '?apiOn=true';
else
ifrm.src += '&apiOn=true';
player_element_id = ifrm.id;
if (typeof _tealium_VZ.videoPlayer == "undefined") {
_tealium_VZ.init();
}
}, false);
Here is a full working page working with the tracking code from refered Tealium documentation link:
<html>
<head>
<title>vzaar</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://player.vzaar.net/libs/flashtakt/client.js" type="text/javascript"></script>
<script>
var video_events = ["playState", "progress", "interaction"]; // Possible values are "playState", "progress" and/or "integration"
var milestone_percentages = ["10", "20", "30", "40", "90"]; // These must be rounded to the nearest 10
var player_element_id = "video";
var player_type = "iframe"; // Possible values are "iframe" or "html"
var fireEvent = false;
var played = false;
var m1 = false;
var m2 = false;
var m3 = false;
var m4 = false;
window._tealium_VZ = {
name: "Vzaar",
init_tries: 0,
eventsAdded: false,
events: video_events,
milestone_percentages: milestone_percentages,
mediaEventHandler: function (pEvent) {
pos = _tealium_VZ.player_object.getTime();
dur = _tealium_VZ.player_object.getTotalTime();
if (pEvent == "mediaStarted" || pEvent == "started") {
played = true;
var data = {event_type: "video", event_name: "play"};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else if (pEvent == "resume") {
_tealium_VZ.pause = false;
var data = {event_type: "video", event_name: "resume", video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else if (pEvent == "pause") {
_tealium_VZ.pause = true;
var data = {event_type: "video", event_name: "pause", video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else if (pEvent == "mediaEnded") {
played = false;
//_tealium_VZ.resetMilestones();
var data = {event_type: "video", event_name: "complete", video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
} else {
var ms = pEvent.replace(/[^0-9]/g, "")
for (var i = 0; i < _tealium_VZ.milestone_percentages.length; i++) {
if (ms == _tealium_VZ.milestone_percentages[i]) {
var ms_num = (i + 1);
var data = {event_type: "video", event_name: "milestone", video_milestone: "M:" + ms_num + ":" + _tealium_VZ.milestone_percentages[i], video_position: pos, video_duration: dur};
if (fireEvent === true) { utag.link(data) };
console.log(JSON.stringify(data));
}
}
}
},
addEvents: function (a) {
console.log("***** Adding Events ******");
if (a == "iframe") {
for (var i = 0; i < video_events.length; i++) {
_tealium_VZ.player_object.addEventListener(_tealium_VZ.events[i], _tealium_VZ.mediaEventHandler);
}
} else {
for (var i = 0; i < video_events.length; i++) {
_tealium_VZ.player_object.addEventListener(_tealium_VZ.events[i], "_tealium_VZ.mediaEventHandler");
}
}
},
init: function () {
if (typeof vzPlayer != "undefined") {
if (player_type == "iframe") {
vz_player = new vzPlayer(player_element_id)
vz_player.ready(function (e) {
console.log("TEALIUM: Connecting Tealium with Oyala Player - SUCCESS");
_tealium_VZ.player_object = vz_player;
_tealium_VZ.addEvents(player_type)
console.log("****** Events Added ******");
_tealium_VZ.eventsAdded = true;
})
} else {
window.vzaarPlayerReady = function () {
console.log("*********** Video Ready **************");
console.log("TEALIUM: Connecting Tealium with Oyala Player - SUCCESS");
vzPlayer = document.getElementById(player_element_id);
_tealium_VZ.player_object = vzPlayer;
_tealium_VZ.addEvents(player_type)
console.log("****** Events Added ******");
_tealium_VZ.eventsAdded = true;
_tealium_VZ.readyFunction = true;
}
}
} else if (!_tealium_VZ.eventsAdded) {
// If Vzaar object is not defined we will increment the number of tries by 1
_tealium_VZ.init_tries += 1;
//Stop trying to connect to the Video Player if tried 100 times
if (_tealium_VZ.init_tries > 100) {
console.log("TEALIUM: Cannot connect to Vzaar Video");
return;
}
// Calls init function repeatedly either 100 times or Vzaar Object is defined
setTimeout(function () {
_tealium_VZ.init()
}, 100);
}
}
}
window.addEventListener('load', function(){
var ifrm = document.getElementsByTagName('iframe')[0];
if (ifrm.src.indexOf("apiOn=true") === -1)
if (ifrm.src.indexOf("?") === -1)
ifrm.src += '?apiOn=true';
else
ifrm.src += '&apiOn=true';
player_element_id = ifrm.id;
if (typeof _tealium_VZ.videoPlayer == "undefined") {
_tealium_VZ.init();
}
}, false);
</script>
</head>
<body>
<iframe
id="video"
name="video"
title="vzaar video player"
class="vzaar-video-player"
type="text/html"
width="640"
height="480"
frameborder="0"
allowfullscreen=""
allowtransparency="true"
mozallowfullscreen=""
webkitallowfullscreen=""
src="//view.vzaar.com/9036822/player?apiOn=true">
</iframe>
</body>
</html>
Result from that example page:

Google Maps - Fixed source and draggable destination in website

I`m using the API to integrate Google Maps in our website. But we did not met the requirement by using them.
I tried using different options. Our requirement is that - the source is set to fixed location(should not be dragged) and the accurate destination is to be entered in the text area and the end user should have an option to point out the exact location(may be near to the location entered in the destination text area).
calculation of distance and the remaining part is working fine for me. Pointing the exact location in the destination also achieved.
Only thing to be worked on is that fixing the source location(End user should not drag/move the source location).
<script type="text/javascript">
var source, destination;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
google.maps.event.addDomListener(window, 'load', function () {
new google.maps.places.SearchBox(document.getElementById('txtSource'));
new google.maps.places.SearchBox(document.getElementById('txtDestination'));
directionsDisplay = new google.maps.DirectionsRenderer({ 'draggable': true });
});
function GetRoute() {
var mapOptions = {
zoom: 4,
};
map = new google.maps.Map(document.getElementById('dvMap'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('dvPanel'));
//*********DIRECTIONS AND ROUTE**********************//
source = document.getElementById("txtSource").value;
destination = document.getElementById("txtDestination").value;
var request = {
origin: source,
destination: destination,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
//*********DISTANCE AND DURATION**********************//
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
var distance = response.rows[0].elements[0].distance.text;
var duration = response.rows[0].elements[0].duration.text;
var dvDistance = document.getElementById("dvDistance");
dvDistance.innerHTML = "";
dvDistance.innerHTML += "Distance: " + distance + "<br />";
dvDistance.innerHTML += "Duration:" + duration;
} else {
alert("Unable to find the distance via road.");
}
});
}
</script>
By using above code, Both the source and destination are draggable.
Google maps marker are not moveable by default, I think, when you set their coordinates on map they stay on the same location.
If still moving you can remove the event listener on the marker
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function () {
new google.maps.places.SearchBox(document.getElementById('txtSource'));
new google.maps.places.SearchBox(document.getElementById('txtDestination'));
});
var gmarkers = [];
var map = null;
var startLocation = null;
var endLocation = null;
var directionsService = null;
var polyline = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
//google.maps.event.addListener(map, 'click', function () {
// infowindow.close();
//});
directionsService = new google.maps.DirectionsService();
var request = {
origin: document.getElementById("txtSource").value,
destination: document.getElementById("txtDestination").value,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, RenderCustomDirections);
}
function RenderCustomDirections(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var bounds = new google.maps.LatLngBounds();
var route = response.routes[0];
var summaryPanel = document.getElementById("directions_panel");
startLocation = new Object();
endLocation = new Object();
summaryPanel.innerHTML = "";
// For each route, display summary information.
for (var i = 0; i < route.legs.length; i++) {
var routeSegment = i + 1;
summaryPanel.innerHTML += route.legs[i].start_address + "<br />" + " to " + "<br />";
summaryPanel.innerHTML += route.legs[i].end_address + "<br />";
summaryPanel.innerHTML += route.legs[i].distance.text + "<br /><br />";
}
var path = response.routes[0].overview_path;
var legs = response.routes[0].legs;
for (i = 0; i < legs.length; i++) {
if (i == 0) {
startLocation.latlng = legs[i].start_location;
startLocation.address = legs[i].start_address;
startLocation.marker = createMarker(legs[i].start_location, "start", legs[i].start_address, "green", false);
}
endLocation.latlng = legs[i].end_location;
endLocation.address = legs[i].end_address;
var steps = legs[i].steps;
for (j = 0; j < steps.length; j++) {
var nextSegment = steps[j].path;
var dist_dur = "";
if (steps[j].distance && steps[j].distance.text) dist_dur += " " + steps[j].distance.text;
if (steps[j].duration && steps[j].duration.text) dist_dur += " " + steps[j].duration.text;
for (k = 0; k < nextSegment.length; k++) {
polyline.getPath().push(nextSegment[k]);
bounds.extend(nextSegment[k]);
}
}
}
polyline.setMap(map);
map.fitBounds(bounds);
endLocation.marker = createMarker(endLocation.latlng, "end", endLocation.address, "red", true);
}
else alert("Please try again " + status);
}
function createMarker(latlng, label, html, color, draggable) {
//alert("createMarker(" + latlng + "," + label + "," + html + "," + color + ")");
var contentString = '<b>' + label + '</b><br>' + html;
var marker = new google.maps.Marker({
position: latlng,
draggable: draggable,
map: map,
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
google.maps.event.addListener(marker, 'dragend', function () {
var request = {
origin: startLocation.marker.getPosition(),
destination: endLocation.marker.getPosition(),
travelMode: google.maps.DirectionsTravelMode.WALKING
};
startLocation.marker.setMap(null);
endLocation.marker.setMap(null);
gmarkers = [];
polyline.setMap(null);
polyline = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
directionsService.route(request, RenderCustomDirections);
});
return marker;
}
</script>

how do i display base 64 encoded string as image in ionic app in offline

my code in here
here $scope.student_photo is my variable to get encoded string
first i get it in ajax and stored in local db
$http.post(mData.url+'getStudentDetails/',{student_id : student_id} ).success(function(data){
//$scope.student_pic = data.student_details[0].student_pic;
//$scope.student_photo = data.student_details[0].student_photo;
$scope.myImage=data.student_details[0].student_photo;
//alert($scope.myImage);
// var image_stu = data.student_details[0].student_photo;
// localStorage.setItem("imageData", image_stu);
// document.getElementById("img_stu").src='data:image/png;base64,' + image_stu;
//alert("DONE");
var events = data.student_details
var l = events.length;
//alert(l);
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM dashboard ', [], function(tx, results){
if (results.rows.length == 0)
{
tx.executeSql("INSERT INTO dashboard(dashboard_id, stu_name,clas,sec,student_image) VALUES(?,?,?,?,?)", [ student_id,data.student_details[0].student_name, data.student_details[0].class_name, data.student_details[0].section_name,data.student_details[0].student_photo], function(tx, res) {
$scope.dashboardDetails();
//alert('INSERTED');
}, function(e) {
//alert('ERROR: ' + e.message);
});
}
});
});
});
$scope.showScreen = function(screen) {
$state.go('app.'+screen);
}
$scope.printDashboard = function()
{
//alert('ss');
db.transaction(function (tx) {
// tx.executeSql('SELECT * FROM dashboard', [], function (tx, dtresult) {
//alert("dtresult.rows.length" + dtresult.rows.length);
// console.log("dtresult.rows.length" + dtresult.rows.length);
// $scope.totalrecords = dtresult.rows.length;
// });
tx.executeSql('SELECT * FROM dashboard', [], function (tx, dresult) {
console.log("dresult.rows.length" + dresult.rows.length);
dataset = dresult.rows;
console.log(dresult.rows);
for (var i = 0, item = null; i < dresult.rows.length; i++) {
item = dataset.item(i);
$scope.dashboarditems.push({stu_name: item['stu_name'],stu_class: item['clas'],stu_sec: item['Sec'],stu_img: item['student_image']});
//$scope.items.push({id: item['notice_title'], notice:item['notice'], event_date: item['event_date']});
console.log($scope.dashboarditems[0]);
}
$state.go('app.dashboard');
});
});
}
$scope.dashboardDetails = function()
{
var citems = [];
syncWithServer(function(syncSuccess){
$scope.printDashboard();
}, false);
}
Question:
How to display my base64 string to image formate.
If your base64 string is present inside the $scope.student_photo
try the following img tag to display the image in view
<img ng-src="{{'data:image/png;base64,'+student_photo}}">

unable to open hyperlink in a new tab which is created from bootstrap-wysiwyg editor

i am using bootstrap-wysiwyg rich text editor in my application and i am not able to open the hyerlink created in a new window.
i am using the bootstrap-wysiwyg.js file which is below. i am not able to figure out how to make the hyperlink created, to open in a new tab.
(function ($) {
'use strict';
/** underscoreThrottle()
* From underscore http://underscorejs.org/docs/underscore.html
*/
var underscoreThrottle = function(func, wait) {
var context, args, timeout, result;
var previous = 0;
var later = function() {
previous = new Date;
timeout = null;
result = func.apply(context, args);
};
return function() {
var now = new Date;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
return result;
};
}
var readFileIntoDataUrl = function (fileInfo) {
var loader = $.Deferred(),
fReader = new FileReader();
fReader.onload = function (e) {
loader.resolve(e.target.result);
};
fReader.onerror = loader.reject;
fReader.onprogress = loader.notify;
fReader.readAsDataURL(fileInfo);
return loader.promise();
};
$.fn.cleanHtml = function (o) {
if ( $(this).data("wysiwyg-html-mode") === true ) {
$(this).html($(this).text());
$(this).attr('contenteditable',true);
$(this).data('wysiwyg-html-mode',false);
}
// Strip the images with src="data:image/.." out;
if ( o === true && $(this).parent().is("form") ) {
var gGal = $(this).html;
if ( $(gGal).has( "img" ).length ) {
var gImages = $( "img", $(gGal));
var gResults = [];
var gEditor = $(this).parent();
$.each(gImages, function(i,v) {
if ( $(v).attr('src').match(/^data:image\/.*$/) ) {
gResults.push(gImages[i]);
$(gEditor).prepend("<input value='"+$(v).attr('src')+"' type='hidden' name='postedimage/"+i+"' />");
$(v).attr('src', 'postedimage/'+i);
}});
}
}
var html = $(this).html();
return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, '');
};
$.fn.wysiwyg = function (userOptions) {
var editor = this,
wrapper = $(editor).parent(),
selectedRange,
options,
toolbarBtnSelector,
updateToolbar = function () {
if (options.activeToolbarClass) {
$(options.toolbarSelector,wrapper).find(toolbarBtnSelector).each(underscoreThrottle(function () {
var commandArr = $(this).data(options.commandRole).split(' '),
command = commandArr[0];
// If the command has an argument and its value matches this button. == used for string/number comparison
if (commandArr.length > 1 && document.queryCommandEnabled(command) && document.queryCommandValue(command) == commandArr[1]) {
$(this).addClass(options.activeToolbarClass);
// Else if the command has no arguments and it is active
} else if (commandArr.length === 1 && document.queryCommandEnabled(command) && document.queryCommandState(command)) {
$(this).addClass(options.activeToolbarClass);
// Else the command is not active
} else {
$(this).removeClass(options.activeToolbarClass);
}
}, options.keypressTimeout));
}
},
execCommand = function (commandWithArgs, valueArg) {
var commandArr = commandWithArgs.split(' '),
command = commandArr.shift(),
args = commandArr.join(' ') + (valueArg || '');
var parts = commandWithArgs.split('-');
if ( parts.length == 1 ) {
document.execCommand(command, 0, args);
}
else if ( parts[0] == 'format' && parts.length == 2) {
document.execCommand('formatBlock', false, parts[1] );
}
editor.trigger('change');
updateToolbar();
},
bindHotkeys = function (hotKeys) {
$.each(hotKeys, function (hotkey, command) {
editor.keydown(hotkey, function (e) {
if (editor.attr('contenteditable') && editor.is(':visible')) {
e.preventDefault();
e.stopPropagation();
execCommand(command);
}
}).keyup(hotkey, function (e) {
if (editor.attr('contenteditable') && editor.is(':visible')) {
e.preventDefault();
e.stopPropagation();
}
});
});
editor.keyup(function(){ editor.trigger('change'); });
},
getCurrentRange = function () {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
}
} else if (document.selection) {
range = document.selection.createRange();
} return range;
},
saveSelection = function () {
selectedRange = getCurrentRange();
},
restoreSelection = function () {
var selection;
if (window.getSelection || document.createRange) {
selection = window.getSelection();
if (selectedRange) {
try {
selection.removeAllRanges();
} catch (ex) {
document.body.createTextRange().select();
document.selection.empty();
}
selection.addRange(selectedRange);
}
}
else if (document.selection && selectedRange) {
selectedRange.select()
}
},
// Adding Toggle HTML based on the work by #jd0000, but cleaned up a little to work in this context.
toggleHtmlEdit = function(a) {
if ( $(editor).data("wysiwyg-html-mode") !== true ) {
var oContent = $(editor).html();
var editorPre = $( "<pre />" )
$(editorPre).append( document.createTextNode( oContent ) );
$(editorPre).attr('contenteditable',true);
$(editor).html(' ');
$(editor).append($(editorPre));
$(editor).attr('contenteditable', false);
$(editor).data("wysiwyg-html-mode", true);
$(editorPre).focus();
}
else {
$(editor).html($(editor).text());
$(editor).attr('contenteditable',true);
$(editor).data('wysiwyg-html-mode',false);
$(editor).focus();
}
},
insertFiles = function (files) {
editor.focus();
$.each(files, function (idx, fileInfo) {
if (/^image\//.test(fileInfo.type)) {
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
execCommand('insertimage', dataUrl);
editor.trigger('image-inserted');
}).fail(function (e) {
options.fileUploadError("file-reader", e);
});
} else {
options.fileUploadError("unsupported-file-type", fileInfo.type);
}
});
},
markSelection = function (input, color) {
restoreSelection();
if (document.queryCommandSupported('hiliteColor')) {
document.execCommand('hiliteColor', 0, color || 'transparent');
}
saveSelection();
input.data(options.selectionMarker, color);
},
bindToolbar = function (toolbar, options) {
toolbar.find(toolbarBtnSelector, wrapper).click(function () {
restoreSelection();
editor.focus();
if ($(this).data(options.commandRole) === 'html') {
toggleHtmlEdit();
}
else {
execCommand($(this).data(options.commandRole));
}
saveSelection();
});
toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
this.value = '';
restoreSelection();
if (newValue) {
editor.focus();
execCommand($(this).data(options.commandRole), newValue);
}
saveSelection();
}).on('focus', function () {
var input = $(this);
if (!input.data(options.selectionMarker)) {
markSelection(input, options.selectionColor);
input.focus();
}
}).on('blur', function () {
var input = $(this);
if (input.data(options.selectionMarker)) {
markSelection(input, false);
}
});
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
restoreSelection();
if (this.type === 'file' && this.files && this.files.length > 0) {
insertFiles(this.files);
}
saveSelection();
this.value = '';
});
},
initFileDrops = function () {
editor.on('dragenter dragover', false)
.on('drop', function (e) {
var dataTransfer = e.originalEvent.dataTransfer;
e.stopPropagation();
e.preventDefault();
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
insertFiles(dataTransfer.files);
}
});
};
options = $.extend(true, {}, $.fn.wysiwyg.defaults, $.fn.wysiwyg.defaults1, userOptions);
toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']';
bindHotkeys(options.hotKeys);
// Support placeholder attribute on the DIV
if ($(this).attr('placeholder') != '') {
$(this).addClass('placeholderText');
$(this).html($(this).attr('placeholder'));
$(this).bind('focus',function(e) {
if ( $(this).attr('placeholder') != '' && $(this).text() == $(this).attr('placeholder') ) {
$(this).removeClass('placeholderText');
$(this).html('');
}
});
$(this).bind('blur',function(e) {
if ( $(this).attr('placeholder') != '' && $(this).text() == '' ) {
$(this).addClass('placeholderText');
$(this).html($(this).attr('placeholder'));
}
})
}
if (options.dragAndDropImages) {
initFileDrops();
}
bindToolbar($(options.toolbarSelector), options);
editor.attr('contenteditable', true)
.on('mouseup keyup mouseout', function () {
saveSelection();
updateToolbar();
});
$(window).bind('touchend', function (e) {
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
currentRange = getCurrentRange(),
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
if (!clear || isInside) {
saveSelection();
updateToolbar();
}
});
return this;
};
$.fn.wysiwyg.defaults = {
hotKeys: {
'Ctrl+b meta+b': 'bold',
'Ctrl+i meta+i': 'italic',
'Ctrl+u meta+u': 'underline',
'Ctrl+z': 'undo',
'Ctrl+y meta+y meta+shift+z': 'redo',
'Ctrl+l meta+l': 'justifyleft',
'Ctrl+r meta+r': 'justifyright',
'Ctrl+e meta+e': 'justifycenter',
'Ctrl+j meta+j': 'justifyfull',
'Shift+tab': 'outdent',
'tab': 'indent'
},
toolbarSelector: '[data-role=editor-toolbar]',
commandRole: 'edit',
activeToolbarClass: 'btn-info',
selectionMarker: 'edit-focus-marker',
selectionColor: 'darkgrey',
dragAndDropImages: true,
keypressTimeout: 200,
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
};
$.fn.wysiwyg.defaults1 = {
hotKeys: {
'Ctrl+b meta+b': 'bold',
'Ctrl+i meta+i': 'italic',
'Ctrl+u meta+u': 'underline',
'Ctrl+z': 'undo',
'Ctrl+y meta+y meta+shift+z': 'redo',
'Ctrl+l meta+l': 'justifyleft',
'Ctrl+r meta+r': 'justifyright',
'Ctrl+e meta+e': 'justifycenter',
'Ctrl+j meta+j': 'justifyfull',
'Shift+tab': 'outdent',
'tab': 'indent'
},
toolbarSelector: '[data-role=editor1-toolbar]',
commandRole: 'edit',
activeToolbarClass: 'btn-info',
selectionMarker: 'edit-focus-marker',
selectionColor: 'darkgrey',
dragAndDropImages: true,
keypressTimeout: 200,
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
};
}(window.jQuery));
#
i am saving the editor contents and then i am retrieving it in a different page as below.
<p class="textAlignLeft" ng-bind-html="editorContent | unsafe"></p>
"editorContent" will have the contents entered in the richtext editor, and the hyper link in it has to open in a new window.
in the browser console i am getting the following output.
<p class="textAlignLeft ng-binding" ng-bind-html="editorContent | unsafe">ajslkjsak sdsad</p>
One way of doing that would be to bind to click event of anchor tag and open URL in new tab using JavaScript.
Say, the ID of your editor is "editor", the following code would work with it
$("a", "#editor").click(function(e) {
window.open($(this).attr('href'), '_blank')
});
this will bind click event on all the a tags inside editor div and when the user clicks any of it, the url will be opened in new window.
Update:
using jQuery, it is very easy. First assign an id to your <p> tag like
<p id="myCustomContent" class="textAlignLeft" ng-bind-html="newsContent | unsafe"></p>
Where myCustomContent is the id
now use the following code
$("a", "#myCustomContent").each(function() {
$(this).attr('target', '_blank');
});
this will loop once on all the anchor tags and make them open in new tab when user clicks on them.

TypeError: 'undefined' is not an object (evaluating 'authDetails.access_token') while i

I am getting the following error in my controller:
angular.module('bcpBackOffice').controller('assetsCtrl', ['$scope', '$state', '$log', '$filter', '$compile', 'ApplicationConfig', '$mdDialog', 'RoomManagerFactory',
The error is showing for the variable authDetails.access_token in my controller.
Here is my controller
'use strict';
/**
* #ngdoc function
* #name bcpBackOffice.controller:assetsCtrl
* #description
* # assetsCtrl
* Controller of the bcpBackOffice
*/
angular.module('bcpBackOffice').controller('assetsCtrl', ['$scope', '$state', '$log', '$filter', '$compile', 'ApplicationConfig', '$mdDialog', 'RoomManagerFactory',
'RoomService', 'DataService', 'RoomServicesVO', 'RoomPricingVO','BcpBase64ImageDataEncodedMultipartFileVO','ImagePath','RoomVO','ImageFileExtensionPattern', assetsCtrl]);
function assetsCtrl($scope, $state, $log, $filter, $compile, ApplicationConfig, $mdDialog, RoomManagerFactory, RoomService, DataService,
RoomServicesVO, RoomPricingVO, BcpBase64ImageDataEncodedMultipartFileVO, ImagePath, RoomVO, ImageFileExtensionPattern) {
// Variable definition
var authDetails = ApplicationConfig.loggedInUserData.authDetails;
var accessToken = authDetails.access_token;
$scope.selectedTabIndex = 0;
$scope.masterData = "";
$scope.roomAttributes = [];
$scope.roomServiceRateUnits = [];
$scope.roomServices = [];
$scope.dayHours = null;
$scope.propertyId = ApplicationConfig.loggedInUserData.propertyId;
$scope.rooms = [];
$scope.populateMasterAttributeData = [];
$scope.attributeValue = [];
$scope.assetServices = new RoomServicesVO();
$scope.editAssetServicesFlag = false;
$scope.editAssetServicesIndex = '';
$scope.imageRoomPicturesPath = ImagePath.RoomImagePicturePath;
$scope.imageFloorPlanPath = ImagePath.RoomImageFloorPlanPath;
$scope.validateUploadedFile = validateUploadedFile;
$scope.assetsFromDateContainer = {};
$scope.weekdaySlot = [];
var weekdayPricingVO = new RoomPricingVO();
weekdayPricingVO.slotType = 'WEEKDAY';
$scope.weekdaySlot.push(weekdayPricingVO);
$scope.weekendSlot = [];
var weekendPricingVO = new RoomPricingVO();
weekendPricingVO.slotType = 'WEEKEND';
$scope.weekendSlot.push(weekendPricingVO);
// Function definition
$scope.increaseCounter = increaseCounter;
$scope.decreaseCounter = decreaseCounter;
$scope.loadDataForAssets = loadDataForAssets;
$scope.addWeekdaySlot = addWeekdaySlot;
$scope.addWeekendSlot = addWeekendSlot;
$scope.deleteWeekdaySlot = deleteWeekdaySlot;
$scope.deleteWeekendSlot = deleteWeekendSlot;
$scope.addInclusiveServices = addInclusiveServices;
$scope.closePopup = closePopup;
$scope.saveInclusiveServices = saveInclusiveServices;
$scope.getAssetsMasterData = getAssetsMasterData;
$scope.switchToAssetsServiceTab = switchToAssetsServiceTab;
$scope.saveRoomData = saveRoomData;
$scope.getDayHours = getDayHours;
$scope.addAdditionalServicesToRoom = addAdditionalServicesToRoom;
$scope.populateAttributeData = populateAttributeData;
$scope.getAllAssetsOfProperty = getAllAssetsOfProperty;
$scope.setWorkingHoursToTime = setWorkingHoursToTime;
$scope.disabledToDate = disabledToDate;
$scope.validatePricingSlot = validatePricingSlot;
$scope.editAssetService = editAssetService;
$scope.deleteAssetService = deleteAssetService;
$scope.reloadAssetServiceVO = reloadAssetServiceVO;
$scope.uploadFloorPlan = uploadFloorPlan;
$scope.uploadRoomImage = uploadRoomImage;
$scope.imagesDataParser = imagesDataParser;
/**
* RoomVO Object Contains Data.
*/
$scope.roomVO = RoomManagerFactory.retrieveInstance();
$scope.roomServicesVO = new RoomServicesVO();
$scope.roomPricingVO = new RoomPricingVO();
/**
* Save Room Data.(create new Asset.)
*/
function saveRoomData() {
$scope.roomVO.availableFromDate = $filter('date')(new Date($scope.assetsFromDateContainer.availableFromDate), "yyyy-MM-dd HH:mm:ss");
$log.debug($scope.roomVO);
if (typeof $scope.roomVO.roomType == "string" || $scope.roomVO.roomType instanceof String) {
$scope.roomVO.roomType = JSON.parse($scope.roomVO.roomType);
}
addWeekdayAndWeekendSlotToAsset();
RoomService.createRoomOfProperty($scope.roomVO, $scope.propertyId, accessToken).then(function (response) {
$scope.rooms.push(response.data);
$scope.roomVO = new RoomVO();
$state.go('template.' + ApplicationConfig.urlBasedOnUserRole + '.assets.show-assets');
},function(error){
$log.error(error);
});
}
/**
* Add Additional Services to Room.
*/
function addAdditionalServicesToRoom() {
$scope.roomServicesVO = $scope.assetServices;
if($scope.editAssetServicesFlag == true){
$scope.roomVO.editRoomServices($scope.editAssetServicesIndex,$scope.roomServicesVO);
}
else {
$scope.roomVO.addRoomServices($scope.roomServicesVO);
}
$scope.editAssetServicesFlag = false;
$scope.assetServices = new RoomServicesVO();
return true;
}
function getDayHours() {
DataService.getDayHoursFromJson().then(function (response) {
$scope.dayHours = response.data;
});
}
function setWorkingHoursToTime(fromTime) {
angular.forEach($scope.dayHours, function (dayHour, index) {
if (fromTime == dayHour.value) {
$scope.totimeIndex = index;
}
});
}
function reloadAssetServiceVO(){
$scope.editAssetServicesFlag = false;
$scope.assetServices = new RoomServicesVO();
}
function editAssetService(index){
$scope.editAssetServicesFlag = true;
$scope.editAssetServicesIndex = index;
$scope.roomServicesVO = $scope.roomVO.roomServices[index];
angular.copy($scope.roomServicesVO, $scope.assetServices);
}
function deleteAssetService(index){
$scope.roomVO.roomServices.splice(index,1);
}
function disabledToDate(fromTime, index, dayType) {
var selectOptions;
if (dayType == 'weekday') {
selectOptions = document.getElementsByClassName('toTimeSelectWeekday_' + index)[0].options;
}
if (dayType == 'weekend') {
selectOptions = document.getElementsByClassName('toTimeSelectWeekend_' + index)[0].options;
}
if (selectOptions.length > 0) {
angular.forEach(selectOptions, function (selectOption) {
selectOption.removeAttribute('disabled');
var value = $filter('date')(selectOption.value, 'HH:mm:ss');
var fromTimeFilter = $filter('date')(fromTime, 'HH:mm:ss');
console.log(value-fromTimeFilter);
if (value <= fromTimeFilter) {
selectOption.setAttribute('disabled', true);
}
});
}
}
/**
* get master data while adding new assets
*/
function getAssetsMasterData() {
switchToAssetsServiceTab(0);
var masterDataPromise = RoomService.getMasterDataOfRoom(accessToken);
masterDataPromise.then(function (promise) {
$scope.masterData = promise.data;
//$scope.roomAttributes = $scope.masterData.roomAttributes;
angular.copy($scope.masterData.roomAttributes, $scope.roomAttributes);
angular.copy($scope.masterData.roomServiceRateUnits, $scope.roomServiceRateUnits);
angular.copy($scope.masterData.roomServices, $scope.roomServices);
$scope.attributeValue = [];
populateAttributeData();
$log.debug($scope.masterData.roomAttributes);
$state.go('template.' + ApplicationConfig.urlBasedOnUserRole + '.assets.add-asset');
});
}
function getAllAssetsOfProperty() {
RoomService.getAllRoomsOfProperty(accessToken, $scope.propertyId).then(function (response) {
$scope.rooms = response.data;
});
}
function populateAttributeData() {
$scope.populateMasterAttributeData = [];
angular.forEach($scope.roomAttributes, function (attributeObject) {
if (typeof attributeObject.value == "string" || attributeObject.value instanceof String) {
var parsedAttributeValue = JSON.parse(attributeObject.value);
} else {
var parsedAttributeValue = attributeObject.value;
}
angular.forEach(parsedAttributeValue, function (attribute) {
var tempAttributeObject = {};
tempAttributeObject.id = attributeObject.id;
tempAttributeObject.label = attribute;
tempAttributeObject.checked = false;
$scope.populateMasterAttributeData.push(tempAttributeObject);
});
}, $scope.populateMasterAttributeData);
}
/**
* load the data after loading the page for Assets Page
*/
function loadDataForAssets() {
$scope.assetsFromDateContainer.availableFromDate = $filter('date')(new Date(), "yyyy-MM-dd HH:mm:ss");
$scope.roomVO.guestCapacity = 1;
$scope.roomVO.minimumBookingHours = 1;
}
/**
* Increase counter value on click on item/element
* #param value
*/
function increaseCounter(value) {
var countEle = document.getElementById(value);
countEle.value = +countEle.value + 1;
if (value == "countFld") {
$scope.roomVO.guestCapacity = countEle.value;
} else {
if (value == "countFld2") {
$scope.roomVO.minimumBookingHours = countEle.value;
}
}
}
/**
* Decrease counter value on click on item/element
* #param value
*/
function decreaseCounter(value) {
var countEle = document.getElementById(value);
if (countEle.value > 1) {
countEle.value = countEle.value - 1;
if (value == "countFld") {
$scope.roomVO.guestCapacity = countEle.value;
} else {
if (value == "countFld2") {
$scope.roomVO.minimumBookingHours = countEle.value;
}
}
}
else {
}
}
/**
* add time slot for weekday
*/
function addWeekdaySlot() {
var roomPricingVO = new RoomPricingVO();
roomPricingVO.slotType = 'WEEKDAY';
$scope.weekdaySlot.push(roomPricingVO);
var currentIndex = ($scope.weekdaySlot.length - 1);
var weekdaytbl = document.getElementById("weekdaySlotsTbl");
var lasti = weekdaytbl.rows.length;
var row = weekdaytbl.insertRow(lasti);
var cell1 = row.insertCell(0);
cell1.setAttribute("style", "width:80px;");
var cell2 = row.insertCell(1);
cell2.setAttribute("style", "width:80px;");
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
$log.debug($scope.weekdaySlot.length - 1);
var formTimeModel = "weekdaySlot[" + currentIndex + "].fromTime";
var toTimeModel = "weekdaySlot[" + currentIndex + "].toTime";
var rateModel = "weekdaySlot[" + currentIndex + "].rate";
cell1.innerHTML = document.getElementById("weekdays_fromTime").innerHTML;
cell1.getElementsByTagName("select")[0].setAttribute("ng-model", formTimeModel);
var disabledToDateFunction = 'disabledToDate(weekdaySlot[' + currentIndex + '].fromTime,' + currentIndex + ',\'weekday\')';
cell1.getElementsByTagName("select")[0].setAttribute("ng-change", disabledToDateFunction);
cell2.innerHTML = document.getElementById("weekdays_toTime").innerHTML;
cell2.getElementsByTagName("select")[0].setAttribute("ng-model", toTimeModel);
cell2.getElementsByTagName("select")[0].setAttribute("class", cell2.getElementsByTagName("select")[0].getAttribute("class") + ' toTimeSelectWeekday_' + currentIndex);
cell3.innerHTML = document.getElementById("weekdays_price").innerHTML;
cell3.getElementsByTagName("input")[0].setAttribute("ng-model", rateModel);
var deleteFunction = 'deleteWeekdaySlot($event,' + currentIndex + ')';
cell4.innerHTML = "<img src='assets/images/icons/close_icon.png'>";
disabledToDate($scope.weekdaySlot[currentIndex].fromTime, currentIndex,'weekday');
$compile($(row).contents())($scope);
}
/**
* add time slot for weekend
*/
function addWeekendSlot() {
var roomPricingVO = new RoomPricingVO();
roomPricingVO.slotType = 'WEEKEND';
$scope.weekendSlot.push(roomPricingVO);
var currentIndex = ($scope.weekendSlot.length - 1);
var weekdaytbl = document.getElementById("weekendSlotsTbl");
var lasti = weekdaytbl.rows.length;
var row = weekdaytbl.insertRow(lasti);
var cell1 = row.insertCell(0);
cell1.setAttribute("style", "width:80px;");
var cell2 = row.insertCell(1);
cell2.setAttribute("style", "width:80px;");
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
var formTimeModel = "weekendSlot[" + currentIndex + "].fromTime";
var toTimeModel = "weekendSlot[" + currentIndex + "].toTime";
var rateModel = "weekendSlot[" + currentIndex + "].rate";
cell1.innerHTML = document.getElementById("weekdays_fromTime").innerHTML;
cell1.getElementsByTagName("select")[0].setAttribute("ng-model", formTimeModel);
var disabledToDateFunction = 'disabledToDate(weekendSlot[' + currentIndex + '].fromTime,' + currentIndex + ',\'weekend\')';
cell1.getElementsByTagName("select")[0].setAttribute("ng-change", disabledToDateFunction);
cell2.innerHTML = document.getElementById("weekdays_toTime").innerHTML;
cell2.getElementsByTagName("select")[0].setAttribute("ng-model", toTimeModel);
cell2.getElementsByTagName("select")[0].setAttribute("class", cell2.getElementsByTagName("select")[0].getAttribute("class") + ' toTimeSelectWeekend_' + currentIndex);
cell3.innerHTML = document.getElementById("weekdays_price").innerHTML;
cell3.getElementsByTagName("input")[0].setAttribute("ng-model", rateModel);
var deleteFunction = 'deleteWeekendSlot($event,' + currentIndex + ')';
cell4.innerHTML = "<img src='assets/images/icons/close_icon.png'>";
disabledToDate($scope.weekendSlot[currentIndex].fromTime, currentIndex, 'weekend');
$compile($(row).contents())($scope);
}
function addWeekdayAndWeekendSlotToAsset() {
var mergedWeekdayWeekendPricing = [];
mergedWeekdayWeekendPricing = $scope.weekdaySlot.concat($scope.weekendSlot);
$scope.roomVO.roomPricings = mergedWeekdayWeekendPricing;
}
/**
* delete weekday slots
* #param $event
*/
function deleteWeekdaySlot($event, currentIndex) {
var index = $event.currentTarget.parentNode.parentNode.rowIndex;
document.getElementById("weekdaySlotsTbl").deleteRow(index);
delete($scope.weekdaySlot[currentIndex]);
}
/**
* delete weekend slots
* #param $event
*/
function deleteWeekendSlot($event, currentIndex) {
var index = $event.currentTarget.parentNode.parentNode.rowIndex;
document.getElementById("weekendSlotsTbl").deleteRow(index);
delete($scope.weekendSlot[currentIndex]);
}
/**
* add Inclusive Services for Assets popup
*/
function addInclusiveServices() {
$mdDialog.show({
templateUrl: 'app/templates/views/' + ApplicationConfig.urlBasedOnUserRole + '/fragments/add-inclusive-assets-services.html',
scope: $scope,
preserveScope: true,
overlay: true,
clickOutsideToClose: false,
parent:angular.element('#addInclusiveServices')
});
}
/**
* Save added inclusive services for Assets
*/
function saveInclusiveServices() {
addAttributeToAsset();
$mdDialog.hide();
}
function addAttributeToAsset() {
$scope.attributeValue = [];
$scope.roomVO.roomAttributes = $scope.masterData.roomAttributes;
$log.debug($scope.populateMasterAttributeData);
if (typeof $scope.roomVO.roomAttributes == "string" || $scope.roomVO.roomAttributes instanceof String) {
$scope.roomVO.roomAttributes = JSON.parse($scope.roomVO.roomAttributes);
}
if ($scope.roomVO.roomAttributes.length != 0) {
angular.forEach($scope.roomVO.roomAttributes, function (roomAttribute) {
var filteredSelectedAttr = $filter('filter')($scope.populateMasterAttributeData, function (populateMasterAttributeData) {
return ((roomAttribute.id == populateMasterAttributeData.id)&&(populateMasterAttributeData.checked == true));
});
var tempAttributeValueArray = [];
angular.forEach(filteredSelectedAttr, function (filteredAttributeLabel) {
tempAttributeValueArray.push(filteredAttributeLabel.label);
$scope.attributeValue.push(filteredAttributeLabel.label);
});
roomAttribute.value = tempAttributeValueArray;
});
}
$scope.roomVO.roomAttributes = JSON.stringify($scope.roomVO.roomAttributes);
}
/**
* close the popup window
*/
function closePopup() {
$mdDialog.hide();
}
/**
* after adding new asset switch to next tab
* to add assets service
* #param index
*/
function switchToAssetsServiceTab(index) {
$scope.selectedTabIndex = index;
}
function validatePricingSlot(){
createDummyTimeSlots();
//var sortByStartTime = $filter('orderBy')($scope.weekdaySlot, expression, comparator);
return false;
}
function createDummyTimeSlots(){
var listOfHours = $filter('getValueArrayOfKey')($scope.dayHours)('value');
var operableHours = $filter('filter')(listOfHours, function(hour){
return (hour >= $scope.roomVO.operableHoursStartTime && hour <= $scope.roomVO.operableHoursEndTime);
});
var sortedByFromTimeAndToTime = $filter('orderBy')($scope.weekdaySlot, ['fromTime', 'toTime']);
angular.forEach(sortedByFromTimeAndToTime, function(sortedObject){
angular.forEach(operableHours, function(hour, index){
if(hour >= sortedObject.fromTime && hour <= sortedObject.toTime){
operableHours.splice(index, 1);
}
});
});
console.log("+++++++++++++++++operableHours++++++++++++++++++++");
console.log(operableHours);
}
function uploadFloorPlan(files) {
if(validateUploadedFile()) {
var roomFloorPlanVO = new BcpBase64ImageDataEncodedMultipartFileVO().getRoomFloorPlanVO();
roomFloorPlanVO.originalFileName = files[0].name;
roomFloorPlanVO.size = files[0].size;
roomFloorPlanVO.contentType = files[0].type;
if (files && files[0]) {
setImageBase64ToBase64VO(roomFloorPlanVO, files[0]);
}
$scope.roomVO.floorPlanImageData = roomFloorPlanVO;
$log.debug($scope.roomVO);
}
}
function uploadRoomImage(files) {
if (validateUploadedFile()) {
console.log(files);
angular.forEach(files, function (file) {
var roomImageVO = new BcpBase64ImageDataEncodedMultipartFileVO().getRoomImageVO();
roomImageVO.originalFileName = file.name;
roomImageVO.size = file.size;
roomImageVO.contentType = file.type;
if (files && files[0]) {
setImageBase64ToBase64VO(roomImageVO, file);
}
$scope.roomVO.addRoomImageData(roomImageVO);
});
$log.debug($scope.roomVO);
}
}
function setImageBase64ToBase64VO(roomFloorPlanAndImageDataVO, file) {
var FR = new FileReader();
FR.onload = function (e) {
roomFloorPlanAndImageDataVO.base64EncodedImageData = e.target.result;
};
FR.readAsDataURL(file);
}
function imagesDataParser(roomImages, index){
if (typeof roomImages == "string" || roomImages instanceof String) {
$scope.rooms[index].images = JSON.parse(roomImages);
}
}
function validateUploadedFile() {
var allowedFiles = [".jpg", ".jpeg", ".gif", ".png"];
var fileUpload = document.getElementById("myfile");
var myPicture = document.getElementById("myPicture");
var lblError = document.getElementById("lblError");
var errorMyPicture = document.getElementById("errorMyPicture");
if (fileUpload.files.length > 0) {
if (!(ImageFileExtensionPattern).test(fileUpload.value.toLowerCase())) {
lblError.innerHTML = "Please upload files having extensions: <b>" + allowedFiles.join(', ') + "</b> only.";
return false;
}
}
if (myPicture.files.length > 0) {
var flag = false;
for(var readFile = 0; readFile < myPicture.files.length;readFile ++) {
if (!(ImageFileExtensionPattern).test(myPicture.files[readFile].name.toLowerCase())) {
errorMyPicture.innerHTML = "Please upload files having extensions: <b>" + allowedFiles.join(', ') + "</b> only.";
flag = true;
break;
}
}
if(flag){return false;}
if (myPicture.files.length > 5) {
errorMyPicture.innerHTML = "Oops!! You can upload max 5 files";
return false;
}
}
lblError.innerHTML = "";
errorMyPicture.innerHTML = "";
return true;
}
// called function on load
$scope.getDayHours();
$scope.getAllAssetsOfProperty();
}
**Here is my test case :**
'use strict';
describe('Controller: assetsCtrl', function () {
beforeEach(module('bcpBackOffice'));
beforeEach(module('BcpUIServices'));
beforeEach(module('ui.router'));
var assetsCtrl,
state,
log,
filter,
compile,
ApplicationConfig,
mdDialog,
RoomManagerFactory,
RoomService,
DataService,
RoomServicesVO,
RoomPricingVO,
$rootScope,
scope,
$httpBackend;
//Mock Data
var mockDayHours= [{
"label": "06:00 AM",
"value": "06:00:00"
},
{
"label": "07:00 AM",
"value": "07:00:00"
}];
beforeEach(inject(function(_$rootScope_, $controller, _$state_, _$log_, _$filter_, _$compile_, _ApplicationConfig_, _$mdDialog_, _RoomManagerFactory_, _RoomService_, _DataService_,
_RoomServicesVO_, _RoomPricingVO_, _$httpBackend_){
$rootScope = _$rootScope_;
scope = $rootScope.$new();
state = _$state_;
log = _$log_;
filter = _$filter_;
compile = _$compile_;
ApplicationConfig = _ApplicationConfig_;
mdDialog = _$mdDialog_;
RoomManagerFactory = _RoomManagerFactory_;
RoomService = _RoomService_;
DataService = _DataService_;
RoomServicesVO = _RoomServicesVO_;
RoomPricingVO = _RoomPricingVO_;
$httpBackend = _$httpBackend_;
assetsCtrl = $controller('assetsCtrl', {
$scope:scope,
$state:state,
$log:log,
$filter:filter,
$compile:compile,
ApplicationConfig:ApplicationConfig,
$mdDialog:mdDialog,
RoomManagerFactory:RoomManagerFactory,
RoomService:RoomService,
DataService:DataService,
RoomServicesVO:RoomServicesVO,
RoomPricingVO:RoomPricingVO
});
}));
beforeEach(function(){
ApplicationConfig.loggedInUserData.authDetails = {
access_token: "0e45e276-89ff-403f-8e02-7f85a41c2d26",
token_type: "bearer",
refresh_token: "ce872f46-5877-4266-9a0e-5199b63ac247",
expires_in: 10430,
scope: "read write"
};
$httpBackend.whenGET("app/mock_data/dayHours.json").respond(mockDayHours);
});
beforeEach(function(){
$rootScope.$digest();
});
it('should get day hours', function(){
scope.getDayHours();
$httpBackend.flush();
expect(scope.dayHours).toBe(mockDayHours);
});

Resources