Modify text with jQuery for dynamically added elements in DOM - javascript

I have a page http://www.projectdemocracy.in/ where some elements are dynamically added (example - CSS class ".fyre-comment-count" showing "X Comment").
I wanted to modify the text once page is loaded.
I was able to change the text using console of jQuery
$(".fyre-comment-count").html($(".fyre-comment-count").text().split(" ")[0]+" Conversations");
When I type the same in my page, it doesn't work.
I also tried $(document).ready(function(){}); but no luck (same with document.ajaxSuccess).
Similarly, document.on would be working only with 'click' events but I want it to be done by default.
$(document).on('click', '.fyre-comment-article', function() {
//Code
});
Does it have any 'load' type event in document.on?
What should I do to accomplish this?
Thanks,

I analyzed your web page and saw the following code:
var articleId = fyre.conv.load.makeArticleId(null);
fyre.conv.load({}, [{
el: 'livefyre-comments',
network: "livefyre.com",
siteId: "351251",
articleId: articleId,
signed: false,
collectionMeta: {
articleId: articleId,
url: "http://projectdemocracy.in",//fyre.conv.load.makeCollectionUrl(),
}
}], function() {});
It seems like the 3rd argument of fyre.conv.load method is a callback function that will be executed when all elements are generated.
So put your code inside this function. It will be like this:
...
}], function() {
console.log('callback');
$(".fyre-comment-count").html($(".fyre-comment-count").text().split(" ")[0]+" Conversations");
});
Hope this helps!
EDIT
If it still doesn't work it may be because livefyre runs this callback before DOM elements are being created. The workaround is to put $(".fyre-comment-count").html(...); inside setTimeout with minimal delay:
...
}], function() {
setTimeout(function() {
$(".fyre-comment-count").html($(".fyre-comment-count").text().split(" ")[0]+" Conversations");
}, 10); //minimal delay. wait till livefyre generates all needed elements
});
EDIT 2
This is another variant how to make it work:
...
}], function(widget) {
widget.on('commentCountUpdated', function() {
setTimeout(function() {
$(".fyre-comment-count").html($(".fyre-comment-count").text().split(" ")[0]+" Conversations");
}, 10);
});
});
This widget has a commentCountUpdated event, so you have to subscribe on it, and every time the comments number is changing, your callback will be executed
By the way, commentCountUpdated callback recieves a single argument - the number of comments, so you can rewrite your code as follows:
}], function(widget) {
widget.on('commentCountUpdated', function(commentsNum) {
setTimeout(function() {
$(".fyre-comment-count").html(commentsNum + " Conversations");
}, 10);
});
});

jQuery has a on load event, if this is what you are looking for:
$(window).load(function(){ ... });

Related

Rebind after ajax is complete

I am currently in the process of working on the app which is through modular pattern.
The problem i am currently getting is that once the Ajax is complete, i want to be able to fire a function within the object. The object i can see but when i specify a function, it fails and comes back as Undefined.
JS
var TestCase = {
settings: {
cu: $('.select'),
},
init: function() {
se = this.settings;
},
windowsReady: function() {
TestCase.init();
if ($.fn.selectBox) {
TestCase.selectBind();
}
},
ajaxComp: function() {
TestCase.init();
TestCase.selectBind();
},
selectBind: function(){
se.cu.selectBox();
},
};
JS Fire - The selectBind works fine when its loaded through the ready call. However as mentioned before, the ajaxcomplete keeps coming back as Undefined for TestCase.ajaxComp(); or a direct call for TestCase.selectBind(); Please note that when i console.log(TestCase) it lists all the objects.
$(document).ready(function () {
TestCase.windowsReady();
});
$(document).ajaxSuccess(function() {
console.log(TestCase);
TestCase.ajaxComp();
console.log('completed');
});
This is happenning because of this line:
se = this.settings;
The this in the scope of your $(document).ajaxSuccess(...) method will be the jQuery object, not TestCase object.
Try changing it to se = TestCase.settings;

Reinit functions after ajax page load

The issue is that after the .load() function gets triggered, the predefined functions don't execute.
I am trying to re-init my functions after ajax .load(); function.
Here's my sample code:
var myApp = {
myObj: {
key1: value1,
key1: value1
},
activities:{
myFunction1: function() {
// my activity 1
},
myFunction2: function() {
// my activity 2
}
}
$(document).ready(function() {
myApp.activities.myFunction1(); // This function executes
$('.load-next-page').load(function() {
// next page loaded
myApp.activities.myFunction1(); // This function doesn't trigger, Need to trigger this function
});
});
$(document).on("load", ".load-next-page", function(){
myApp.activities.myFunction1();
});
Each time document element is loaded the function is triggered.
If IE8 is not a constraint, use the DOMSubtreeModified event for this.
try Promises like Q
and then using .then()
or jquery .promise()
like $( "div" ).promise().done(function() {...
you can read more about it hare and hare

Executing Javascript on return from Ajax

My page makes an Ajax call which returns some HTML to embed in the page and a script to run, attaching JQuery tooltips to various elements of the embedded HTML. The HTML and script are returned as JSON objects by my Django backend, and appear OK in the page, but the Javascript doesn't seem to work when I evaluate it:
$.ajax({
type: "GET",
url: "/url/to/ajax",
data: {
"foo": bar
},
success: function (data) {
$("#my-table").html(data['html']);
// alert(data['script']); // this works: I can see the script
eval(data['script']);
},
error: function () {
$("#my-table").html('');
}
});
The script itself looks like a series of expressions such as:
$(".foobar1").tooltip({
content: "The <em>foo</em> to the <strong>bar</strong>.",
tooltipClass: "tt-ref",
show: null,
close: function (event, ui) {
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(400, 1);
},
function () {
$(this).fadeOut("400", function () {
$(this).remove();
})
});
}
});
where foobar1 is a class in the HTML just added to the #my-table HTML.
Can anyone see where I'm going wrong here? Both jquery and jquery-ui are loaded on my page.
You don't need to eval anything, let browser execute it. For this create script element, set its content and append it to DOM:
success: function(data) {
$("#my-table").html(data.html);
$('<script>').html(data.script).appendTo('body');
},
Another, probably better option is to make script a part of the returned HTML.
You might try :
eval("data['script']");

How to wait for a function to complete before executing another function

I'm using selecter jquery. I initialize it by typing the code
$("select").selecter();
I need to make sure that the formstone selecter jquery library has completed before i start appending elements. So what i did is to is use the $.when function
initialize: function(){
$.when($("select").selecter()).then(this.initOptions());
},
initOptions: function(){
this.$el.find('.selecter').addClass('something');
}
But this does not work. How can i wait while formstone selecter is doing its thing before i execute another function?
Thanks,
UPDATE
Here's the update of what i did but it does not work.
initialize: function(){
$("select").selecter({callback: this.initOptions });
},
initOptions: function(){
this.$el.find('.selecter').addClass('something');
}
There is a callback option.
The function passed as a callback will receive the newly selected value as the first parameter
Should be $("select").selecter(callback: function() { alert('callback fired.') });
or as shown
$("select").selecter({
callback: selectCallback
});
function selectCallback(value, index) {
alert("VALUE: " + value + ", INDEX: " + index);
}
The problem which I think regarding the callback edited code is that this can refer to anything. Try the following code
var selectorObj = {
initialize: function(){
$("select").selecter({callback: selectorObj.initOptions });
},
initOptions: function(){
this.$el.find('.selecter').addClass('something');
}
};
Created a working fiddler for you http://jsfiddle.net/6Bj6j/
The css is out of shape. Just select what is poping up when you click on the dropdown. You will get an alert which is written in the callback.
The problem with the provided snippet is the scope of the callback:
var selectorObj = {
initialize: function(){
$("select").selecter({ callback: selectorObj.initOptions });
},
initOptions: function(){
// 'this' refers to the "$('.selecter')" jQuery element
this.addClass('something');
}
};
However if you just need to add a class to the rendered element, you should use the 'customClass' option:
$("select").selecter({
customClass: "something"
});
If you need to do more, you can always access the Selecter element directly:
var $selecter = $("select").selecter().next(".selecter");
$selecter.addClass("something").find(".selecter-selected").trigger("click");
Sidenote: I'm the main developer of Formstone. If you have any suggestions for new features or better implementation, just open a new issue on GitHub.

Refactor $(document).ready(), currently have 2 instances

I've got following JavaScript functions but want to refactor the $(document).ready() as I've got 2 instance of it. How can I achieve this?
FlashMessenger = {
init: function() {
setTimeout(function() {
$(".flash").fadeOut("slow", function () {
$(".flash").remove();
});
}, 5000);
}
}
SelectLanguage = {
init: function() {
$('#selectLanguageId').change(function() {
$('#frmSelectLanguage').submit();
});
}
}
$(document).ready(FlashMessenger.init);
$(document).ready(SelectLanguage.init);
It’s perfectly acceptable to set multiple handlers for $(document).ready, although you may have a good reason to do otherwise that I’m not aware of. You might be interested in knowing that $(handler) can be used as shorthand for $(document).ready(handler):
$(FlashMessenger.init);
$(SelectLanguage.init);
If you really want them in one call though, try this:
$(function() {
FlashMessenger.init();
SelectLanguage.init();
});
First off, there's no reason you have to combine them.
But if you want to:
$(document).ready(function(jq){
FlashMessenger.init(jq);
SelectLanguage.init(jq);
});
Breaking it down:
Create a function to do all your init (it can be named or anonymous; the one above is anonymous).
Have it call the other init functions, passing in the jQuery instance that jQuery passes you just in case they use it.
You might choose to wrap each init call in a try/catch block as well, so that errors in one init don't prevent the next init from occuring, but that depends on your needs.
Just combine them into one call with an anonymous function:
$(document).ready(function()
{
FlashMessenger.init();
SelectLanguage.init();
});
$(document).ready(function() {
FlashMessenger.init();
SelectLanguage.init();
});
Option 1
FlashMessenger = {
init: function() {
setTimeout(function() {
$(".flash").fadeOut("slow", function () {
$(".flash").remove();
});
}, 5000);
}
}
SelectLanguage = {
init: function() {
$('#selectLanguageId').change(function() {
$('#frmSelectLanguage').submit();
});
}
}
$(function(){
FlashMessenger.init();
SelectLanguage.init();
});
Option 2
FlashMessenger = {
init: function() {
setTimeout(function() {
$(".flash").fadeOut("slow", function () {
$(".flash").remove();
});
}, 5000);
}
}
SelectLanguage = {
init: function() {
$('#selectLanguageId').change(function() {
$('#frmSelectLanguage').submit();
});
}
}
$(document).ready(function(){
FlashMessenger.init();
SelectLanguage.init();
});
Option 3
You actually don't need those 2 objects since the only hold the init methods, so here's the ultimate solution, in my opinion, unless you use those objects elsewhere.
$(function(){
$('#selectLanguageId').change(function() {
$('#frmSelectLanguage').submit();
});
setTimeout(function() {
$(".flash").fadeOut("slow", function () {
$(".flash").remove();
});
}, 5000);
})
I prefer 2 and 3 for this reason.
I think what the op is saying is, "If in the future I have a third function to be invoked at document.ready, then how do I do it without touching that piece of code?"
If you do not want multiple $(document).ready() calls, you could just create an array called startupHooks and add each method to it:
startupHooks[ startupHooks.length ] = myNewStartupHook;
and your startup script could look like
$(document).ready(function() {
for( var i=0; i<startupHooks.length; i++ ) {
startupHooks[i]();
}
}
I know that is not mighty useful, but if that appeals to you, you can do it this way.
Personally, I'd go with multiple $(document).ready() calls.
Personally I'd go for not using document.ready at all.
If you place the scripts at the end of your html-page(just before the tag) you can just write in any way you like.
Maybe this doesn't work for 0.01% of the scripts but it never failed to work for me.
Positive effect of this is that the initial HTML+CSS rendering goes faster.
You can also read about it on yahoo. http://developer.yahoo.com/performance/rules.html#js_bottom

Categories

Resources