Trying to create a service to build my NgTable - angularjs

I'm trying to create a service that return me the NgTableParams so I don't need to do it every time I need a table.
I was able to do it and it worked, but only if i have only one table using it in my controller, if I try to use it in a second table look's like the service mess the parameters of the fist and second table and stop working.
I tried to change the service to a factory and tried to make a angular.copy of the service so each copy create one different table yet noting worked.
Every time i need a table it is like this:
$scope.tableParams = NgTableDataService.getGenericTableParams($scope.onboardcomputerstatus, $scope.filterObject);
$scope.searchTable = { filter: '' };
$scope.tableParams = new NgTableParams({
count: $scope.session.user.tablePagination,
filter: $scope.searchTable.filter
}, {
counts: rowsPerPageTemplate,
getData: function (params) {
var funcFilter = function (item) {
var pfilter = params.filter().filter.toUpperCase();
return item.onboardComputer.id.toString().indexOf(pfilter) >= 0
|| (!!item.onboardComputer.remainingMonitoringMsgs ? item.onboardComputer.remainingMonitoringMsgs : "").toString().indexOf(pfilter) >= 0
|| $filter('date')((!!item.onboardComputer.oldestMonitoringTimestamp ? item.onboardComputer.oldestMonitoringTimestamp : ""), Session.get().company.dateHourFormatHTML).indexOf(pfilter) >= 0
|| $filter('date')((!!item.lastCommunicatio ? item.lastCommunicatio : ""), Session.get().company.dateHourFormatHTML).indexOf(pfilter) >= 0
|| $filter('date')((!!item.lastRegister ? item.lastRegister : ""), Session.get().company.dateHourFormatHTML).indexOf(pfilter) >= 0
|| item.vehicle.code.toUpperCase().indexOf(pfilter) >= 0
|| item.vehicle.name.toUpperCase().indexOf(pfilter) >= 0;
}
filteredData = params.filter() ? $filter('filter')($scope.onboardcomputerstatus, funcFilter) : $scope.onboardcomputerstatus;
if (!!filteredData && filteredData.length >= 0) {
params.total(filteredData.length);
var rowsPerPageTemplateWithAllData = rowsPerPageTemplate.slice();
var isFound = rowsPerPageTemplateWithAllData.some(function (element) {
return element === filteredData.length;
});
var filteredDataLength = filteredData.length + (isFound ? 1 : 0);
rowsPerPageTemplateWithAllData.push(filteredDataLength);
params.settings().counts = rowsPerPageTemplateWithAllData;
if (params.count() === MY_CONSTANTS.TABLE_PAGINATION_ALL) {
params.count(filteredDataLength);
}
if (params.total() <= params.count()) {
params.page(1);
}
var x = $filter('orderBy')(filteredData, params.orderBy());
var y = x.slice((params.page() - 1) * params.count(), params.page() * params.count());
return y;
} else {
return null;
}
}
});
So I tried to do a factory like this:
angular.module('control-room').factory('NgTableDataFactory', function (
$filter, MY_CONSTANTS, NgTableParams, Session
) {
var ngTableObj = {};
ngTableObj.tableData = {};
ngTableObj.filterObject = {};
ngTableObj.session = Session.get();
ngTableObj.defaultDateFormat = (!!ngTableObj.session.company ? ngTableObj.session.company.dateHourFormatHTML : null);
ngTableObj.tablePagination = (!!ngTableObj.session.user ? ngTableObj.session.user.tablePagination : MY_CONSTANTS.QTD_REG_TAB_INDEX);
ngTableObj.NgTableParamsFactory = new NgTableParams({
count: ngTableObj.tablePagination,
filter: ""
}, {
counts: rowsPerPageTemplate,
getData: function (params) {
if (!!params.filter().filter && params.filter().filter != '') {
var pfilter = params.filter().filter.toUpperCase();
} else {
var pfilter = '';
}
let filteredData = params.filter() ? $filter('filter')(ngTableObj.tableData, ngTableObj.funcFilterFactory(ngTableObj.filterObject, pfilter)) : ngTableObj.tableData;
if (!!filteredData && filteredData.length >= 0) {
params.total(filteredData.length);
var rowsPerPageTemplateWithAllData = rowsPerPageTemplate.slice();
var isFound = rowsPerPageTemplateWithAllData.some(function (element) {
return element === filteredData.length;
});
var filteredDataLength = filteredData.length + (isFound ? 1 : 0);
rowsPerPageTemplateWithAllData.push(filteredDataLength);
params.settings().counts = rowsPerPageTemplateWithAllData;
if (params.count() === MY_CONSTANTS.TABLE_PAGINATION_ALL && filteredDataLength > 0) {
params.count(filteredDataLength);
}
var x = $filter('orderBy')(filteredData, params.orderBy());
var y = x.slice((params.page() - 1) * params.count(), params.page() * params.count());
return y;
} else {
return null;
}
}
});
ngTableObj.findPropertyValue = function (obj, propertyList){
let aux = obj;
for(property of propertyList){
aux = aux[property];
}
return aux
};
ngTableObj.funcFilterFactory = function (f_Object, p_filter) {
return function (item) {
var result = false;
if (!!f_Object.columnNames) {
f_Object.columnNames.forEach(function (row) {
if (!result){
const propertyValue = ngTableObj.findPropertyValue(item, row.split('.'));
result = (propertyValue ? propertyValue.toString() : "").toUpperCase().indexOf(p_filter) >= 0 || result;
}
});
};
if (!!f_Object.translateNames) {
f_Object.translateNames.forEach(function (row) {
if (!result){
const propertyValue = ngTableObj.findPropertyValue(item, row.split('.'));
result = $filter('translate')((propertyValue != null ? propertyValue.toString() : "").toUpperCase()).indexOf(p_filter) >= 0 || result;
}
});
}
if (!!f_Object.dateFormat) {
f_Object.dateFormat.forEach(function (row) {
if (typeof(row) == 'string') {
if (!result) {
const propertyValue = ngTableObj.findPropertyValue(item, row.split('.'));
result = propertyValue ? $filter('date')(propertyValue, ngTableObj.defaultDateFormat).toUpperCase().indexOf(p_filter) >= 0 : false || result;
}
}else {
if (!result) {
const propertyValue = ngTableObj.findPropertyValue(item, row[0].split('.'));
result = propertyValue ? $filter('date')(propertyValue, row[1]).toUpperCase().indexOf(p_filter) >= 0 : false || result;
}
}
});
}
return result;
};
};
return ngTableObj
});
and in the controller is like this:
$scope.filterObject = {
columnNames : ['onboardComputer.id', 'onboardComputer.remainingMonitoringMsgs', 'vehicle.code', 'vehicle.name' ],
dateFormat : ['onboardComputer.oldestMonitoringTimestamp', 'lastCommunicatio', 'lastRegister' ]
};
$scope.tableFactory = NgTableDataFactory;
$scope.tableFactory.tableData = $scope.onboardcomputerstatus;
$scope.tableFactory.filterObject = $scope.filterObject;
$scope.tableFactory.session = Session.get();
$scope.tableParams = $scope.tableFactory.NgTableParamsFactory
Like I said, this way it work well, but only if i use one time, if I have 2 tables it stop working

Related

How to return a promise from an AngularJS Service using $q.all

The goal is to return a boolean value defining if a Job can be posted based on Earned staffing.
There are different pieces that come from three different sql tables. Rather than making a sql query that returns all of them in one result, i'm trying to understand how to use the $q.all function. The problem is that I am not getting a promise back from the service. The error is: TypeError: Cannot read property 'then' of undefined
There a few articles on this subject but most that I have found are old and still refer to using defer. I have tried the suggestions in the others and none of them have worked. They mentioned that the $q.all needs a return, and to return the $q.resolve and $q.reject for the return values.
Here is the code in my service:
function isMDOLevelAllowed(mdoLevel, finance) {
this.crData = "";
this.pData = "";
var mdoLevelToMatch = "", mdoMatrix = "", mdoOnRollsTotal = 0, mdoAuthTotal = 0;
var mdoVarianceTotal = 0, mdoPending = 0, mdoPendingThisLevel = 0;
return $q.all([
getCRO36ByFinance(finance),
epEarnedMDOSDOResource(finance),
getPendingByFinance(finance)
]).then(function (data) {
var crData = data[0];
var eData = data[1];
var pData = data[2];
var mdoData = crData.filter(function (m) { return m.jobType === "MDO"; });
mdoLevelToMatch = mdoData.filter(function (m) { return m.payGrade === mdoLevel; })[0];
mdoVarianceTotal = mdoData.reduce(function (a, b) { return a + b.variance; }, 0);
mdoMatrix = mdoData.map(function (m) { return { payGrade: m.payGrade, authorized: m.totalAuthorized }; });
mdoPending = pData.mdoTotalCount;
mdoPendingThisLevel = eval("pData.mdO" + mdoLevelToMatch.payGrade + "Count");
// Check if over Total Authorized
if (mdoVarianceTotal + mdoPending < 0) {
// Check if over Paylevel Authorized
if (mdoLevelToMatch.variance + mdoPendingThisLevel < 0) {
return $q.resolve();
}
else {
return $q.reject();
}
}
else {
return $q.reject();
}
}).$promise;
}
var service = {
getEarnedByFinance: getEarnedByFinance,
getCRO36ByFinance: getCRO36ByFinance,
getPendingByFinance: getPendingByFinance,
isMDOLevelAllowed: isMDOLevelAllowed,
isSDOAllowed: isSDOAllowed
};
return service;
How about trying:
function isMDOLevelAllowed(mdoLevel, finance) {
var defer = $q.defer();
this.crData = "";
this.pData = "";
var mdoLevelToMatch = "", mdoMatrix = "", mdoOnRollsTotal = 0, mdoAuthTotal = 0;
var mdoVarianceTotal = 0, mdoPending = 0, mdoPendingThisLevel = 0;
$q.all([
getCRO36ByFinance(finance),
epEarnedMDOSDOResource(finance),
getPendingByFinance(finance)
]).then(function (data) {
var crData = data[0];
var eData = data[1];
var pData = data[2];
var mdoData = crData.filter(function (m) { return m.jobType === "MDO"; });
mdoLevelToMatch = mdoData.filter(function (m) { return m.payGrade === mdoLevel; })[0];
mdoVarianceTotal = mdoData.reduce(function (a, b) { return a + b.variance; }, 0);
mdoMatrix = mdoData.map(function (m) { return { payGrade: m.payGrade, authorized: m.totalAuthorized }; });
mdoPending = pData.mdoTotalCount;
mdoPendingThisLevel = eval("pData.mdO" + mdoLevelToMatch.payGrade + "Count");
// Check if over Total Authorized
if (mdoVarianceTotal + mdoPending < 0) {
// Check if over Paylevel Authorized
if (mdoLevelToMatch.variance + mdoPendingThisLevel < 0) {
defer.resolve();
}
else {
defer.reject();
}
}
else {
defer.reject();
}
});
return defer.promise;
}
Take a note on how i defined var defer = $q.defer(); and then returned defer.promise just once. You dont need to return resolve and reject
Thank you for your help. I got it to work. I changed the $q.resolve, $q.reject to a return true or false, and removed the $promise at the end.
function isMDOLevelAllowed(mdoLevel, finance) {
this.crData = "";
this.pData = "";
var mdoLevelToMatch = "", mdoMatrix = "", mdoOnRollsTotal = 0, mdoAuthTotal = 0;
var mdoVarianceTotal = 0, mdoPending = 0, mdoPendingThisLevel = 0;
return $q.all([
getCRO36ByFinance(finance),
epEarnedMDOSDOResource(finance),
getPendingByFinance(finance)
]).then(function (data) {
var crData = data[0];
var eData = data[1];
var pData = data[2];
var mdoData = crData.filter(function (m) { return m.jobType === "MDO"; });
mdoLevelToMatch = mdoData.filter(function (m) { return m.payGrade === mdoLevel; })[0];
//mdoOnRollsTotal = mdoData.reduce(function (a, b) { return a + b.totalOnRolls; }, 0);
//mdoAuthTotal = mdoData.reduce(function (a, b) { return a + b.totalAuthorized; }, 0);
mdoVarianceTotal = mdoData.reduce(function (a, b) { return a + b.variance; }, 0);
mdoMatrix = mdoData.map(function (m) { return { payGrade: m.payGrade, authorized: m.totalAuthorized }; });
mdoPending = pData.mdoTotalCount;
mdoPendingThisLevel = eval("pData.mdO" + mdoLevelToMatch.payGrade + "Count");
// Check if over Total Authorized
if (mdoVarianceTotal + mdoPending < 0) {
// Check if over Paylevel Authorized
if (mdoLevelToMatch.variance + mdoPendingThisLevel < 0) {
return true;
}
else {
return false;
}
}
else {
return false;
}
});
}

Buffering in jPlayer

We use Icecast streaming server to jPlayer on our website and also used on our mobile app. I was trying to add an <intro> to the Icecast config, but when I do, it presents an issue on mobile devices. Whenever the phone has an interruption causing a temporary disconnect, like a call that comes in, the stream repeats what you started listening to when you first connected to the stream, after the intro plays again of course. For instance, if I start the stream listening to one show or song, a call comes in and ends, the intro plays on the reconnect and the stream plays from where I initially started listening.
I have played with Icecast queue and burst settings up and down and none at all, and tried different formats, the same result. I've also had conversations on a couple of other streaming related posts and have been told it seems the issue is with the client buffer and player, which I did not set up. I took a look at our stream-player.js, it is jPlayer 2.9.2 with the following tacked on to the end at line 3507:
;(function() {
var DOMParser, find, parse;
DOMParser = (typeof window !== "undefined" && window !== null ? window.DOMParser : void 0) || (typeof require === "function" ? require('xmldom').DOMParser : void 0) || function() {};
find = function(node, list) {
var attributes, childNode, childNodeName, childNodes, i, match, x, _i, _j, _ref, _ref1;
if (node.hasChildNodes()) {
childNodes = node.childNodes;
for (i = _i = 0, _ref = childNodes.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
childNode = childNodes[i];
childNodeName = childNode.nodeName;
if (/REF/i.test(childNodeName)) {
attributes = childNode.attributes;
for (x = _j = 0, _ref1 = attributes.length; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; x = 0 <= _ref1 ? ++_j : --_j) {
match = attributes[x].nodeName.match(/HREF/i);
if (match) {
list.push({
file: childNode.getAttribute(match[0]).trim()
});
break;
}
}
} else if (childNodeName !== '#text') {
find(childNode, list);
}
}
}
return null;
};
parse = function(playlist) {
var doc, ret;
ret = [];
doc = (new DOMParser()).parseFromString(playlist, 'text/xml').documentElement;
if (!doc) {
return ret;
}
find(doc, ret);
return ret;
};
(typeof module !== "undefined" && module !== null ? module.exports : window).ASX = {
name: 'asx',
parse: parse
};
}).call(this);
(function() {
var COMMENT_RE, EXTENDED, comments, empty, extended, parse, simple;
EXTENDED = '#EXTM3U';
COMMENT_RE = /:(?:(-?\d+),(.+)\s*-\s*(.+)|(.+))\n(.+)/;
extended = function(line) {
var match;
match = line.match(COMMENT_RE);
if (match && match.length === 6) {
return {
length: match[1] || 0,
artist: match[2] || '',
title: match[4] || match[3],
file: match[5].trim()
};
}
};
simple = function(string) {
return {
file: string.trim()
};
};
empty = function(line) {
return !!line.trim().length;
};
comments = function(line) {
return line[0] !== '#';
};
parse = function(playlist) {
var firstNewline;
playlist = playlist.replace(/\r/g, '');
firstNewline = playlist.search('\n');
if (playlist.substr(0, firstNewline) === EXTENDED) {
return playlist.substr(firstNewline).split('\n#').filter(empty).map(extended);
} else {
return playlist.split('\n').filter(empty).filter(comments).map(simple);
}
};
(typeof module !== "undefined" && module !== null ? module.exports : window).M3U = {
name: 'm3u',
parse: parse
};
}).call(this);
(function() {
var LISTING_RE, parse;
LISTING_RE = /(file|title|length)(\d+)=(.+)\r?/i;
parse = function(playlist) {
var index, key, line, match, tracks, value, _, _i, _len, _ref;
tracks = [];
_ref = playlist.trim().split('\n');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
line = _ref[_i];
match = line.match(LISTING_RE);
if (match && match.length === 4) {
_ = match[0], key = match[1], index = match[2], value = match[3];
if (!tracks[index]) {
tracks[index] = {};
}
tracks[index][key.toLowerCase()] = value;
}
}
return tracks.filter(function(track) {
return track != null;
});
};
(typeof module !== "undefined" && module !== null ? module.exports : window).PLS = {
name: 'pls',
parse: parse
};
}).call(this);
;(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
window.PlayerUI = (function() {
function PlayerUI(container) {
var _this = this;
this.container = container;
this.onStateButtonClicked = __bind(this.onStateButtonClicked, this);
this.duration = null;
this.state = 'loading';
this.player = $('<div></div>');
this.container.append(this.player);
this.player.jPlayer({
ready: function() {
return _this.state = 'paused';
}
});
this.volume = this.container.find('.volume-slider input').rangeslider({
polyfill: false,
onSlide: function(position, value) {
return _this.player.jPlayer('volume', value / 100.0);
},
onSlideEnd: function(position, value) {
return _this.player.jPlayer('volume', value / 100.0);
}
});
this.hookEvents();
}
PlayerUI.prototype.hookEvents = function() {
var _this = this;
this.container.find('.state-button a').click(this.onStateButtonClicked);
this.player.on($.jPlayer.event.play, function() {
return _this.setState('playing');
});
this.player.on($.jPlayer.event.pause, function() {
return _this.setState('paused');
});
this.player.on($.jPlayer.event.durationchange, function(e) {
return _this.container.trigger('player.setProgressMax', {
maxValue: e.jPlayer.status.duration
});
});
this.player.on($.jPlayer.event.timeupdate, function(e) {
return _this.container.trigger('player.updateProgress', {
value: e.jPlayer.status.currentTime
});
});
return this.player.on($.jPlayer.event.ended, function(e) {
return _this.container.trigger('player.trackEnded');
});
};
PlayerUI.prototype.setState = function(state) {
this.state = state;
return this.container.find('.state-button a').removeClass().addClass("state-" + state);
};
PlayerUI.prototype.onStateButtonClicked = function(event) {
event.preventDefault();
switch (this.state) {
case 'playing':
return this.pause();
case 'paused':
return this.play();
default:
return this.noop();
}
};
PlayerUI.prototype.setMedia = function(media) {
this.pause();
return this.player.jPlayer('setMedia', media);
};
PlayerUI.prototype.setProgress = function(pct) {
return this.player.jPlayer('playHead', pct);
};
PlayerUI.prototype.play = function() {
this.setState('playing');
return this.player.jPlayer('play');
};
PlayerUI.prototype.pause = function() {
this.setState('paused');
return this.player.jPlayer('pause');
};
PlayerUI.prototype.noop = function() {
return null;
};
return PlayerUI;
})();
}).call(this);
;(function() {
window.PlaylistUI = (function() {
function PlaylistUI(container) {
var _this = this;
this.container = container;
this.container.hide();
$(window).on('playlistloader.finished', function(evt, data) {
return _this.setPlaylist(PlaylistLoader.coalescePlaylists(data.playlists));
});
}
PlaylistUI.prototype.loadM3UList = function(m3uList) {
return new PlaylistLoader(m3uList);
};
PlaylistUI.prototype.setPlaylist = function(playlistData) {
if (typeof playlistData.data !== 'undefined') {
this.name = playlistData.name;
playlistData = playlistData.data;
}
this.playlist = playlistData;
this.container.hide();
this.unhookEvents();
this.renderPlaylist();
this.container.show();
this.hookEvents();
return this.container.trigger('playlistui.ready', {
ui: this,
autoplay: false //this.getAutoplay()
});
};
PlaylistUI.prototype.unhookEvents = function() {
return this.container.find('.playlist-item').off('click.playlistUI', 'a');
};
PlaylistUI.prototype.hookEvents = function() {
var _this = this;
return this.container.find('.playlist-item').on('click.playlistUI', 'a', function(evt) {
var idx, item;
evt.preventDefault();
idx = $(evt.target).parent('.playlist-item').data('idx');
item = _this.getItemByIdx(idx);
return _this.select(item);
});
};
PlaylistUI.prototype.renderPlaylist = function() {
var idx, item, playlist, _i, _len, _ref, _results;
playlist = this.container.find('.playlist');
playlist.empty();
_ref = this.playlist;
_results = [];
for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
item = _ref[idx];
_results.push(playlist.append(this.rowTemplate(item, idx)));
}
return _results;
};
PlaylistUI.prototype.rowTemplate = function(item, idx) {
return $("<li class=\"playlist-item\" data-idx=\"" + idx + "\">" + item.title + "</li>");
};
PlaylistUI.prototype.getAutoplay = function() {
var item, _i, _len, _ref;
_ref = this.playlist;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
if (item.autoplay) {
return item;
}
}
return null;
};
PlaylistUI.prototype.getItemByIdx = function(idx) {
return this.playlist[idx];
};
PlaylistUI.prototype.getRowForItem = function(item) {
var compare, found, idx, _i, _len, _ref;
_ref = this.playlist;
for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
compare = _ref[idx];
if (compare === item) {
found = this.container.find(".playlist-item[data-idx=" + idx + "]");
return found;
}
}
return null;
};
PlaylistUI.prototype.getIndexForItem = function(item) {
var compare, idx, _i, _len, _ref;
_ref = this.playlist;
for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
compare = _ref[idx];
if (item === compare) {
return idx;
}
}
return null;
};
PlaylistUI.prototype.findNext = function() {
var currentIndex, nextIndex;
currentIndex = this.getIndexForItem(this.current);
if (currentIndex === null) {
return null;
}
nextIndex = currentIndex + 1;
if (nextIndex >= this.playlist.length) {
return null;
}
return this.playlist[nextIndex];
};
PlaylistUI.prototype.select = function(item) {
if (item) {
this.current = item;
this.getRowForItem(item).addClass('selected').siblings().removeClass('selected');
return this.container.trigger('playlistui.select', {
ui: this,
item: item
});
}
};
PlaylistUI.prototype.selectFirst = function() {
return this.select(this.playlist[0]);
};
PlaylistUI.prototype.selectNext = function() {
var nextItem;
nextItem = this.findNext();
if (nextItem === null) {
return false;
}
this.select(nextItem);
return true;
};
return PlaylistUI;
})();
}).call(this);
;(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
window.PlaylistLoader = (function() {
function PlaylistLoader(playlists) {
this.playlists = playlists;
this.loadedItem = __bind(this.loadedItem, this);
this.loadPlaylists();
}
PlaylistLoader.prototype.loadPlaylists = function() {
var idx, item, _i, _len, _ref, _results,
_this = this;
this.loadCount = 0;
this.data = new Array(this.playlists.length);
_ref = this.playlists;
_results = [];
for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
item = _ref[idx];
_results.push((function() {
var tmp;
tmp = idx;
return jQuery.ajax({
url: item
}).done(function(data) {
return _this.loadedItem(tmp, data);
});
})());
}
return _results;
};
PlaylistLoader.prototype.loadedItem = function(idx, data) {
var playlist;
playlist = M3U.parse(data);
this.data[idx] = playlist;
$(window).trigger('playlistloader.loadeditem', {
index: idx,
playlist: playlist
});
this.loadCount++;
if (this.loadCount === this.playlists.length) {
return this.finishedLoading();
}
};
PlaylistLoader.prototype.finishedLoading = function() {
return $(window).trigger('playlistloader.finished', {
playlists: this.data
});
};
PlaylistLoader.coalescePlaylists = function(playlistsLoaded) {
var fileEntry, output, playlist, _i, _j, _len, _len1;
output = [];
for (_i = 0, _len = playlistsLoaded.length; _i < _len; _i++) {
playlist = playlistsLoaded[_i];
for (_j = 0, _len1 = playlist.length; _j < _len1; _j++) {
fileEntry = playlist[_j];
output.push(fileEntry);
}
}
return output;
};
return PlaylistLoader;
})();
}).call(this);
;(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
window.StreamUI = (function() {
function StreamUI(selector, streamPlaylists) {
this.selector = selector;
this.streamPlaylists = streamPlaylists;
this.playlistSelect = __bind(this.playlistSelect, this);
this.playlistReady = __bind(this.playlistReady, this);
this.container = jQuery(this.selector);
this.playlist = new PlaylistUI(this.container.find('.playlist-ui'));
this.player = new PlayerUI(this.container.find('.player-ui'));
this.hookEvents();
this.playlist.loadM3UList(this.streamPlaylists);
}
StreamUI.prototype.hookEvents = function() {
var playlistUI;
playlistUI = this.container.find('.playlist-ui');
playlistUI.on('playlistui.ready', this.playlistReady);
return playlistUI.on('playlistui.select', this.playlistSelect);
};
StreamUI.prototype.playlistReady = function(evt, eventinfo) {
if (eventinfo.autoplay !== null) {
return eventinfo.ui.select(eventinfo.autoplay);
} else {
return eventinfo.ui.selectFirst();
}
};
StreamUI.prototype.playlistSelect = function(evt, eventinfo) {
this.player.setMedia({
mp3: eventinfo.item.file
});
return this.player.play();
};
return StreamUI;
})();
}).call(this);
Although I'm primarily a linux developer with most of my programming experience in Perl and PHP, and do know jQuery pretty well dealing with my web development, I'm surely a novice when it comes to jPlayer or even audio streaming. I was hoping someone could spot something in hte code above that could contribute to the issue we have when adding an intro to our Icecast 2.4.4 stream?
Our streams are available at the URL below, I have the intro on our HD4 stream at the moment.
streaming player
The issue is easily duplicated by starting the stream and listening a bit until the song changes, call the phone letting it interrupt the stream, then hang up. This will cause the first song listened to be playing again after the intro.
I believe the codec is a match, I did have an issue getting the intro to work until I formatted as MP3 128Kbps bit rate 44.1KHz sampling and 2 channel stereo. Here is the intro file info:
user#stream:~$ mediainfo /usr/share/icecast2/web/high_quality.mp3
General
Complete name : /usr/share/icecast2/web/high_quality.mp3
Format : MPEG Audio
File size : 138 KiB
Duration : 8s 777ms
Overall bit rate mode : Constant
Overall bit rate : 128 Kbps
Writing library : LAME3.99r
Audio
Format : MPEG Audio
Format version : Version 1
Format profile : Layer 3
Mode : Joint stereo
Mode extension : MS Stereo
Duration : 8s 803ms
Bit rate mode : Constant
Bit rate : 128 Kbps
Channel(s) : 2 channels
Sampling rate : 44.1 KHz
Compression mode : Lossy
Stream size : 137 KiB (100%)
Writing library : LAME3.99r
Encoding settings : -m j -V 4 -q 3 -lowpass 17 -b 128
Sounds like the underlying browser cache kicks in and forces replay of something held in memory. Browsers are 'awesome' like that under some circumstances and will then go out of their way to ignore no-cache directives and other things.
One way to make sure the browser doesn't try to play cache shenanigans is to add a "cache buster". Essentially a query string ( /stream?foo=bar ), which makes the browser engine think it's dynamically generated content and discard its cache; cf. https://www.keycdn.com/support/what-is-cache-busting .
At this time your Icecast server doesn't seem to answer any requests. So I can't look into the specifics on your side.

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);
});

angular's equivalent of ko.utils.arrayMap or adding extra properties to returned data array?

Im in the process of converting a knockout app to angular, I currently get an array of objects from the server but I would like to extend each object by adding some extra properties.
In knockout I would do the following:
var mappedResults = ko.utils.arrayMap(results, function(item) {
item.selected = ko.observable(true);
item.viewPreview = ko.observable(false);
return new reed.search.Candidate(item, self.viewModel.fileDownloadFailCookieName);
});
and the Candidate viewmodel:
reed.search.Candidate = function(data, fileDownloadFailCookieName) {
debugger
if (data == null) {
throw 'Error: cannot initiate candidate';
}
this.fileDownloadFailCookieName = fileDownloadFailCookieName;
this.candidateId = data.CandidateId;
this.name = data.Name;
this.surname = data.Surname;
this.forename = data.Forename;
this.displayLocation = data.DisplayLocation;
this.lastJobDetails = data.LastJobDetails;
this.displayPayRate = data.DisplayPayRate;
this.lastSignIn = data.LastSignIn;
this.downloadCVUrl = data.DownloadCVUrl;
this.additionalInfo = data.AdditionalInfo;
this.isAvailable = (data.IsAvailable) ? "Availability confirmed" : "";
this.availableMornings = data.AvailableMornings;
this.availableAfternoons = data.AvailableAfternoons;
this.availableEvenings = data.AvailableEvenings;
this.availableWeekends = data.AvailableWeekends;
this.availableShiftWork = data.AvailableShiftWork;
this.availableNights = data.AvailableNights;
this.availabilityUpdatedOn = data.AvailabilityUpdatedOn;
this.availabilityUpdatedOnDate = "| <strong>Availability updated</strong> " + data.AvailabilityUpdatedOn;
this.isAvailableForSomething =
this.availableMornings
|| this.availableAfternoons
|| this.availableEvenings
|| this.availableWeekends
|| this.availableShiftWork
|| this.availableNights;
this.viewPreview = ko.observable(false);
this.selected = ko.observable(false);
this.hasBeenNotified = ko.observable(false);
this.select = function() {
this.selected(true);
};
this.deSelect = function() {
this.selected(false);
};
this.HasFlagSet = function(availability) {
return availability ? "availabilitySelected" : "availabilityNotSelected";
};
this.ajaxCvDownload = function() {
var path = window.location.href,
iframeError,
cookieName = this.fileDownloadFailCookieName;
// download path
path = path.match(/(.+\/)/ig)[0];
if (path.match(/home/ig)) {
path = path.replace('home', this.downloadCVUrl);
} else {
path = this.downloadCVUrl;
};
$('<iframe />').attr('src', path)
.hide()
.appendTo('body').load(function() {
var message = decodeURIComponent(reed.shared.utils.getCookie(cookieName));
message = message.replace(/\+/g, " ");
if (message.length > 0 && message != "null") {
reed.shared.utils.showMessage(message, "Download Failed");
}
});
}
}
how can I achieve the same functionality in angular?
You don't need angular for this array itself contains a map function and all modern browsers support it.
var mappedResults = results.map(function(item) {
item.selected = true;
item.viewPreview = false;
return new reed.search.Candidate(item,
self.viewModel.fileDownloadFailCookieName);
});
Some other things you can improve. Firstly if you are using webapi to return data, use a formatter that fixes casing.Check this blog http://blogs.msmvps.com/theproblemsolver/2014/03/26/webapi-pascalcase-and-camelcase/
Once you have the formatter lines such as these are not required
this.surname = data.Surname;
You can then use angular.extend to copy properties into your class.

How to check if expression will have a value after evaluating

Let's say I have a following template:
"foo['x'] = '{{ myVar }}';"
Is there an angular way of checking if evaluating this against my current scope will give myVar some value ? I've got an array of such small templates and I only want to include them in the document when values are truthy. I was hoping either $interpolate, $parse or $eval might come in handy here. I know for sure that $interpolate is useless. What about the other two ? Maybe it's at least possible to get the name of the assigned value/expression ?
EDIT
I wasn't specific enough. What I was trying to achieve, was checking in advance if for example template '{{ myVar }}' evaluated against the current scope will return an empty string or value of the scope variable (if it exists). The case was really specific - when traversing an array of short templates I wanted to know if a template will return as an empty string or not, and only include it in my final html if it doesn't.
I'm not sure what are you trying to achieve, but to if you want to check if myVar is truthy in current scope, you can:
{{myVar ? "aw yiss" : "nope"}}
Evaluates to "aw yiss" if myVar is truthy and "nope" otherwise.
I ended up with a modified $interpolate provider but maybe someone knows a shorter solution :
app.provider('customInterpolateProvider', [
function $InterpolateProvider() {
var startSymbol = '{{';
var endSymbol = '}}';
this.startSymbol = function(value){
if (value) {
startSymbol = value;
return this;
} else {
return startSymbol;
}
};
this.endSymbol = function(value){
if (value) {
endSymbol = value;
return this;
} else {
return endSymbol;
}
};
this.$get = ['$parse', '$sce', function($parse, $sce) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length;
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
allOrNothing = !!allOrNothing;
var startIndex,
endIndex,
index = 0,
expressions = [],
parseFns = [],
textLength = text.length,
exp;
var getValue = function (value) {
return trustedContext ?
$sce.getTrusted(trustedContext, value) :
$sce.valueOf(value);
};
var stringify = function (value) {
if (value == null) {
return '';
}
switch (typeof value) {
case 'string':
break;
case 'number':
value = '' + value;
break;
default:
value = angular.toJson(value);
}
return value;
};
var parseStringifyInterceptor = function(value) {
try {
return stringify(getValue(value));
} catch(err) {
console.err(err.toString());
}
};
while(index < textLength) {
if ( ((startIndex = text.indexOf(startSymbol, index)) !== -1) &&
((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) !== -1) ) {
exp = text.substring(startIndex + startSymbolLength, endIndex);
expressions.push(exp);
parseFns.push($parse(exp, parseStringifyInterceptor));
index = endIndex + endSymbolLength;
} else {
break;
}
}
if (!expressions.length && !text.contains(startSymbol) && !text.contains(endSymbol)) {
expressions.push(text);
}
if (!mustHaveExpression) {
var compute = function(values) {
for(var i = 0, ii = expressions.length; i < ii; i++) {
if (allOrNothing && angular.isUndefined(values[i])) {
return;
}
expressions[i] = values[i];
}
return expressions.join('');
};
return angular.extend(function interpolationFn(context) {
var i = 0;
var ii = expressions.length;
var values = new Array(ii);
try {
if (ii && !parseFns.length) {
return expressions[0];
} else {
for (; i < ii; i++) {
values[i] = parseFns[i](context);
}
return compute(values);
}
} catch(err) {
console.err(err.toString());
}
}, {
exp: text,
expressions: expressions,
$$watchDelegate: function (scope, listener, objectEquality) {
var lastValue;
return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
var currValue = compute(values);
if (angular.isFunction(listener)) {
listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
}
lastValue = currValue;
}, objectEquality);
}
});
}
}
return $interpolate;
}];
}
]);
Lines below were added because in some cases I have a predefined text in my short template and I always want to render it :
if (!expressions.length && !text.contains(startSymbol) && !text.contains(endSymbol)) {
expressions.push(text);
}
if (ii && !parseFns.length) {
return expressions[0];
} else {

Resources