I've been trying to implement JavaScript thats read my twitter account ant return to me the latest 2 tweeties...
I try to use the XML but, it doesn't work well.
There is a easy way to do this?
<script>
var ajax = "";
$(function () {
ret_tweets(1);
$('body').data('page', 1);
in_scroll();
});
function in_scroll() {
$(window).scroll(function () {
if (($(window).scrollTop() + $(window).height() + 10) >= $(document).height()) {
$(window).unbind('scroll');
ajax.abort();
ret_tweets($('body').data('page'));
}
});
}
function retorna_tweets(pagina) {
$('#list-tweets').append('<li class="Loading">Loading</li>');
var screen_name = 'new';
var url = 'http://api.twitter.com/1/statuses/user_timeline.json?callback=?';
$('body').data('page', paging + 1);
ajax = $.getJSON(url, {
screen_name: screen_name,
page: page
}, function (tweets) {
$('.carregando').fadeOut(function () {
for (x in tweets)
$('#list-tweets').append('<li>' + tweets[x].text + '</li>');
in_scroll();
$(this).remove();
});
});
}
</script>
There is another solution using JAvaScript?
Twitter offers solution to this:
<script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script>
<script type="text/javascript" src="http://twitter.com/statuses/user_timeline/takewara.json?callback=twitterCallback2&count=2"></script>
The above will get last two tweets from user takewara (yes, thats me on twitter :) )
EDIT
here is also snippet from my page how do i do it:
<h2 style="display: none;" >Actualities</h2>
<div id="twitter_div">
<h2 style="display: none;" >Twitter Updates</h2>
<ul id="twitter_update_list"></ul>
..older tweets
</div>
<script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"> </script>
<script type="text/javascript" src="http://twitter.com/statuses/user_timeline/takewara.json?callback=twitterCallback2&count=2"></script>
</div>
</div>
Try This, should Work:
The JavaScript:
function twtLnks(txt) {
p = txt.split(" ");
txt = "";
for (var i = 0; i < p.length; i++) {
var str = p[i];
var lnk = "https://twitter.com/#!/";
if (str.indexOf("#") != -1) { str = '' + str + ''; }
if (str.indexOf("#") != -1) { str = '' + str + ''; }
if (str.indexOf("http://") != -1) { str = '' + str + ''; }
txt += str + " ";
} return txt;
}
function tweets() {
if ($('.homeTwitter').length) {
$('.homeTwitter').append('<span>Loading.</span>');
//Here put your account
var sn = 'YourAccount';
var u = 'https://api.twitter.com/1/statuses/user_timeline.json?callback=?';
var t = $.getJSON(u, { screen_name: sn }, function(twt) {
$('.homeTwitter span').fadeOut("fast", function() {
$(".homeTwitter").append("<ul></ul>");
for (var i = 0; i < 1; i++) {
if (twt[i]) {
var txt = twtLnks(twt[i].text);
$(".homeTwitter ul").append('<li>' + txt + '</li>');
} else {
break;
}
}
$(".homeTwitter").append('#' + sn + '');
$(this).remove();
});
});
}
}
$(document).ready(function() {
tweets();
});
IN C#
<div class="homeTwitter">
<h2>Twitter</h2>
</div>
Related
How can I get Blogger to display random posts, while preventing an infinite loop when there are no posts to display?
Here is my JavaScript code which I am attempting to use:
<script>
var dt_numposts = 10;
var dt_snippet_length = 100;
var dt_info = 'true';
var dt_comment = 'Comment';
var dt_disable = '';
var dt_current = [];
var dt_total_posts = 0;
var dt_current = new Array(dt_numposts);
function totalposts(json) {
dt_total_posts = json.feed.openSearch$totalResults.$t
}
document.write('<script type=\"text/javascript\" src=\"/feeds/posts/summary?max-results=100&orderby=published&alt=json-in-script&callback=totalposts\"><\/script>');
function getvalue() {
for (var i = 0; i < dt_numposts; i++) {
var found = false;
var rndValue = get_random();
for (var j = 0; j < dt_current.length; j++) {
if (dt_current[j] == rndValue) {
found = true;
break
}
};
if (found) {
i--
} else {
dt_current[i] = rndValue
}
}
};
function get_random() {
var ranNum = 1 + Math.round(Math.random() * (dt_total_posts - 1));
return ranNum
};
function random_list(json) {
a = location.href;
y = a.indexOf('?m=0');
for (var i = 0; i < dt_numposts; i++) {
var entry = json.feed.entry[i];
var dt_posttitle = entry.title.$t;
if ('content' in entry) {
var dt_get_snippet = entry.content.$t
} else {
if ('summary' in entry) {
var dt_get_snippet = entry.summary.$t
} else {
var dt_get_snippet = "";
}
};
dt_get_snippet = dt_get_snippet.replace(/<[^>]*>/g, "");
if (dt_get_snippet.length < dt_snippet_length) {
var dt_snippet = dt_get_snippet
} else {
dt_get_snippet = dt_get_snippet.substring(0, dt_snippet_length);
var space = dt_get_snippet.lastIndexOf(" ");
dt_snippet = dt_get_snippet.substring(0, space) + "
";
};
for (var j = 0; j < entry.link.length; j++) {
if ('thr$total' in entry) {
var dt_commentsNum = entry.thr$total.$t + ' ' + dt_comment
} else {
dt_commentsNum = dt_disable
};
if (entry.link[j].rel == 'alternate') {
var dt_posturl = entry.link[j].href;
if (y != -1) {
dt_posturl = dt_posturl + '?m=0'
}
var dt_postdate = entry.published.$t;
if ('media$thumbnail' in entry) {
var dt_thumb = entry.media$thumbnail.url
} else {
dt_thumb = "https://blogspot.com/"
}
}
};
document.write('<img alt="' + dt_posttitle + '" src="' + dt_thumb + '"/>');
document.write('<div>' + dt_posttitle + '</div>');
if (dt_info == 'true') {
document.write('<span>' + dt_postdate.substring(8, 10) + '/' + dt_postdate.substring(5, 7) + '/' + dt_postdate.substring(0, 4) + ' - ' + dt_commentsNum) + '</span>'
}
document.write('<div style="clear:both"></div>')
}
};
getvalue();
for (var i = 0; i < dt_numposts; i++) {
document.write('<script type=\"text/javascript\" src=\"/feeds/posts/summary?alt=json-in-script&start-index=' + dt_current[i] + '&max-results=1&callback=random_list\"><\/script>')
};
</script>
Expected output:
?
Actual output:
?
It looks like your post is mostly code; please add some more details.
It looks like you're trying to populate dt_current with dt_numposts = 10 elements. I modified getvalue() as follows, so that dt_numposts is capped at dt_total_posts, which may be 0. This allows the outer for loop to exit.
function getvalue() {
dt_numposts = (dt_total_posts < dt_numposts) ? dt_total_posts : dt_numposts;
// ...
I couldn't test this, because I don't have an example /feeds/posts/summary?max-results=100&orderby=published&alt=json-in-script&callback=totalposts JSON resource, but it works for zero posts. Whether is works for dt_numposts > 0, you'll need to test!
I am new to JSLink and am trying to separate fields of the View Item form into tabs rather than the New Item form (tried using this on DispForm, showed tabs but not different fields). Are there any examples or ways to modify this to work on the view form?
Link: https://code.msdn.microsoft.com/office/Client-side-rendering-code-b2eedf92#content
var currentFormUniqueId;
var currentFormWebPartId;
// Use "Multi String" javascript to embed the required css
var MultiString = function (f) {
return f.toString().split('\n').slice(1, -1).join('\n');
}
//CSS would go here
var tabsObj = [
["General", ["Title", "Age", "Married", "Mobile", "SSN"]],
["Work", ["Manager", "Salary", "Phone", "Email"]],
["Other", ["Comments"]]
];
(function () {
// jQuery library is required in this sample
// Fallback to loading jQuery from a CDN path if the local is unavailable
(window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.0.min.js"><\/script>'));
var tabsContext = {};
tabsContext.OnPreRender = TabsOnPreRender;
tabsContext.OnPostRender = TabsOnPostRender;
// accordionContext.OnPostRender = accordionOnPostRender;
tabsContext.Templates = {};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(tabsContext);
})();
function TabsOnPreRender(ctx) {
if (!currentFormUniqueId) {
currentFormUniqueId = ctx.FormUniqueId;
currentFormWebPartId = "WebPart" + ctx.FormUniqueId;
jQuery(document).ready(function () {
var tabHTMLTemplate = "<li class='{class}'><a href='#{Index}'>{Title}</a></li>";
var tabClass;
var tabsHTML = "";
for (var i = 0; i < tabsObj.length; i++) {
tabClass = "";
if (i == 0){ tabClass = "active";}
tabsHTML += tabHTMLTemplate.replace(/{Index}/g, i).replace(/{Title}/g, tabsObj[i][0]).replace(/{class}/g, tabClass)
}
jQuery("#" + currentFormWebPartId).prepend("<ul class='tabs'>" + tabsHTML + "</ul>");
jQuery('.tabs li a').on('click', function (e) {
var currentIndex = jQuery(this).attr('href').replace("#","");
showTabControls(currentIndex);
jQuery(this).parent('li').addClass('active').siblings().removeClass('active');
e.preventDefault();
});
showTabControls(0);
jQuery("#" + currentFormWebPartId).prepend("<!--mce:0-->");
});
}
}
function TabsOnPostRender(ctx) {
var controlId = ctx.ListSchema.Field[0].Name + "_" + ctx.ListSchema.Field[0].Id;
jQuery("[id^='" + controlId + "']").closest("tr").attr('id', 'tr_' + ctx.ListSchema.Field[0].Name).hide();
}
function showTabControls(index)
{
jQuery("#" + currentFormWebPartId + " [id^='tr_']").hide();
for (var i = 0; i < tabsObj[index][1].length; i++) {
jQuery("[id^='tr_" + tabsObj[index][1][i] + "']").show();
}
}
Replace functions TabsOnPostRender and showTabControls:
function TabsOnPostRender(ctx) {
var controlId = ctx.ListSchema.Field[0].Name;
jQuery("a[name^='SPBookmark_" + controlId + "']").closest("tr").hide();
}
function showTabControls(index ){
jQuery("a[name^='SPBookmark_']").closest("tr").hide();
for (var i = 0; i < tabsObj[index][1].length; i++) {
jQuery("a[name^='SPBookmark_" + tabsObj[index][1][i] + "']").closest("tr").show();
}
}
I recently built a small quiz application, it currently only has two questions. After all the questions are finished I would like for the app to present a page that says "You made it here" (eventually I'll add more). However for some reason the final-function feedback of this code is not working. Where am I going wrong?
$(document).ready(function () {
var questions = [
{question: "Who is Zack Morris?",
choices: ['images/ACslater.jpg','images/CarltonBanks.jpeg','images/ZachMorris.jpg'],
quesNum: 1,
correctAns: 2},
{question: "Who is Corey Matthews?",
choices: ['images/CoryMatthews.jpeg','images/EdAlonzo.jpg','images/Shawnhunter.jpg'],
quesNum: 2,
correctAns: 1},
];
var userAnswer //THis needs to be looked into
var counter = 0;
var score = 0;
var html_string = '';
var string4end = ''
//function to loop choices in HTML, updates counter, checks answer
var update_html = function(currentQuestion) {
// put current question into a variable for convenience.
// put the question string between paragraph tags
html_string = '<p>' + currentQuestion.question + '</p>';
// create an unordered list for the choices
html_string += '<ul>';
// loop through the choices array
for (var j = 0; j < currentQuestion.choices.length; j++) {
// put the image as a list item
html_string += '<li><img src="' + currentQuestion.choices[j] + '"></li>';
}
html_string += '</ul>';
$('.setImg').html(html_string);
}
update_html(questions[0]);
$('.setImg li').on('click', function (e) {
userAnswer = $(this).index();
checkAnswer();
counter++;
update_html(questions[counter]);
$('#score').html(score);
showFinalFeedback();
});
//function to identify right question
function checkAnswer ()
{
if (userAnswer === questions[counter].correctAns)
{
score=+100;
}
}
function showFinalFeedback ()
{
if (counter === (questions.length+1))
{
string4end = '<p>' + 'You made it here!!!!' + '</p>';
$('.setImg').html(string4end);
}
}
});
I agree with Vector that you either should start with 1 as Counter initialization or, to check
if (counter < questions.length) {
return;
}
alert('You \'ve made it till here');
I also rewrote it in a form of a jquery plugin, maybe a handy comparison to your way of working?
jsfiddle: http://jsfiddle.net/DEb7J/
;(function($) {
function Question(options) {
if (typeof options === 'undefined') {
return;
}
this.chosen = -1;
this.question = options.question;
this.options = options.options;
this.correct = options.correct;
this.toString = function() {
var msg = '<h3><i>' + this.question + '</i></h3>';
for (var i = 0; i < this.options.length; i++) {
msg += '<a id="opt' + i + '" class="answer toggleOff" onclick="$(this.parentNode).data(\'quizMaster\').toggle(' + i + ')">' + this.options[i] + '</a>';
}
return msg;
};
this.toggle = function(i) {
var el = $('#opt' + i);
if ($(el).hasClass('toggleOff')) {
$(el).removeClass('toggleOff');
$(el).addClass('toggleOn');
} else {
$(el).removeClass('toggleOn');
$(el).addClass('toggleOff');
}
};
}
function Quiz(elem, options) {
this.element = $(elem);
this.lastQuestion = -1;
this.questions = [];
this.correct = 0;
if (typeof options !== 'undefined' && typeof options.questions !== undefined) {
for (var i = 0; i < options.questions.length; i++) {
this.questions.push(new Question(options.questions[i]));
}
}
this.start = function() {
this.lastQuestion = -1;
this.element.html('');
for (var i = 0; i < this.questions.length; i++) {
this.questions[i].chosen = -1;
}
this.correct = 0;
this.next();
};
this.next = function() {
if (this.lastQuestion >= 0) {
var p = this.questions[this.lastQuestion];
if (p.chosen === -1) {
alert('Answer the question first!');
return false;
}
if (p.chosen === p.correct) {
this.correct++;
}
$(this.element).html('');
}
this.lastQuestion++;
if (this.lastQuestion < this.questions.length) {
var q = this.questions[this.lastQuestion];
$(this.element).html(q.toString());
console.log(q.toString());
} else {
alert('you replied correct on ' + this.correct + ' out of ' + this.questions.length + ' questions');
this.start();
}
};
this.toggle = function(i) {
if (this.lastQuestion < this.questions.length) {
var q = this.questions[this.lastQuestion];
q.toggle(q.chosen);
q.toggle(i);
q.chosen = i;
}
};
}
$.fn.quizMaster = function(options) {
if (!this.length || typeof this.selector === 'undefined') {
return;
}
var quiz = new Quiz($(this), options);
quiz.start();
$(this).data('quizMaster', quiz);
$('#btnConfirmAnswer').on('click', function(e) {
e.preventDefault();
quiz.next();
});
};
}(jQuery));
$(function() {
$('#millionaire').quizMaster({
questions: [
{
question: 'Where are the everglades?',
options: ['Brazil','France','USA','South Africa'],
correct: 2
},
{
question: 'Witch sport uses the term "Homerun"?',
options: ['Basketball','Baseball','Hockey','American Football'],
correct: 1
}
]
});
});
Hey guys thanks for your help. I was able to use the following work around to ensure everything worked:
$('.setImg').on('click', 'li', function () {
userAnswer = $(this).index();
checkAnswer();
counter++;
$('#score').html(score);
if (counter < questions.length)
{
update_html(questions[counter]);
}
else{
showFinalFeedback();
}
});
I've created a dynamic listview from database on my jQuery mobile #page1.
That works all perfect. I can see a list with all items from my database (ID, name ...)
Now I want to pass the ID garm.ID from my database item to the next page, after I've clicked on a item in the listview.
My JavaScript:
$(document).on("pagecreate", "#page1",function(){
$(function() {
$.ajaxSetup( {
"async": false
} );
$.getJSON("http://server/kas1.js", function(data) {
for(var i = 0; i < data.length; i++) {
var garm = data[i];
$.getJSON("http://server/kas2.js", function(data) {
var no = data[0].no;
$("#content-page1").append(
"<ul data-role=\"listview\">" +
"<li><a href=\"#page2\">" +
"<h2>Hello</h2>" +
"<p>Status:"+data[0].no+"</p>" +
"</a></li>" +
"</ul><br>"
);
});
}
});
$.ajaxSetup( {
"async": true
} );
});
});
You can see the line: "<li><a href=\"#page2\">" +
With this link you will redirect to the next page and on the next page I want to use the passed ID.
Try this:
$(document).on("pagecreate", "#page1",function(){
$(function() {
$.ajaxSetup( { "async": false } );
$.getJSON("http://server/kas1.js", function(data) {
for(var i = 0; i < data.length; i++) {
var garm = data[i];
$.getJSON("http://server/kas2.js", function(data) {
var no = data[0].no;
$("#content-page1").append(
"<ul data-role=\"listview\">" +
"<li><a href='#page2?garm_id='" + garm.ID + ">" +
"<h2>Hello</h2>" +
"<p>Status:"+data[0].no+"</p>" +
"</a></li>" +
"</ul><br>"
);
});
}
});
$.ajaxSetup( { "async": true } );
});
});
On page two:
function queryStringParameters (keyValueString) {
var query_string, whole_query_string, query_string_obj = {};
if (typeof keyValueString === "undefined") {
whole_query_string = window.location.search;
if (whole_query_string[0] === "?") {
query_string = whole_query_string.replace('?', '');
} else {
query_string = whole_query_string;
}
} else {
query_string = keyValueString
}
var query_string_array = query_string.split('&');
if (query_string !== '') {
for (var i = 0; i < query_string_array.length; i++) {
var query = query_string_array[i],
query_array = query.split('=');
query_string_obj[query_array[0]] = query_array[1] || '';
}
return query_string_obj;
} else {
return {};
}
}
var hash = window.location.hash,
queryString = hash.split('?')[1],
garm = queryStringParameters(queryString),
garm_id = garm.id;
I hope this works:
'<li><a href="#page2,garmId='+ garm.ID +'">'
then, in page 2 you can (hopefully) parse the hashtag to get the id
Hope this helps, cheers
I Have an odd issue with some JavaScript code (again, I hate debugging JS code). I am working on a regular table - which I fill up from a JSON call, and have added in support for some paging (sort of 2x paging I guess you could call it), sorting and some selecting of rows. Everything is working nicely - BUT when a row is DESELECTED (and deselected only) my add_navigate event gets fired twice, which results in a bit of reloading of data that is not needed - and an indication of loading that is even more not needed.
First here's my JS code:
var customerType;
var selYear;
var selMonth;
var sdir;
var sort;
var page;
var noteId;
var hasDoneCall;
var customerId;
var customerIdChanged = false;
function initValues() {
customerType = "Publisher";
selYear = new Date().getFullYear();
selMonth = new Date().getMonth()+1;
sdir = false;
sort = "CustomerName";
page = 1;
noteId = false;
customerId = 0;
hasDoneCall = location.href.indexOf('#') > 0;
}
function flash(elm, color, duration) {
var current = elm.css('backgroundColor');
elm.animate({ backgroundColor: 'rgb(' + color + ')' }, duration / 2).animate({ backgroundColor: current }, duration / 2);
}
function createNotes(elm) {
var btn = jQuery(elm);
btn.attr('disabled', 'disabled');
bulkCreditOption('true', '', function(changeSet) {
var i = 0;
while (i < changeSet.length) {
var selector = "input[type=checkbox][value=" + changeSet[i] + "].check:checked";
var row = jQuery(selector).parent().parent();
var cell = row.find("td:nth-child(2)");
cell.html("" + cell.html() + "");
flash(row, '60, 130, 200', 500);
i++;
}
btn.removeAttr('disabled');
});
}
function deleteNotes(elm) {
var btn = jQuery(elm);
btn.attr('disabled', 'disabled');
bulkCreditOption('', 'true', function(changeSet) {
var i = 0;
while (i < changeSet.length) {
var selector = "input[type=checkbox][value=" + changeSet[i] + "].check:checked";
var row = jQuery(selector).parent().parent();
var cell = row.find("td:nth-child(2)");
cell.html(cell.text());
flash(row, '60, 130, 200', 500);
i++;
}
btn.removeAttr('disabled');
});
}
function bulkCreditOption(createNotes, deleteNotes, callback) {
var path = "/BulkCredit";
var data = "";
var checked = jQuery("input[type=checkbox].check:checked");
checked.each(function(chk) {
data += "&ids=" + urlencode(jQuery(this).val());
});
jQuery.ajax({
type: 'POST',
url: path,
dataType: 'json',
data: "createNotes=" + urlencode(createNotes) + data + "&deleteNotes=" + urlencode(deleteNotes),
success: function(msg) {
callback(msg);
}
});
}
initValues();
Sys.Application.add_init(function() {
Sys.Application.add_navigate(function(sender, e) {
var reinstate = e.get_state();
if (typeof (reinstate) != 'undefined' && typeof (reinstate.customerType) != 'undefined') {
customerType = reinstate.customerType;
selYear = reinstate.selYear;
selMonth = reinstate.selMonth;
sdir = reinstate.sdir;
sort = reinstate.sort;
page = reinstate.page;
noteId = reinstate.noteId;
customerId = reinstate.customerId;
} else {
initValues();
}
if (!customerIdChanged) {
jQuery("#customerTypeChanger").val(customerType);
jQuery("#customerFilter").val(customerId);
jQuery("#monthPicker").empty();
makeMonthPicker();
if (noteId != false && noteId != 'false') {
doShowNotes();
} else {
jQuery("#notesContent").hide();
jQuery("#tableContent").show();
doAjaxCall();
}
} else {
//logic to fetch customer specific stuff here, TODO
customerIdChanged = false;
}
});
Sys.Application.set_enableHistory(true);
jQuery(document).ready(function() {
origColor = jQuery("#dataTable > thead > tr > th").css('backgroundColor');
makeMonthPicker();
jQuery("#customerTypeChanger").val(customerType);
jQuery("#customerTypeChanger").change(function() {
customerType = jQuery(this).val();
iqSetHistory();
});
jQuery("#customerFilter").change(function() {
customerId = jQuery(this).val();
var tableBody = jQuery("#dataTable > tbody");
tableBody.find("tr").removeClass("selected");
tableBody.find("tr[rel=" + customerId + "]").addClass("selected");
customerIdChanged = true;
iqSetHistory();
});
jQuery(".checkAll").click(function() {
var elm = jQuery(this);
if (elm.is(':checked')) {
jQuery(".check").attr('checked', 'checked');
} else {
jQuery(".check").removeAttr('checked');
}
});
if (!hasDoneCall) {
if (noteId == false) {
doAjaxCall();
} else {
doShowNotes();
}
}
});
});
function makeMonthPicker() {
var selDate = new Date();
selDate.setFullYear(selYear);
selDate.setMonth(selMonth-1);
jQuery("#monthPicker").monthPicker(function(year, month) {
selYear = year;
selMonth = month;
iqSetHistory();
}, selDate);
}
var origColor;
var notesPath = "/ShowNotes";
function fadeOut(elm) {
elm.animate({ backgroundColor: 'rgb(180, 180, 180)' }, 250);
}
function fadeIn(elm) {
elm.animate({ backgroundColor: origColor }, 250);
}
function iqSetHistory() {
var state = { 'customerType': customerType, 'selYear': selYear, 'selMonth': selMonth, 'sdir': sdir, 'sort': sort, 'page': page, 'noteId': noteId, 'customerId':customerId };
Sys.Application.addHistoryPoint(state);
}
var ajaxPath = "/GetCreditListMonth";
function doAjaxCall() {
fadeOut(jQuery("#dataTable > thead > tr > th"));
jQuery.ajax({
type: "POST",
url: ajaxPath,
dataType: "json",
data: "month=" + selMonth + "&year=" + selYear + "&custType=" + customerType + "&sort=" + sort + "&sdir=" + sdir + "&page=" + page + "&asCsv=false",
success: function(msg) {
var table = jQuery("#dataTable");
var tableBody = table.find("tbody");
tableBody.empty();
var i = 0;
while (i < msg.Rows.length) {
var data = msg.Rows[i];
var row = jQuery("<tr rel=\"" + data.CustomerId + "\"></tr>");
if (data.CustomerId == customerId) {
row.addClass("selected");
}
if (i % 2 == 1) {
row.addClass("alternatetablerow");
}
var custName = data.CustomerName;
if (data.PaymentCreated) {
custName = "" + custName + "";
}
row.append("<td><input type=\"checkbox\" class=\"check\" name=\"ids\" value=\"" + getCreditId(data.CustomerId) + "\" /></td>");
row.append("<td>" + custName + "</td>");
row.append("<td>" + data.AmountExcludingTaxes + "</td>");
row.append("<td>" + data.BonusAmount + "</td>");
row.append("<td>" + data.Amount + "</td>");
row.appendTo(tableBody);
i++;
}
tableBody.find("input, a").click(function(event){ //Stop clicks from falling through to the table row event
event.stopPropagation();
return true;
});
tableBody.find("tr").click(function(event){
var row = jQuery(this);
if (row.hasClass("selected")) { //Deselect
jQuery("#customerFilter").val(0);
} else {
jQuery("#customerFilter").val(jQuery(this).attr('rel'));
}
jQuery("#customerFilter").triggerHandler("change");
});
createPager(msg.Pages, jQuery("#pager"));
jQuery(".checkAll").triggerHandler('click');
fadeIn(table.find('thead > tr > th'));
}
});
}
function downloadListAsCsv() {
window.location.href = ajaxPath + "?month=" + selMonth + "&year=" + selYear + "&custType=" + customerType + "&sort=" + sort + "&sdir=" + sdir + "&page=0&asCsv=true";
}
function doShowNotes(){
jQuery.ajax({
type: "GET",
url: notesPath + "/" + noteId,
success: function(msg) {
jQuery("#tableContent").hide();
jQuery("#notesContent").html(msg).show();
}
});
}
function showNotes(id) {
noteId = id;
iqSetHistory();
}
function showTable() {
noteId = false;
iqSetHistory();
}
function getCreditId(custId) {
return selYear + "-" + selMonth + "-" + custId;
}
function sortDataTable(col) {
if (col == sort) {
sdir = !sdir;
} else {
sdir = false;
}
page = 1
sort = col;
iqSetHistory();
}
function createPager(totalPages, elm) {
elm.empty();
if (totalPages > 1)
{
var builder = "";
var numDirections = 2;
if (page > 1)
{
if (page - numDirections - 1 > 0)
{
builder += CreatePageLinkStatic(1, "«");
builder += " ";
}
builder += CreatePageLinkStatic(page - 1, "<");
builder += " ";
}
var n = page - numDirections;
while (n < page)
{
if (n > 0)
{
builder += CreatePageLinkStatic(n, n);
builder += " ";
}
n++;
}
builder += page;
builder += " ";
n = page + 1;
while (n <= page + numDirections && n <= totalPages)
{
builder += CreatePageLinkStatic(n, n);
builder +=" ";
n++;
}
if (page < totalPages)
{
builder += CreatePageLinkStatic(page + 1, ">");
builder += " ";
if (page + numDirections < totalPages)
{
builder += CreatePageLinkStatic(totalPages, "»");
}
}
builder;
elm.append(builder);
}
}
function CreatePageLinkStatic(page, str){
return "" + str + "";
}
function pageDataTable(newPage){
page = newPage;
iqSetHistory();
}
And the markup:
<div id="tableContent">
<select id="customerTypeChanger">
<option selected="selected" value="Publisher">Publisher</option>
<option value="Advertiser">Advertiser</option>
</select>
<select id="customerFilter"><option value="0">Choose Customer</option><option value="1">Customer 1</option><option value="1">Customer 2</option>...</select>
<div id="monthPicker"></div>
<div>DownloadAsCSV</div>
<table id="dataTable" class="grid">
<thead>
<tr>
<th style="text-align: left"><input type="checkbox" name="toggleCheckBox" class="checkAll" value="dummy" /></th>
<th>Customer name</th>
<th><a href="javascript:sortDataTable('AmountExcludingTaxes')">Amount</th>
<th>Bonus amount</th>
<th>Amount including VAT</th>
</tr>
</thead>
<tbody></tbody>
</table>
<div class="pagination" id="pager"></div>
<div>With the selected rows</div>
<input id="createNotes" type="button" value="Create notes" onclick="javascript:createNotes(this)" /> <input id="deleteNotes" value="Delete notes" type="submit" onclick="javascript:deleteNotes(this)" />
</div>
<div id="notesContent"></div>
If needed as well, here's the code I did for the monthpicker (it is a very basic datepicker thing that just lets you flick back and forth between months and gives an output like
< April 2009 May 2009 June 2009 >
(where bold is clickable links taking you to see just that month period, and italic is the already selected one, obviously actual html markup differs)
It utilizes the datepicker from jQuery UI to get the localized names of the months
(function($) {
var selDate;
$.fn.monthPicker = function(callback, selectedDate) {
selDate = selectedDate;
var elm = this;
this.html("<span class=\"prevMonthButton\"><</span><span class=\"prevMonth\"></span><span class=\"curMonth\"></span><span class=\"nextMonth\"></span><span class=\"nextMonthButton\">></span>");
populateDates(this);
var prevMonthFunc = function() {
var month = selDate.getMonth() - 1;
if (month < 0) {
month = 11;
selDate.setFullYear(selDate.getFullYear() - 1);
}
selDate.setMonth(month);
populateDates(elm);
callback(selDate.getFullYear(), selDate.getMonth() + 1);
return false;
}
var nextMonthFunc = function() {
var month = selDate.getMonth() + 1;
if (month > 11) {
month = 0;
selDate.setFullYear(selDate.getFullYear() + 1);
}
selDate.setMonth(month);
populateDates(elm);
callback(selDate.getFullYear(), selDate.getMonth() + 1);
return false;
};
this.find(".prevMonth > a").click(prevMonthFunc);
this.find(".prevMonthButton > a").click(prevMonthFunc);
this.find(".nextMonth > a").click(nextMonthFunc);
this.find(".nextMonthButton > a").click(nextMonthFunc);
}
function populateDates(elm) {
var months = jQuery.datepicker._defaults.monthNames;
var selYear = selDate.getFullYear();
var selMonth = selDate.getMonth();
elm.find(".curMonth").text(months[selMonth] + " " + selYear);
var prevMonth = selMonth - 1;
var prevYear = selYear;
if (prevMonth < 0) {
prevMonth = 11;
prevYear = prevYear - 1;
}
elm.find(".prevMonth > a").text(months[prevMonth] + " " + prevYear);
var nextMonth = selMonth + 1;
var nextYear = selYear;
if (nextMonth > 11) {
nextMonth = 0;
nextYear = nextYear + 1;
}
elm.find(".nextMonth > a").text(months[nextMonth] + " " + nextYear);
}
})(jQuery);
I know most of this JavaScript code sucks - but for the main part it seems to do the job quite nicely, but as I said click a row to select it, then click it to deselect and boom, double call to add_navigate which results in an extra call to my JSON service and a visual flicker on the client side - and I cannot work out why it happens (and even more strange, why it just happens when it is deselected and not on a selected one as well).
I would try doing
.unbind('click').click(function()
instead of
.click(function()
Just to make sure click events are not getting bound twice.
I think the issue is with double binding of events to the same element unconsiously.
This is usually the scenario,
(function($){
var MyDocument = new Object({
prepareBody : function(){
//addClick Event
$('div#updatedElement').click(MyDocument.ajaxCall());
//adjusting the height of an updatedElement to an-otherElement
$('div#updatedElement').css('height', $('div#otherElement').height());
},
ajaxCall : function(){
//do your ajax Call
$.getJSON('index.php',{param:1, param:2},function(response){
//do something with your response
$('div#updatedElement').html(response)
//say if after your call you decide to update the body again
MyDocument.prepareBody();
//what that does is you will double bind click to the updateElement div.
//The next time that it is click, the AjaxCall function will run twice
//The next time it is clicked the MyDocument.ajaxCall function will be run four times
//8 - 16 - 32 and by now, firefox would have crashed!
},'json');
}
});
$(document).ready(function(){
MyDocument.prepareBody()
});
})(jQuery);
So as advised by KClough, unbind Events before binding them so that they run only once! Sad jQuery does not overwrite them as do other frameworks!
Hope this helps some one else
Oh Sorry I had completely forgotten about this question.
I restructured some of my code a little while after this and the issue was then gone. I am not exactly sure what caused this, seeing as it still surprised me how I only ever, seemingly, got the double loading half the time.
Anyhoow, the issue is solved, only I don't know how or why, which still slightly bothers me, but on the other hand - it works.