How to have smart-table parse content as HTML / conditional formatting - angularjs

I know that I can format a cell to parse content as a link in ng-repeat:
<a ng-href="{{::domainname}}/{{::row.sector}}/{{::row.cname}}/ipo-{{::row.tickerbb}}.html">{{::row.cname}}</a>
Here is the fiddle.
How do I make it dynamic, so that if row.tickerbb is null - show a different URL?
I tried to do it in the controller, looping through the data:
var i = 0;
$.each(data, function () {
if (data[i].tickerbb != null) {
data[i].cname = '<a title="' + data[i].cname + '"' + ' ng-href="' + domainname + '/' + data[i].sector + '/' + data[i].shortcname + '/ipo-' + data[i].tickerbb + '.html">' + data[i].cname + '</a>';
}
else {
data[i].cname = '<a title="' + data[i].cname + '" href="Holdings">' + data[i].cname + '</a>';
}
i += 1;
})
But the results show up as raw html tags:
How do I do conditional formatting of the smart-table cell? Or is there a way to sanitize cells in smart-tables?

Resolved it by constructing my link in the controller:
var i = 0;
$.each(data, function () {
data[i].weight = (data[i].weight * 100).toFixed(2) + '%';
if (data[i].shortcname != null) {
var cname = data[i].cname;
var sector = data[i].sector;
var shortcname = data[i].shortcname;
var tic = data[i].tickerbb;
var url = '<a title="' + cname + '" href="' + $scope.domainname + '/' + sector + '/' + shortcname + '/ipo-' + tic + '.html">' + cname + '</a>';
data[i].cname = url;
}
else
{
data[i].cname = '<a title="' + data[i].cname + '" href="Holdings">' + data[i].cname + '</a>';
}
i += 1;
})
And then sanitizing it inside ng-repeat:
<td ng-bind-html="row.cname"></td>

Related

How can I display a treeview with an already selected node?

I'm using this slightly modified treeview directive (https://github.com/eu81273/angular.treeview, jFiddle Example) in my app. I can get it to save the node that has been selected, but I can't seem to figure out how to display the treeview with a node already selected, if the user edits previously saved form.
Treeview Directive:
angular.module('App').directive('treeModel', ['$compile', function ($compile) {
return {
restrict: 'A',
controller: treeviewController,
link: function (scope, element, attrs) {
//tree id
var treeId = attrs.treeId;
//tree model
var treeModel = attrs.treeModel;
//node id
var nodeId = attrs.nodeId || 'id';
//node label
var nodeLabel = attrs.nodeLabel || 'label';
//children
var nodeChildren = attrs.nodeChildren || 'children';
//tree template
var template =
'<ul>' +
'<li data-ng-repeat="node in ' + treeModel + '">' +
'<i class="collapsed" data-ng-show="node.' + nodeChildren + '.length && node.collapsed" data-ng-click="' + treeId + '.selectNodeHead(node)"></i>' +
'<i class="expanded" data-ng-show="node.' + nodeChildren + '.length && !node.collapsed" data-ng-click="' + treeId + '.selectNodeHead(node)"></i>' +
'<i class="normal" data-ng-hide="node.' + nodeChildren + '.length" data-ng-class="node.selected" data-ng-click="' + treeId + '.selectNodeLabel(node)"></i> ' +
'<span data-ng-hide="node.' + nodeChildren + '.length" class="tree-item" data-ng-class="node.selected" data-ng-click="' + treeId + '.selectNodeLabel(node)">{{node.' + nodeLabel + '}}</span>' +
'<span data-ng-show="node.' + nodeChildren + '.length" class="tree-node" data-ng-class="node.selected" data-ng-click="' + treeId + '.selectNodeLabel(node)">{{node.' + nodeLabel + '}}</span>' +
'<div data-ng-hide="node.collapsed" data-tree-id="' + treeId + '" data-tree-model="node.' + nodeChildren + '" data-node-id=' + nodeId + ' data-node-label=' + nodeLabel + ' data-node-children=' + nodeChildren + '></div>' +
'</li>' +
'</ul>';
//check tree id, tree model
if (treeId && treeModel) {
//root node
if (attrs.angularTreeview) {
//create tree object if not exists
scope[treeId] = scope[treeId] || {};
//if node head clicks,
scope[treeId].selectNodeHead = scope[treeId].selectNodeHead || function (selectedNode) {
//Collapse or Expand
selectedNode.collapsed = !selectedNode.collapsed;
};
// my attempt at pre-loading a selected node
if (scope.savedNode != undefined) {
scope[treeId].currentNode = scope.savedNode;
//scope.savedNode comes from the controller, and looks like this...
/*{
"children": [],
"collapsed": false,
"selected": "selected",
"treeNodeName": "Node name here",
"treeNodeId": "eY40Ik"
}*/
}
//if node label clicks,
scope[treeId].selectNodeLabel = scope[treeId].selectNodeLabel || function (selectedNode) {
// only allow to select nodes that are not expandable
if (!selectedNode.children.length) {
//remove highlight from previous node
if (scope[treeId].currentNode && scope[treeId].currentNode.selected) {
scope[treeId].currentNode.selected = undefined;
}
//toggle currentNode
if (scope[treeId].currentNode == selectedNode) {
scope[treeId].currentNode = {};
selectedNode = {};
scope.currentSelectedNode = {
name: "",
id: ""
};
} else {
scope[treeId].currentNode = selectedNode;
selectedNode.selected = 'selected';
scope.currentSelectedNode = {
name: selectedNode.sourceName,
id: selectedNode.sourceId
}
}
}
};
}
//Rendering template.
element.html('').append($compile(template)(scope));
}
}
};
}]);
HTML:
<div data-angular-treeview="true"
data-tree-id="treeId"
data-tree-model="treeData"
data-node-id="treeNodeId"
data-node-label="treeNodeName"
data-node-children="children">
</div>
Only the selected node is being saved, not the entire tree-model.
How would I load up a tree with a node already selected?

Widget for getting facebook group's timeline / posts

I want to integrate facebook Widget for getting facebook group's timeline / posts. I have searched & got this https://developers.facebook.com/docs/plugins/page-plugin but this gives user's & page's timeline. I wanted Group's timeline. I didn't found perfect answer on Fb Developer portal & didn't get anything on web.
Any help on this is appreciated.
Thanks in Advance.
After lots of search, no plugin kind of thing i got for this. But yes got one blog in php where the developer made custom widget manually, I modified it with JavaScript & jQuery.
<div style="height: 375px; background: #f6f7f9;">
<div id="fb-root"></div>
<p class="text-center media-body social-link" style="background: white">
<img src="~/Content/Images/Link-Red.png" />
Facebook Group
</p>
<div id="fix-div"></div>
<div id="facebook-group" style="overflow-y: scroll; height: 375px; margin-top: 55px;"></div>
</div>
Facebook JavaScript API as follows-
<script>
var access_token = '<!-- Valid fb access token -->';
var groupId = 'valid facebook group id';
window.fbAsyncInit = function () {
FB.init({
appId: 'valid facebook app id',
cookie: true,
xfbml: true,
version: 'v2.8'
});
FB.api("" + groupId + "?fields=cover,icon,name,privacy",
'get',
{ access_token: access_token },
function (groupResponse) {
if (groupResponse && !groupResponse.error) {
$("#fix-div").html('');
$("#facebook-group").html('');
var fixDivHtml =
"<div style='z-index: 10;position: absolute;border: 1px solid #e9ebee;max-width: 470px;background: white;min-height: 50px;'><div class='media' style='border: 0'><div class='media-left media-middle' style='vertical-align: bottom'><a href='https://www.facebook.com/groups/" + groupResponse.id + "' target='_blank'><img class='media-object' src='/Content/Images/Facebook-group.png' style='min-height: 50px;padding: 5px 10px;width: 64px;'></a></div><div class='media-body media-middle'><a href='https://www.facebook.com/groups/" + groupResponse.id + "' target='_blank'><h4 class='media-heading' style='font-size: 14px;font-weight: bold;'>" + groupResponse.name + "</h4></a></div></div></div>";
$("#fix-div").append(fixDivHtml);
FB.api("/" +
groupId +
"/feed?fields=id,message,link,attachments{media,description},created_time,from,object_id,parent_id&limit=1000",
'get',
{ access_token: access_token },
function (response) {
if (response && !response.error) {
for (var i = 0; i < response.data.length; i++) {
var picture = undefined;
var description = undefined;
var date = formatDate(response.data[i].created_time);
if (response.data[i].attachments !== undefined) {
if (response.data[i].attachments.data.length > 0) {
if (
response.data[i].attachments.data[0].media !==
undefined) {
if (
response.data[i].attachments.data[0].media
.image !==
undefined)
picture = response.data[i].attachments
.data[0].media.image.src;
if (
response.data[i].attachments.data[0].media
.image.description !==
undefined)
description = response.data[i].attachments
.data[0].media.image.description;
} else {
if (
response.data[i].attachments.data[0]
.description !==
undefined)
description = response.data[i].attachments
.data[0].description;
}
}
}
var message = response.data[i].message;
var
append =
"<div class='border'><div class='media'><div class='media-left media-middle'><a href='https://www.facebook.com/" + response.data[i].from.id + "' target='_blank'><img class='media-object' src='http://graph.facebook.com/" + response.data[i].from.id + "/picture?type=square'></a></div><div class='media-body' style='vertical-align: bottom'><a href='https://www.facebook.com/" + response.data[i].from.id + "' target='_blank'><h4 class='media-heading'>" + response.data[i].from.name + ".<br /><small>" + date + "</small></h4></a></div>";
if (message !== undefined) {
if (ValidURL(message) === 1) {
append +=
"<a class='ellipsis' href='" +
message +
"' target='_blank'>" +
message +
"</a>";
} else {
append += "<a class='ellipsis'>" + message + "</a>";
}
}
if (picture !== undefined)
append +=
"<a href='" +
response.data[i].link +
"' target='_blank'><img class='img-responsive' src='" +
picture +
"'/></a>";
if (description !== undefined)
append += "<p>" + description + "</p>";
append += '<hr///>' +
"<div class='btn-group btn-group-justified' role='group' aria-label='Justified button group'>" +
"<a href=" +
response.data[i].link +
" class='btn btn-default' role='button' target='_blank'><i class='fa fa-thumbs-up' aria-hidden='true'></i> Like</a>" +
"<a href=" +
response.data[i].link +
" class='btn btn-default' role='button' target='_blank'><i class='fa fa-comment' aria-hidden='true'></i> Comment</a></div></div></div>";
$("#facebook-group").append(append);
}
}
});
}
});
};
(function () {
var e = document.createElement('script');
e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
var formatDate = function (input) {
var d = new Date(Date.parse(input));
input = d.toString();
d = new Date(Date.parse(input.replace(/-/g, "/")));
var month = [
'january', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December'
];
var date = d.getDay().toString() +
" " +
month[d.getMonth().toString()] +
", " +
d.getFullYear().toString();
return (date);
};
function ValidURL(str) {
if (
/^(http|https|ftp):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/i.test(str))
return 1;
else
return -1;
}
</script>
Here formatDate & ValidURL are helper functions used for some cosmetic operations.

Icomoon glyph on group grid Extjs action column not working?

I have an issue on showing icomoon glyph on grid action columns using sencha architect in extjs 5.0 application. I am using group grid here. Glyphs are showing nicely on any ext button btw.
I have made an overwrite class for Ext.grid.column.Action like shown in following link as
Ext.define('MyApp.override.grid.column.Action', {
override: 'Ext.grid.column.Action',
// overridden to implement
defaultRenderer: function(v, cellValues, record, rowIdx, colIdx, store, view) {
var me = this,
prefix = Ext.baseCSSPrefix,
scope = me.origScope || me,
items = me.items,
len = items.length,
i = 0,
item, ret, disabled, tooltip,glyph, glyphParts, glyphFontFamily;
// Allow a configured renderer to create initial value (And set the other values in the "metadata" argument!)
// Assign a new variable here, since if we modify "v" it will also modify the arguments collection, meaning
// we will pass an incorrect value to getClass/getTip
ret = Ext.isFunction(me.origRenderer) ? me.origRenderer.apply(scope, arguments) || '' : '';
cellValues.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
for (; i < len; i++) {
item = items[i];
disabled = item.disabled || (item.isDisabled ? item.isDisabled.call(item.scope || scope, view, rowIdx, colIdx, item, record) : false);
tooltip = disabled ? null : (item.tooltip || (item.getTip ? item.getTip.apply(item.scope || scope, arguments) : null));
if(Ext.isFunction(item.getGlyph)){
glyph = item.getGlyph.apply(item.scope || scope, arguments);
}else{
glyph = item.glyph;
}
// Only process the item action setup once.
if (!item.hasActionConfiguration) {
// Apply our documented default to all items
item.stopSelection = me.stopSelection;
item.disable = Ext.Function.bind(me.disableAction, me, [i], 0);
item.enable = Ext.Function.bind(me.enableAction, me, [i], 0);
item.hasActionConfiguration = true;
}
if (glyph ) {
if (typeof glyph === 'string') {
glyphParts = glyph.split('#');
glyph = glyphParts[0];
glyphFontFamily = glyphParts[1];
} else {
glyphFontFamily = Ext._glyphFontFamily;
}
ret += '<span role="button" title="' + (item.altText || me.altText) + '" class="' + prefix + 'action-col-icon ' + prefix + 'action-col-glyph ' + prefix + 'action-col-' + String(i) + ' ' + (disabled ? prefix + 'item-disabled' : ' ') +
' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope || scope, arguments) : (item.iconCls || me.iconCls || '')) + '"' +
' style="font-family:' + glyphFontFamily + '"' +
(tooltip ? ' data-qtip="' + tooltip + '"' : '') + '>&#' + glyph + ';</span>';
} else {
ret += '<img role="button" alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
'" class="' + me.actionIconCls + ' ' + prefix + 'action-col-' + String(i) + ' ' + (disabled ? prefix + 'item-disabled' : ' ') +
(Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope || scope, arguments) : (item.iconCls || me.iconCls || '')) + '"' +
(tooltip ? ' data-qtip="' + tooltip + '"' : '') + ' />';
}
}
return ret;
}
});
and also applied getGlyph function like:
getGlyph: function(v, meta, rec) {
return 'xe600#icomoon';
}
But still not showing any icon or glyp at the column.
I found the following output from the override class as
<span role="button" title="" class="x-action-col-icon x-action-col-glyph x-action-col-0 xe600#icomoon" style="font-family:icomoon"></span>
Which seems fine to me. Not sure what is wrong here, can any one help me?
Its my bad I could not check in the link i mentioned in my question:
I have to add the css line in my css file for showing the glyphs in action columns:
.x-action-col-glyph {font-size:16px; line-height:16px; color:#9BC8E9; width:20px}
After this glyphs are shown.

getClass for actionColumn only in a few rows

I'm using the code below, to set the css class for an action column.
But even if the result is null, some elements are inserted by extjs.
getClass: function(v, meta, data) {
if (data.myDate < new Date())
return null;
else
return 'insert';
}
Generated html for return null:
<img alt="" src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
class="x-action-col-icon x-action-col-1 null">
The major problem is that cursor is changed to a hand pointer when moving this "blank" space.
There is a way to not generate elements when no icon is to be shown?
I don't see any way to do it without extending action column. IMO easiest way is to provide custom renderer function. Example:
Ext.define('Ext.grid.column.MyAction', {
extend: 'Ext.grid.column.Action',
constructor: function(config) {
var me = this,
cfg = Ext.apply({}, config),
items = cfg.items || [me],
l = items.length,
i,
item,
cls;
me.callParent(arguments);
me.renderer = function(v, meta) {
v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
for (i = 0; i < l; i++) {
item = items[i];
item.disable = Ext.Function.bind(me.disableAction, me, [i]);
item.enable = Ext.Function.bind(me.enableAction, me, [i]);
cls = (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || ''));
if (cls !== null) {
v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
'" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' + (item.disabled ? Ext.baseCSSPrefix + 'item-disabled' : ' ') + (item.iconCls || '') +
' ' + cls + '"' +
((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
}
}
return v;
};
}
});

jQuery / json loop not giving me full result with .html()

// Calling the video function with JSON
$.getJSON("videos.php", function(data){
// first check if there is a member available to display,
//if not then show error message
if(data == '') {
$('#tabs-4').html("<div class='errorMember'>Sorry, there is currently no member available videos</div>");
}
// if there is a member, then loop through each data available
else {
$.each(data, function(i,name){
content = '<div class="left"><img src="' + name.pic + '"/>';
content += '<p>' + name.name + '</p>';
content += 'Video link';
content += '</div><br/><hr>';
$("#tabs-4").html(content);
});
}
});​
The problem is that it only gives me one result instead of list of results from the array but if I appendTo(content) .. it adds the full list of results under the current which is not what I want because I need to refresh that content with updated data.
Any ideas to what I'm doing wrong?
Probably so far only the last Element is getting Displayed .
// Calling the video function with JSON
$.getJSON("videos.php", function(data){
// first check if there is a member available to display, if not then show error message
if(data == '') {
$('#tabs-4').html("<div class='errorMember'>Sorry, there is currently no member available videos</div>");
}
// if there is a member, then loop through each data available
else {
//If you want to Clear the Container html
$("#tabs-4").html('');
$.each(data, function(i,name){
content = '<div class="left"><img src="' + name.pic + '"/>';
content += '<p>' + name.name + '</p>';
content += 'Video link';
content += '</div><br/><hr>';
$("#tabs-4").append(content);
});
}
});
Empty the element before filling it:
$('#tabs-4').empty();
$.each(data, function(i,name){
var content =
'<div class="left"><img src="' + name.pic + '"/>' +
'<p>' + name.name + '</p>' +
'Video link' +
'</div><br/><hr>';
$("#tabs-4").append(content);
});
Or put all the elements in the string before putting it in the element:
var content = '';
$.each(data, function(i,name){
content +=
'<div class="left"><img src="' + name.pic + '"/>' +
'<p>' + name.name + '</p>' +
'Video link' +
'</div><br/><hr>';
});
$("#tabs-4").html(content);
If I well understood, probably you may want do something like this
...
else {
$("#tabs-4").empty(); // remove previous data (if any)
$.each(data, function(i,name){
content = '<div class="left"><img src="' + name.pic + '"/>';
content += '<p>' + name.name + '</p>';
content += 'Video link';
content += '</div><br/><hr>';
$("#tabs-4").append(content); // append new data
});
}

Resources