one json-request to multiple DOM-destinations - how? - javascript

I'm having a "list" that I want to populate with a background-json request.
Items have different headings and traffic should be minimal (mobile webapp),
DOM-structure something like:
<div id="deckStart">
<div id="cardContacts">
<h2>Contacts</h2>
<div id="cardContactsContent">nothing here until JSON</div>
</div>
<div id="cardTodo">
<h2>To do</h2>
<div id="cardTodoContent">nothing here until JSON</div>
....
//EDIT
OK, this works:
x$(window).on('load', function() {
x$(window).xhr('json.txt', {
async: true,
callback: function() {
var t = eval('(' + this.responseText + ')');
for(var key in t) {
var obj = t[key];
x$('#' + key).html('inner',obj);
}
}
});
but why doesn't JSON.parse work on chrome? Eval seems dirty..
//end edit
What would be the most efficient way to populate the respective content-divs with one single JSON-request?
Temp load into JS-array?
Temp load into hidden DOM-part?
Some regexp-trick or other I cannot think of?
The network stability / speed is unreliable.
regards,

Can you get jQuery on there? You could do it in a heartbeat with jQuery...

Related

How to use localStorage value filter in ng-repeat

I've set a value when the user click vote choice. Its working.
.then(function(response) {
localStorage.setItem('isClicked', 'Yes');
var i = +localStorage.key("nid");
var nidId = 'nid' + localStorage.length;
localStorage.setItem(nidId, vm.nid);
vm.clickedBefore = true;
})
This is my HTML scope:
<div class="card myfunc" ng-repeat="myfunc in myfuncPage.myfuncs" id="{{myfunc.nid}}" >
<div class="item item-text-wrap">
<h2 class="item-icon-left"><i class="icon ion-ios-analytics"></i>
{{myfunc.title}}</h2>
</div>
<div class="item item-text-wrap" ng-show="localstorage">
<img ng-src="{{myfunc.field_image.und[0].imgPath}}"/>
<p class="custom-class" ng-bind-html='myfunc.body.und[0].value'>
</p>
<ul ng-repeat="vote in myfunc.advmyfunc_choice">
<li ng-repeat="voteselect in vote">
<div class="row">
<button class="col button button-outline button-dark" ng-click="myfuncPage.sendNid(myfunc);myfuncPage.sendVote(voteselect);showVoted = ! showVoted" >{{voteselect.choice}}</button>
<div class="voted-screen" ng-show="showVoted">
<h3>Thanks.</h3>
</div>
</div>
</li>
</ul>
</div>
</div>
In basically, I need remember the div via localStorage and when the page refresh, hide choice divs.
ng-show="showVoted" working on click but I need on refresh.
What is the best way to do it? Thanks.
I am not sure what local storage module you are using, so I can't be specific, but I would write factory that handles the retrieval and storage of the values you need
(function () {
var voteFactory = function (localStorage) {
return {
getVote: function (key) {
var isVoted = false;
// get local storage item, set voted etc
var voted = localStorage.getItem(key);
if(voted) {
isVoted = voted;
}
return isVoted;
},
setVote: function(key, value) {
localStorage.setItem(key,value);
}
};
};
app.factory('voteFactory', ['localStorage', voteFactory]);
})();
Then within the scope controller/directive you are using to show or hide you would have a function:
$scope.showVoted = function(key) {
return voteFactory.getVote(key);
}
then ng-show="showVoted(theidentifieryouwantouse)"
It is also worthwhile to mention I would use ng-if instead of ng-show. To be more efficient you could store your votes as an array instead of individual values and do a check to see if you have retrieved all values, get from local storage if not. Then your functions would interrogate retrieved array instead of repeated calls to local storage. I would also advice maybe using a promise in the factory because retrieval from local storage could be delayed causing some ui oddities.
Hopefully this is along the lines of what you are looking for. I can elaborate if needed.

Knockout.js: combining "visible" and multiple view models

I have spent some time trying to unscramble this issue. I have a page that I would like to be used by a beauty salon owner to manage two things:
Appointments
Days with special schedule
To select a 'view' I am using a toggle that is based on Knockout's visible binding:
So when a radio button is clicked a div is being rendered and another hidden:
<div id="selectingScopes" class="col-xs-6 col-md-4">
<fieldset>
<legend>View:</legend>
<div id="radioControls" class="switch-toggle well">
<input jsf:id="appointmentsRadio" name="appointmentsRadio" type="radio"
data-bind="checked: selectedScope" value="#{bigcopy.appointmentsLabel}"/>
<label for="appointmentsRadio" onclick="">#{bigcopy.appointmentsLabel}</label>
<input jsf:id="specialdaysRadio" name="specialdaysRadio" type="radio"
data-bind="checked: selectedScope" value="#{bigcopy.specialDaysLabel}"/>
<label for="specialdaysRadio" onclick="">#{bigcopy.specialDaysLabel}</label>
<a class="btn btn-primary"></a>
</div>
</fieldset>
</div>
<div id="appointmentsModel" class="row" data-bind="fadeVisible: selectedScope()==='#{bigcopy.appointmentsLabel}'">
<ui:include src="includes/appointmentsManagement.xhtml"/>
</div>
<div class="row" data-bind="fadeVisible: selectedScope()==='#{bigcopy.specialDaysLabel}'">
<ui:include src="includes/specdaysManagement.html"/>
</div>
In the same time I want to bind the "appointmentsModel" div above to a different view model that will be responsible only for managing the table of appointments that have to be uploaded from the server. This is the js file sifted of irrelevant clutter:
var restServiceRoot = "localhost:8080/RimmaNew/rest";
var scopeSelector = {
selectedScope: ko.observable()
};
ko.applyBindings(scopeSelector);
//appointments part
//Initial load
function appointmentsModel() {
var self = this;
self.serviceURL = restServiceRoot + "/appointments";
self.Appointments = ko.observableArray([]);
$.ajax({
url: self.serviceURL,
type: 'get',
data: null,
dataType: 'json',
success: function (appointments) {
var parsed = JSON.parse(appointments);
var appointmentsArray = parsed.current;
var mappedAppointments = $.map(appointmentsArray, function(item){
return new Appointment(item);
});
self.Appointments(mappedAppointments);
},
error: function (xhr, ajaxOptions, thrownError) {
var err = xhr.responseText;
alert(err);
}
});
}
var appointmentsModelImpl = new appointmentsModel();
ko.applyBindings(appointmentsModelImpl, document.getElementById('appointmentsModel'));
My code is inspired of two books: Knockout.js (O'Reilly - Jamie Munro) and Java EE and HTML 5 Enterprise Application Development (Oracle Press) that barely touch upon the topic of having cross-bindings in KO. I equally didn't find official KO documentation to be helpful in this endeavor.
There is a stackoverflow ticket that dealt with a similar issue, but in one it was the author who answered himself - his explanation made perfect sense to himself, but the mentions of 'stopBinding' and 'controlsDescendantBindings' seemed taken out of context to the two bindings that he uses below...I can't see how to apply this to my problem...
So you would make me a huuge favor if you could either
direct me to a resource where I could educate myself on how to use cross-bindings in KO
Or guide me in how can I mend my code to be able to control the visibility of these two divs and apply a viewmodel to each of them
Doing both would be fantastic.
1 The full code for the original page (xhtml) is here
2The js file
3The js 'classes' file
4The enclosed page with the 'appointments' table
Your best bet will probably be to think of your models a little bit differently. Instead of doing a separate model binding, it may make more sense to do a default appointmentsModel, then update the observables inside that.
What I would do is have a single parent binding to the body, or a containing div in the body, then submodels for the various children.
Sample JS:
var MyParentModel = function(){
var self = this;
self.selectingScopes = {
scope: ko.observable("");
};
self.appointmentModel = {
param1: ko.observable(),
param2: ko.observable()
}
};
ko.applyBindings(new MyParentModel());
Sample HTML:
<div id="appointmentsModel" data-bind="with: appointmentModel"></div>

How do you apply an item, from a list of results, to the parent Div tag for the current object?

I am trying to build a function for inserting the number of Facebook Likes into a Div tag. So far, I have a script that can get the URL from a Div tag which is inside of another Div tag called 'entry' and then have the .getJSON() method retrieve the number of Facebook likes for each entry.However, I can't get each retrieved value of Facebook Likes to insert into a Div tag for each entry. Please note, I simplified my code to where it alerts each Facebook Like value. This is what I have so far:
<div class="entry">
<div class="fburl">https://graph.facebook.com/zombies</div>
<div class="facebook-likes"></div>
</div>
<div class="entry">
<div class="fburl">https://graph.facebook.com/starwars</div>
<div class="facebook-likes"></div>
</div>
And here's my jQuery:
$(document).ready(function(){
$(".entry").each(function() {
var fbURL = $(this).find(".fburl").html();
$.getJSON(fbURL, function(fbData) {
var fbArr = fbData['likes'];
alert(fbArr);
});
});
});
​So what I am trying to do is iterate through each entry, get the Open Graph URL for it, retrieve the Likes value, and then insert it into the appropriate Div tag, so the code should render as:
<div class="entry">
<div class="fburl">https://graph.facebook.com/zombies</div>
<div class="facebook-likes">2,586 Likes</div>
</div>
<div class="entry">
<div class="fburl">https://graph.facebook.com/starwars</div>
<div class="facebook-likes">8,905,721 Likes</div>
</div>
​
​
$(document).ready(function() {
$('.entry').each(function() {
var $this = $(this),
fbURL = $this.children('.fburl').html();
$.getJSON(fbURL, function(fbData) {
$this.children('.facebook-likes').html(fbData['likes'] + ' Likes')
});
});
});
See: http://api.jquery.com/children
Demo: http://jsfiddle.net/9EALz/2/
Note: Using children() is going to be marginally more efficient than using find() as it limits the DOM traversal to a single level ( http://jsperf.com/find-vs-children/13 ). Cashing the jQuery object $(this) via var $this = $(this) is also slightly more efficient as it prevents unnecessary selector interpretation ( http://jsperf.com/jquery-cache-vs-no-chace ).
You may want this
$(document).ready(function(){
$(".entry").each(function() {
var entry=$(this), fbURL=$(".fburl", entry).html(),
el=$('.facebook-likes', entry);
$.getJSON(fbURL, function(fbData) {
el.html(numberWithCommas(fbData['likes'])+" Likes");
});
});
});​
A thousand separator function from here
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
DEMO.
Update:
Alternatively you can use this too (using data-attribute) without an extra div for fburl, i.e.
<div class="entry">
<div data-fburl="https://graph.facebook.com/zombies" class="facebook-likes"></div>
</div>
JS
$(".entry").each(function() {
var entry=$(this), fbURL = $(".facebook-likes", entry).attr('data-fburl'),
el=$('.facebook-likes', entry);
$.getJSON(fbURL, function(fbData) {
el.html(numberWithCommas(fbData['likes'])+" Likes");
});
});

Using Shoutcast, Display Now Playing Album Art

I have a small 70x70 box in an HTML player I built where I wish to place in the album artwork to coincide with my now playing information from my shoutcast server. Is there a way, using the artist-song information the shoutcast server provides, that I can search a web service (amazon/last.fm) and have it place the (most likely) album cover there?
Here is the JS code I'm using now:
jQuery(document).ready(function() {
pollstation();
//refresh the data every 30 seconds
setInterval(pollstation, 30000);
});
// Accepts a url and a callback function to run.
function requestCrossDomain( callback ) {
// Take the provided url, and add it to a YQL query. Make sure you encode it!
var yql = 'http://s7.viastreaming.net/scr/yql.php?port='+port+'&username='+user+'&callback=?';
// Request that YSQL string, and run a callback function.
// Pass a defined function to prevent cache-busting.
jQuery.getJSON( yql, cbFunc );
function cbFunc(data) {
// If we have something to work with...
if ( data ) {
// Strip out all script tags, for security reasons. there shouldn't be any, however
data = data[0].results.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
data = data.replace(/<html[^>]*>/gi, '');
data = data.replace(/<\/html>/gi, '');
data = data.replace(/<body[^>]*>/gi, '');
data = data.replace(/<\/body>/gi, '');
// If the user passed a callback, and it
// is a function, call it, and send through the data var.
if ( typeof callback === 'function') {
callback(data);
}
}
// Else, Maybe we requested a site that doesn't exist, and nothing returned.
else throw new Error('Nothing returned from getJSON.');
}
}
function pollstation() {
requestCrossDomain(function(stationdata) {
var lines = stationdata.split('|+|');
jQuery('#sname').html(lines[0]);
jQuery('#sgenre').html(lines[1]);
jQuery('#clisteners').html(lines[2]);
jQuery('#bitrate').html(lines[3]);
jQuery('#artist_block').html('' + jQuery.trim(lines[4]) + '');
var prev = lines[5].split('+|+');
jQuery('#np_table').html('');
for (var i = 0; i < 8; i++)
{
if(typeof(prev[i]) != 'undefined')
{
jQuery('#np_table').append('<tr>'+'<td>'+ prev[i] + '</td>'+'</tr>');
jQuery("tr:odd").css("background-color", "#154270");
}
}
jQuery('#mplayers').html(lines[6]);
jQuery('#mobile').html(lines[7]);
jQuery();
} );
}
and here's the HTML:
<div id="col_left">
<div id="now_playing">
<div id="np_ribbon"><span>Now Playing</span></div>
<div id="np_img"><img name="nowplayingimage" src="" width="70" height="70" alt="album cover" style="background-color: #000000" /></div>
<div id="artist_block">
<span class="artist_name"><strong>Artist:</strong> Artist name</span><br />
<span class="song_name"><strong>Song:</strong> "song title"</span><br />
<span class="album_name"><strong>Album:</strong> Album Name</span> <br />
</div>
<div id="player">
<div id="container"><script type="text/javascript" src="http://shoutcast.mixstream.net/js/external/flash/s7.viastreaming.net:8790:0:::999999:::1"></script></div>
</div>
</div><!-- end now playing -->
<div id="recent">
<div class="table_title">Recently Played</div>
<table id="np_table">
</table>
</div><!-- end recent -->
</div><!-- end col_left -->
So naturally, I want the image to appear where the div "np_img" is. Any ideas what code to use and how to implement it. You can probably tell by my code that I'm an amateur so please be clear and gentle. :)
You can use the iTunes search API. It supports JSONP so you can use it directly within your webpage, without worrying about cross-domain.
As #Brad mentioned, iTunes has terms of use. In particular:
(...) provided such Promo Content: (i) is placed only on pages that promote
the content on which the Promo Content is based; (ii) is proximate to
a "Download on iTunes" or "Available on the App Store" badge (as
approved by Apple) that acts as a link directly to pages within iTunes
or the App Store where consumers can purchase the promoted content. (...)
Here's how the code looks like:
​function refreshArtwork(artist, track) {
$.ajax({
url: 'http://itunes.apple.com/search',
data: {
term: artist + ' ' + track,
media: 'music'
},
dataType: 'jsonp',
success: function(json) {
if(json.results.length === 0) {
$('img[name="nowplayingimage"]').attr('src', '');
return;
}
// trust the first result blindly...
var artworkURL = json.results[0].artworkUrl100;
$('img[name="nowplayingimage"]').attr('src', artworkURL);
}
});
}

HTML Node Map Generator?

Alright, what I'm looking for is something that could generate a graphical tree-style map of a web pages nodes.
So essentially it could theoretically transform something like this:
<aside id="leftCol">
<section class="container">
<header class="child1">
<hgroup>
<h1 class="title">Demo Project</h1>
<h3 class="subTitle">WEBSITE 2011</h3>
</hgroup>
</header>
<div class="child2" id="thisDiv">
<div class="subChild1">
<div class="anotherChild1"></div>
<div class="anotherChild2"></div>
<div class="anotherChild3"></div>
</div>
<div class="subChild2">
<p>Some Text</p>
</div>
</div>
<footer class="child3">
Link to project here
</footer>
</section>
</aside>
(This would of course be inside the HTML and BODY tags but for the sake of an example I'm going to use a snippet from my portfolio page with some generated text)
Into something like this:
Example http://www.deviantart.com/download/287437946/node_map_by_wild_fire126-d4r4sje.png
There's absolutely no design thought put into this so don't criticize it, purely for the example purpose. I made this image in photoshop quickly just to illustrate exactly what I'm talking about. All of this could be easily generated with CSS for the most part. It does not by any means have to be this graphical but for the sake of me being bored, it is.
I'm looking for a plugin or a piece of software that can do this for me. I would prefer that it would generate this map in HTML or as an image. I guess any map type would be okay as long as it would be easy to follow.
As a last resort if I can't find quite what I'm looking for I might end up just writing it myself, if that happens, I would be happy to be looking for some people to help with the coding of the plugin.
You could retrieve all children of a certain element and return their tag, class, id and depth. Then you can get creative with css to create a visual tree. Something like this should work. Example at http://jsfiddle.net/elclanrs/UHbMa/.
jQuery plugin:
$.fn.buildTree = function() {
var tree = {};
this.find('*').andSelf().each(function(i, v) {
var parents = $(this).parents().length - 1;
for (var i = 0; i < parents; i++) {
tree[v.tagName.toLowerCase()] = {
id: v.id,
className: v.className,
depth: i
}
}
});
return tree;
};
And then you call it like:
var tree= $('aside').buildTree(),
html = '';
for (tag in tree) {
html += '<p><strong>Tag:</strong> ' + tag +
' | <strong>Class:</strong> ' + tree[tag].className +
' | <strong>Depth:</strong> ' + tree[tag].depth;
}
$('#tree').append(html);
Graphviz is a nice tool for doing such a thing.
You could use a piece of Javascript to generate a Graphviz file and generate a png with the tool.
The javascript should recursively visit all Elements and Generate unique IDs for every Element and write them out in the fairly easy to understand Graphviz format.
Here's a Bookmarklet to convert a page to the Graphviz format.
javascript:void((function() {var f = function(pid, e) { var id = "id" + Math.round(Math.random()*1000000), c = e.childNodes, r = id+'[label="'+(e.tagName ? e.tagName : e.nodeValue.replace(/[\n\r]+/g," "))+'"];\n'; for(var i = 0; i < c.length; i++) { r+=f(id, c[i]); }; if(pid) {r += pid + "->" + id + ";\n";}; return r;}; document.body.innerText = "digraph {\n" + f(false, document.getElementsByTagName("html")[0]) + "}"})())
Here's a quick workthrough to the format: http://www.orient-lodge.com/node/3408
Then generate a png file: (example works under Unix)
dot -Tpng < graph.dot > g.png
There's a Javascript Renderer for Graphviz, too. Canviz I haven't tried it yet, but looks promising.

Categories

Resources