Wait for data to load - javascript

I am trying to add a custom tweet button on my angular app. Here is the code I use to do it:
HTML:
<a href="" class="retweet" retweet target="_blank" data-info="{{ data.name }}">
Tweet
</a>
JS:
myApp.directive('retweet', function(){
return function(scope, elm, attrs){
var API_URL = "http://cdn.api.twitter.com/1/urls/count.json",
TWEET_URL = "https://twitter.com/intent/tweet";
elm.each(function() {
var elem = $(this),
// Use current page URL as default link
url = encodeURIComponent(elem.attr("data-url") || document.location.href),
// Use page title as default tweet message
text = elem.attr("data-info") || document.title,
via = elem.attr("data-via") || "",
related = encodeURIComponent(elem.attr("data-related")) || "",
hashtags = encodeURIComponent(elem.attr("data-hashtags")) || "";
console.log(elem.attr("data-job"));
// Set href to tweet page
elem.attr({
href: TWEET_URL + "?hashtags=" + hashtags + "&original_referer=" +
encodeURIComponent(document.location.href) + "&related=" + related +
"&source=tweetbutton&text=" + text + "&url=" + url + "&via=" + via,
target: "_blank",
onclick: "return !window.open(this.href, 'Google', 'width=500,height=500')"
});
});
}
})
My problem here is that the js fetch the data before the data is even loaded in the page. Therefere the "text" variable is set to {{ data.test }} rather than the actual data which gets loaded later on the page.
How can I make sure the data is loaded on time?
Many thanks

You can use ng-cloak to prevent rendering uncompiled data:
<a href="" class="retweet" retweet target="_blank" data-info="{{ data.name }}" ng-cloak>
Tweet
</a>
You can read more about this here: http://docs.angularjs.org/api/ng/directive/ngCloak

Can you try to use $scope.data.name directly instead of elem.attr("data-info")?
Or you can add the expression as a property:
<a href ... data-info="$scope.data.name">
And use it like this:
scope.$eval(attrs.dataInfo);

Related

jQuery dynamically add content to div

What I'm trying to do is add for each items in a xml file their content to a html page. I'm trying to make it so that every item content is inside an <article> tag. However, It's my first time using jQuery and my end result is not what I want.
let $items = $(xmlContent).find("item");
$items.each(function() {
let title = $(this).find('title').text();
let date = $(this).find('pubDate').text();
let link = $(this).find('link').text();
let guid = $(this).find('guid').text();
let photo = $(this).find('media').html();
$("#world").append("<article></article>", [$("<a>", {
href: link
}) + ("<h3>" + title + "</h3>")]);
This is what the end result currently is:
<article></article>
[object Object]
<h3>Students Fainting From Hunger in Venezuela’s Failing School System</h3>
And what I want it to become:
<article> <a href= myLink <h3>Students Fainting From Hunger in Venezuela’s Failing School System</h3> </a> </article>
I want to apply my link so that everywhere the user click on the content it goes to the link. Hopefully you can guide me. Thanks!
You can build your article element step by step.
Create 'article' as an element, then create your 'a' element. Append the 'h3' element to the 'a' element before appending 'a' to 'article', and then 'article' to '#world'.
let article = $("<article></article>")
let a = $("<a></a>", {href: link})
a.append("<h3>" + title + "</h3>")
article.append(a)
$("#world").append(article)
You're not using append as described in the documentation -- see the type of arguments you can pass.
Maybe you intended this:
$("#world").append(
$("<article>").append(
$("<a>", { href: link }),
$("<h3>").text(title)
)
);

angular directive , how is directive magically rendered when I do not see a call to it?

in a Directives.js file I see the following code
app.directive('arpLink', function ($http) {
return {
scope: {
link: '=',
className: '#cl'
},
replace: true,
template:
'<span ng-click="clicked()">' +
'<a class="{{ className }}" target="_blank" ng-href="{{ link.url }}">{{ link.title }}</a>' +
'</span>',
link: function (scope, el, attrs) {
scope.clicked = function () {
if (this.link !== undefined && this.link.id !== undefined) {
$http.put('api/links/' + this.link.id, { hitcount: true });
}
};
}
};
});
This ends up displaying a link button on the home page in which I want to remove this button link , normally I would simply delete a line or two of code in other web applications.
I see that in chrome that code does render out to
<span ng-click="clicked()" cl="btn-blue btn-large" arp-link="" link="link" class="ng-isolate-scope"><a data-blah="adf" class="btn-blue btn-large" target="_blank" ng-href="http://eso/docold/" href="http://eso /docold/">Old DOC Home Page</a></span>
<a class="btn-blue btn-large" target="_blank" ng-href="http://eso/docold/" href="http://eso/docold/">Old DOC Home Page</a>
I don't see any files when searching that even call the directive "arpLink"
How is this directive called and how can I stop it from being called?
It's called using the attribute shown in the markup arp-link
The name of the directive is a camelCase version of that attribute.
Directives can be implemented using class, attriute, element and even an html comment
<div class="arp-link"></div>
<arp-link></arp-link>
<div arp-link></div>
<!-- arp-link -->
The restrict option can be used to define which method would reference specific directive you register
To stop it , don't include the directive declaration and/or remove the attribute. Removing only one of them will have no adverse impact...the directive will just never be invoked

Append HTML in angular js giving errors

I am a newbie in angularjs and was trying to append the data in the view on click event.
The following is the code I have written:
Html
<div id="space-for-buttons">
<input type="hidden" id="hdnTopRatedPage" value="0" ng-update-hidden>
<div class='item' ng-repeat='p in programs.rated' home-tab-item watchable="p" ></div>
</div>
<div class = 'rated-spin' ng-show = 'programs.rated == 0 && ratedLoaded == false'> </div>
<div ng-show="programs.rated == 0 && ratedLoaded == true" class="noResultsBlock">No Results for Rated.</div>
<div class='clearfix'></div>
<div ng-controller="MainCtrl" ng-app="woi">
<yes style='background-color: brown;padding-right: 61px;'></yes>
</div>
Directive:
var pageno=1;
function MainCtrl($scope) {
$scope.count = 0;
}
//Directive that returns an element which adds buttons on click which show an alert on click.Here we can put
woi.directive("yes",['userAPI','$rootScope', function(userAPI,$rootScope){
return {
restrict: "E",
template: "<a ng-click='str()' addbuttons>please click on me</a>"
}
}]);
//Directive for adding buttons on click that show an alert on click
woi.directive("addbuttons",['$rootScope','userAPI','$compile', function($rootScope,userAPI,$compile){
return function(scope, element, attrs){
element.bind("click", function(){
scope.count++;
alert("hII")
//var abc= scope.loadRated(pageno);
userAPI.topRated({userid: $rootScope.getUser().userid}, function (r, $scope, div){
if(!$rootScope.device.isMobile && !$rootScope.device.isTablet && !$rootScope.device.isTouch ) {
var topRatedList = r.gettopratedhomepage.topratedprogrammelist;
console.log(r)
var str='';
for(var i=0;i<topRatedList.length;i++)
{
// str+="topRatedList[i].actualname";
var programNameEncode= topRatedList[i].programmename // | encodeUrl;
var program=topRatedList[i].programmename;
var channelId=topRatedList[i].channelid;
var programId=topRatedList[i].programmeid;
var channel=topRatedList[i].channeldisplayname;
var channelNameEncode=topRatedList[i].channeldisplayname //| encodeUrl;
var startTime=topRatedList[i].starttime;
var favourite=topRatedList[i].isfavorite;
var reminder=topRatedList[i].isreminder;
var watchlist=topRatedList[i].iswatchlist;
var duration=topRatedList[i].duration;
var imageFile=topRatedList[i].imagefilepath;
var startTime= topRatedList[i].starttime;
var duration= topRatedList[i].duration;
var isReco=topRatedList[i].isrecommended; // This is for reco
str+=" <div class='item'>" ;
str+="<div class=\"thumb\">";
// str+="<div ng-show=\""+isReco=='1'+"\" class=\"favorite-ribbon\"></div>";
str+="<div class=\"player\"></div>";
str+="<div class='image' style='background-image:url('"+imageFile+"');'>";
str+="<img src='"+imageFile+"'/>";
str+="<a ng-click=\'playVideo("+program+"\,$event)' ng-show='hasVideo()' class='play' style='cursor:pointer'></a>";
str+= "<a ng-href=\"#!/program/"+programNameEncode+"\" ng-show=\"!hasVideo()\" class=\"noPlay\" ng-click=\"EncodeUrlWithDash("+program+",$event,'programme',"+channelId+","+programId+","+startTime+")\"></a></div>";
str+="<span class='time' ng-show='duration'>\""+duration+"\"</span>";
str+="<div class='user-actions' ng-controller='UserController'>";
str+="<a live-tooltip='Add to Favorite' ng-click='toggleFavorite(p, $event)' class='btn btn-small btn-purple-blue' ng-class=\""+{active:favourite == '1'}+"\>";
str+="<i class='icon-favorite'></i></a>";
str+="<a live-tooltip='Reminder Alerts' ng-click='toggleReminder(p, $event)' class='btn btn-small btn-purple-blue' ng-class=\""+{active:reminder == '1'}+"\>";
str+="<i class='icon-reminder'></i></a>";
str+="<a live-tooltip='Add to Watchlist' ng-click='addToWatchlist(p, $event)' class='btn btn-small btn-purple-blue' ng-class=\""+{active:watchlist == '1'}+"\>";
str+="<i class='icon-watchlist'></i></a></div>"; //end of user controller div
str+="</div>"; // end of thumb div
str+="<div class='text-wrapper'>";
str+="<h2 multiline-overflow><a title='"+program+"' href='#!/program/"+programNameEncode+"' ng-click=\""+"EncodeUrlWithDash("+program+",$event,'programme',"+channelId+","+programId+","+startTime+")"+"/ >\""+program+"\"</a></h2>";
str+="<p class='infoChannel' live-tooltip-single-line= '{{channel}}'><a href='#!/channel/"+channelNameEncode+"' ng-click=\""+"EncodeUrlWithDash("+channel+",$event,'channel',"+channelId+","+programId+")"+"/>\""+channel+"\"</a></p>";
str+="<p class='info'>\""+startTime+"\"</p>";
str+="</div></div>"; //end of the main div
//EXTRA LINE
// str+=" <div class='item' ng-repeat='topRatedList[i] in programs.rated' home-tab-item watchable='topRatedList[i]' ></div>" ;
alert("The below value is of str")
alert(str);
angular.element(document.getElementById('space-for-buttons')).append($compile(str)(scope));
}
alert("The below value is of str")
// The above code is required to append data into the division(loadrated)..
}
});
});
};
}]);
however the code is running properly(ie it goes through the entire directive)..But data is not displayed ie appending.
Instead it goes into another directive which I have called hometab directive and giving issues.
I dont know why this is happening.
Please help me out
It would be much easier for you to create a Plunker for this issue here
Concerning your directive, without having full access to your files, it is considered good practice to hold all functionality and styles within the scope of it. Therefore, the only thing that should be in the HTML is the directive element only. Everything else, should thus be within the directive js.
Just as well, your ng-show/hide have very intensive expressions within them. I would try and chop'em down a bit. Additionally, the HTML syntax with quotes are using " " in some instances and ' ' with mixed spaces in others.
I have seen this throw errors in the past, though it is valid to use single or double. The preferred usage is the double quotes "" on everything in HTML and single quotes for JS files. I would just make sure you are using one or the other and not both.
You can check this article about the specific rules here

Fancybox will not use content passed via javascript

Using jquery 1.10.2, fancybox 2.1.5
I'm trying to pass fancybox the "content: data" via javascript but its not working. Yet if I console.log the data variable it shows me valid HTML/text, but fancybox refuses to use it.
<div class="item">
<h4 class="choice">launch modal</h4>
<div class="detail">
This should show up in my <b>fancybox</b>!
</div><!--.detail-->
</div><!--.item-->
$('.choice').each(function(i, elem){
$(elem).siblings('.detail').wrap('<div style="display:none"></div>');
});
$(".choice").fancybox({
maxWidth: 800,
content: 'replace this text',
beforeShow: function(){
var title = $(this.element).text();
var data = $(this.element).parent().find('.detail').html();
console.log('this=' + this + ' | title=' + title + ' | data=' + data);//DEBUG
this.content = data;
}
});
The console log shows clearly that its got the data html content, but fancybox refuses to use it. I've wrapped it in another div with display:none since their site says to do that for whatever reason.
To build your content inside the callback, use afterLoad instead, otherwise the content option will have preference over this.content within any other callback :
$(".choice").fancybox({
maxWidth: 800,
content: 'replace this text',
afterLoad: function () {
var title = $(this.element).text();
var data = $(this.element).parent().find('.detail').html();
console.log('this=' + this + ' | title=' + title + ' | data=' + data); //DEBUG
this.content = data;
}
});
See JSFIDDLE
Note: you can also build/replace the title as in your code above like this.title = title;

How to read additional data within handlebars block expression template?

My html document will have div container which gets populated with handlebars template name 'relatedVideosTemplate' on execution.
<div id="relVideos"></div>
Below anonymous function will make ajax request and pass the data to handlebar template which loops over all items in data object to construct related videos UI.
(function(options) {
var defualt = {
defaultThumb: "/url/to/default/thumbnail/",
apiURL: '/path/to/api/url'
};
options = options || {};
options = $.extend(true, defaults, options);
// handlebars template for the related video carousel
var relatedVideosTemplate : "<h3>Related Videos</h3>" +
"<ul class=\"related-videos\">" +
"{{#foreach items}}<li class=\"video {{#if $last}} last{{/if}}\">" +
"<a href=\"/video/?videoid={{id}}\" class=\"image\">" +
"<img alt=\"{{name}}\" {{#if videoStillURL}}src=\"{{videoStillURL}}\"{{else}}src=\"{{defaultVideoThumb}}\"{{/if}} width=\"90\" height=\"75\" data-id=\"{{id}}\" onerror=\"this.src='{{defaultVideoThumb}}';\" />" +
"<span class=\"video-time\">{{length}}</span></a>" +
"<div class=\"info\"><h5>{{name}}</h5>" +
"<span class=\"published-date\">{{publishedDate}}</span>" +
"{{#if playsTotal}}<span class=\"video-views\">{{playsTotal}} views</span>{{/if}}" +
"</div></li>{{/foreach}}" +
"</ul>",
template, relVideosHTML;
$.ajax({
url: options.apiURL,
success: function(data) {
template = Handlebars.compile(relatedVideosTemplate);
relVideosHTML = template(data);
$("#relVideos").html( relVideosHTML );
}
});
});
Its very likely the video still image (thumbnail) for some videos will return 404 and in that case I use onerror event on image tag to replace it with default thumbnail.
Is there a way to pass this default thumbnal value as object to handlebars block expression template ?
I don't want to amend the data object to have 'defaultThumb' property for all items. Like below...
for ( i = 0, max = data.items.length; i < max; i++) {
// Adding new property to each item in data object
data.items[i].defaultThumb = options.defaultThumb;
};
It seems to me amending data property in above loop is non efficient as the defaultThumb is same across all videos which return 404 for still(thumb) image.
Why not set defaultVideoThumb once at the top level and then reference it as {{../defaultVideoThumb}} inside the loop? Something like this in the template:
<img
{{#if videoStillURL}}src="{{videoStillURL}}"{{else}}src="{{../defaultVideoThumb}}"{{/if}}
width="90" height="75"
onerror="this.src='{{../defaultVideoThumb}}'
>
and then in the JavaScript:
data.defaultVideoThumb = '...';
var html = template(data);
Demo: http://jsfiddle.net/ambiguous/9ecx3/

Categories

Resources