I have an XML file that contains one set of data and this has to be represented in one of the many dojo content panes of a HTML page. I've tried dojox.grid.DataGrid and it works; however since the data grid is used to generally represent tabular data, I don't want to use data grid.
Is there any other way to represent this data in a simple format?
The XML file is something like this:
<Summary>
<neName>abc</neName>
<neType>pqr</neType>
<neRelease>2.0</neRelease>
<neAddress>10.10.82.105</neAddress>
<supervisionState>SUPERVISED</supervisionState>
<operationalState>ENABLED</operationalState>
<alignmentState>ALIGNED</alignmentState>
<criticalAlarms>0</criticalAlarms>
<majorAlarms>0</majorAlarms>
<minorAlarms>0</minorAlarms>
<noOfShelves>5</noOfShelves>
</Summary>
I want this data to be represented something like this:
From what you want the data to look like, I would go for basic css styling of HTML elements rather than any widget.
You can use dgrid however,
check:
https://github.com/SitePen/dgrid/
http://www.sitepen.com/blog/category/dgrid/
If you're feeling frisky, you can make a sort-of generic, XML data widget. Here's an example I have from some time ago.
dojo.declare("foo.XmlDisplay", dijit._Widget, {
postCreate: function()
{
this.inherited(arguments);
dojo.xhrGet({
url: this.href,
handleAs: "xml",
load: dojo.hitch(this, "setData")
});
},
setData: function(data)
{
// All items with a xmldisp-tag attribute should get data
dojo.query("*[data-xmldisp-tag]", this.containerNode).forEach(
function(item) {
var tag = dojo.attr(item, "data-xmldisp-tag");
var value = data.getElementsByTagName(tag);
if(value.length == 1) item.innerHTML = value[0].textContent;
else console.warn("No data in xml for",tag);
}
);
}
});
You can then use it something like this in your HTML (i.e. the widget doesn't care how you display the data, it just uses the given tag names to lookup data in the XML from the server):
<div data-dojo-type="foo.XmlDisplay" href="/MyXmlStuff?id=42">
<dl>
<dt>NE name</dt><dd data-xmldisp-tag="nename">-</dd>
<dt>NE type</dt><dd data-xmldisp-tag="netype">-</dd>
</dl>
<dl>
<dt>Alarms</dt><dd data-xmldisp-tag="majoralarms">-</dd>
<dt>Minor</dt><dd data-xmldisp-tag="minoralarms">-</dd>
</dl>
</div>
Here's a modified jsfiddle you can try: http://fiddle.jshell.net/K4UnJ/3/
Not sure if this fits your task at all, but since I had very similar code lying around, I thought I'd share.
Related
I am trying to make the page content dynamic. I am using ck-editor in which i added html content and used the same vue variables inside it which i declared in the vue file where i want to show ck-editor data. I found a similar post vuejs - “editing” html inside variable
which works fine if i write the html inside a variable. But in my case, i am saving data in database. It is saving properly with html tags, without converting the tags. When i get data using axios it returns it in form of string. And i used vue variable to display that html.
Here is my code for better understanding:
<div v-html="htmlText"></div>
new Vue({
el: '#app',
created() {
this.getSalesContent();
},
data: {
salesContent: '',
pageName: 'Sales',
salesNumber: '987-586-4511'
},
computed: {
htmlText() {
return `${this.salesContent}`;
//return this.salesContent;
}
},
methods: {
getSalesContent(){
axios.get('api/Sales').then(({ data }) => { // getting data from DB
this.salesContent = data.sales; //data.sales have this.pageName and this.salesNumber variables
});
}
}
});
Here is the example of data saved in db:
<p style="font-weight:bold"><span style="color:red">{{pageName}}</span>,</p>
<p style="font-weight:bold"><span style="color:red">${this.pageName} ${this.pageName}</span></p>
<p style="font-weight:bold">Contact Sales at ${this.salesNumber} {{salesNumber}}</span></p>
I used variables in all possible ways. But on the page they are printing in it the same way i saved it. Here is the output:
screenshot
Can anyone help me make it working.
Thanks in Advance.
According to the docs this does not seem possible:
https://v2.vuejs.org/v2/guide/syntax.html#Raw-HTML
Particularly:
The contents of the span will be replaced with the value of the
rawHtml property, interpreted as plain HTML - data bindings are
ignored.
You could as suggested in that answer just use a computed based on what you get from the server.
IMHO since the salesContent is fetched from db, it's a plain String. Thus nor vuejs or vanilla javascript will replace the inline variables with their values. (It may be possible by using eval, but it's totally out of question...) You should manually do that with String replace function. Like the following:
<p style="font-weight:bold"><span style="color:red">{{pageName}}</span>,</p>
<p style="font-weight:bold">Contact Sales at {{salesNumber}}</span></p>
methods: {
getSalesContent(){
axios.get('api/Sales').then(({ data }) => { // getting data from DB
let salesContent = data.sales; //data.sales have this.pageName and this.salesNumber variables
salesContent = salesContent.replace(/{{pageName}}/g, this.pageName)
salesContent = salesContent.replace(/{{salesNumber}}/g, this.salesNumber)
this.salesContent = salesContent
});
}
}
A bit of a newbie question for xml/krpano,
I have a list of json items that I want to be dynamically loaded into XML <hotspots>. I can loop through each item in JavaScript but I have no clue how to do the same loop in XML!
Check out this picture:
Imagine that each rectangle with an image is one item in a JSON list. Each rectangle you see is a <hotspot>. Right now these three hotspots are hardcoded into the XML file, but I want to dynamically load hotspots based on how many JSON list items exist.
Here is one hotspot. If my json list has 16 items, I would expect 16 hotspots
to be loaded.
<!--* video image thumbnail *-->
<hotspot name="start" distorted="true"
url="/panorama/%$panoId%/thumb.png"
ath="0" atv="0"
ox="0" oy="36"
vr_timeout="2000"
zorder="99"
scale="0.8"
onclick="changepano( loadscene(video_scene, null, MERGE|KEEPVIEW|KEEPMOVING, BLEND(1)); );"
alpha="0.0"
onloaded="if(vr_start_done === true, removehotspot(start); start_vr(); , tween(alpha,1); );"
/>
Your question is about dynamically generating hotspots in KRPano from a JSON list.
It is not really clear to me the way you wrote your question if you want to read the JSON from KRPano XML file (let's say FROM KRPano) or if you are expecting to use Javascript to ask KRPano to produce the hotspots.
These are two completly distinct ways of doing it :)
Because I'm lazy and I suppose you want to deal with JSON in JS, I go for this solution...
Loading a JSON file from Javascript
Your KRPano project should look like a core HTML file presenting Javascript to embed the KRPano plugin.
There, you can declare a script content in your HTML in which you will parse your JSON content and you ask KRPano to generate a hotspot. This method should be called when you are sure KRPano is ready, or get it called from KRPano when it is ready, using "onready" attribute.
myHotspotList.json content:
var myHotspotList = [
{
name: "myFirstHotspot",
atv: 15.0,
ath: 56.5686,
url: "myHotspotImage.jpg"
}
];
tour.html content:
<html>
...
<script url="myHotspotList.json'></script>
<script>
function generateHotspots() {
// First, we get the KRPano plugin
var myKRPano = document.getElementById('krpanoSWFObject');
// Now we parse the JSON object
for(var idx in myHotspotList) {
// Get the current Hotspot data
var currHotspot = myHotspotList[idx];
// Ask KRPano to create a hotspot with our current name
myKRPano.call("addhotspot('"+ currHotspot.name +"');");
// Now set various attributes to this hotspot
myKRPano.call("set(hotpost['"+ currHotspot.name +"'].atv, "+currHotspot.atv+");");
myKRPano.call("set(hotpost['"+ currHotspot.name +"'].ath, "+currHotspot.ath+");");
myKRPano.call("set(hotpost['"+ currHotspot.name +"'].url, '"+currHotspot.url+"');");
}
}
</script>
...
// When you ask for pano creation, give your generation method as callback
embedpano({target:"krpanoDIV", onready:generateHotspots});
...
</html>
I hope this help and you got the trick with calling JSON object attributes and all.
Regards
Hi I am just beginning with angular and I am struggling to find the answer to what I'm sure is quite a simple thing to do.
I am currently getting the values of some input boxes and pushing them into my scope. This is creating one long 'array' eg:
['data-1','data-2','data-3']
I would like to format my data in the following way instead
$scope.data = [
{
'header1': 'data1-1',
'header1': 'data1-2',
'header1': 'data1-3'
},
{
'header1': 'data2-1',
'header1': 'data2-2',
'header1': 'data2-3'
}
]
This is my function as it currently is.
$scope.createRow = function(){
angular.forEach(angular.element("input"), function(value, key){
$scope.td.push($(value).val());
});
}
Any help or pointers would be greatly appreciated as I am just getting my head round the angular way
Doing this isn't hard... but before I give you a gun to shoot yourself in the foot, just to say that I think it would be beneficial to explain WHY you want structure in that other format you are mentioning. You seem to have lots of data repetition and that's always a red flag.
Now for the code, you just need to create object before pushing it to the array like:
$scope.createRow = function(){
angular.forEach(angular.element("input"), function(value, key){
var obj = {
"header1": val + "-1",
"header2": val + "-2"
};
$scope.td.push(obj);
});
}
EDIT:
OK, so you are trying to add new row to the table. First of all, you shouldn't be doing angular.forEach, but rather those input elements in HTML should bind to existing scope object, like:
// obviously use better names than Input1Value
// I am here just giving you example
$scope.bindData = {
Input1Value: null,
Input2Value: null
};
// in HTML you will do
// <input ng-model="bindData.Input1Value" />
// <input ng-model="bindData.Input2Value" />
Now that you've eliminated that nasty angular.forEach you need to have some kind of event handler, for example when user clicks the button you want to add this object to the array to which table is data bound. Just be sure to clone the $scope.bindData object when you add it to array.
$scope.createRow = function(){
var newRowData = $scope.cloneObject($scope.bindData);
$scope.td.push(newRowData);
}
// http://heyjavascript.com/4-creative-ways-to-clone-objects/
// https://stackoverflow.com/questions/728360/most-elegant-way-to-clone-a-javascript-object
$scope.cloneObject = function(objToClone) {
var newObj = (JSON.parse(JSON.stringify(objToClone)));
}
To close this answer off - keep in mind, if you ever find yourself directly referencing HTML DOM elements in Javascript with AngularJS - you are doing something wrong. It's a nasty habit to eliminate, especially if you are coming from jQuery background (and how doesn't?), where everything is $("#OhHiThere_ElementWithThisId).
Obviously the main thread on this topic on StackOverflow is this one:
“Thinking in AngularJS” if I have a jQuery background?
However I find that it's too theoretical, so Google around and you may find better overviews like:
jQuery vs. AngularJS: A Comparison and Migration Walkthrough
Is this possible.. here's what I have atm, but my data object is just returning a load of jargon, what am I doing wrong? Am I doing anything.. right, for that matter?
I basically want to print out a list of a users videos (thumbnail and title, and make each one a clickable link to the video itself)
Thanks!
$(document).ready(function(){
$player.init();
})
var $player = (function(){
var player = {};
player.init = function(){
//init Youtube knockout
player.initYoutubeKnockout();
}
player.knockoutModel = {
videoData : ko.observableArray([]),
}
player.initYoutubeKnockout = function()
{
//load the Youtube json feed
$.ajax({
url: 'http://gdata.youtube.com/feeds/api/users/USERNAME/uploads?v=2&alt=json',
type: 'GET',
dataType: 'jsonp',
data: {
count: 5
},
success: function(data, textStatus, xhr) {
player.doYoutubeKnockout(data.item);
}
});
}
player.doYoutubeKnockout = function( data )
{
player.knockoutModel.videoData(data);
ko.applyBindings(player.knockoutModel, $('#youtube-feed')[0]);
console.log($(this));
}
return player;
})();
Frankly you weren't doing much at all.
The JSON data you get back from YouTube is not from data.item, it's in a completely different structure.
I'm assuming you wish to get 5 uploads from the user. The parameter name would be max-results, not count.
Probably the only thing you did fine was set up the url but that's about it.
You need to examine how the JSON returned looks like. Check the API reference for the structure of an atom feed. This is in XML but the corresponding JSON responses will have pretty much the same format with some minor differences. Examine the object by writing it to the console to verify you're getting the right properties.
Once you understand that, you need to use the correct query to get what you're expecting. Check out their API reference on their query parameters.
To help simplify your knockout code, I would strongly recommend you take the response you get back and map it to an object with simplified property names. For instance, to get the thumbnails for an entry, you would have to access the media$group.media$thumbnail array. It would be easier if you can just access it through thumbnail.
Also, if your elements you are binding to need to bind multiple values, it would help to map the values in such a way that your bindings are made easier. For instance, when using the attr binding, you'd set up a property for each of the attributes you want to add. Instead you could just group all the properties in an object and bind to that.
I wrote up a fiddle applying all that I said above to do as you had asked for. This should help give you an idea of what you can do and how to do it.
Demo
I have a form where I select the number of items. Upon clicking submit, it should take me to a new page where it would display the item selected and depending on the number of items selected, it would create those many jqPlots, one for each item.
Any suggestions on how do I go about doing this?
Thanks,
S.
It's hard to give any specifics without more detail about the items, but basically you would pass a JSON structure to your view with the items to be plotted. Then you would loop through the JSON structure, creating DIV tag for each item to be plotted and appending the DIV tags to the body.
The Javascript part would look something like this:
$.each(items, function(index, value) {
$myPlot = $("<div>");
$myPlot.attr("id", "item"+index);
$.jqplot($myPlot.attr("id"), ...);
$("body").append($myPlot);
});
This question is very general, but answering (specifically and only) the question of loading multiple charts:
You need a unique HTML div id for each chart; consider using an RFC 4122 UUID (generate as needed) for each chart/div rather than a sequential index for each. Use something that looks like this as a placeholder div for each:
<div class="chartdiv" id="chartdiv-${UID}">
<a rel="api" type="application/json" href="${JSON_URL}" style="display:none">Data</a>
</div>
This embeds the JSON URL for each div inside it, in a hidden hyperlink that can be discovered by JavaScript iterating over your multi-chart HTML page.
The matter of the UUID is inconsequential -- it just seems the most robust way to guarantee a unique HTML id addressable by JavaScript for each chart.
Subsequently, you should have JavaScript that looks something like:
jq('document').ready(function(){
jq('.chartdiv').each(function(index) {
var div = jq(this);
var json_url = jq('a[type="application/json"]', div).attr('href');
var divid = div.attr('id');
jq.ajax({
url: json_url,
success: function(responseText) { /*callback*/
// TODO: responseText is JSON, use it, normalize it, whatever!
var chartdata = responseText;
jq.jqplot(divid, chartdata.seriesdata, chartdata.options);
}
});
});
});