I'm trying to make a simple plugin that collects the # of Facebook likes and tweets for a given URL (and let users tweet or like a given link). There is a total share count that expands to include LIs for likes and shares upon hover. Currently, on mouseover or select of the like/share LIs, the HTML of the Twitter/Facebook is replaced with a link and text with a subtle CTA. This link is supposed to open a new window with a share dialog for the given social site. However, this link doesn't seem to work at all.
HTML
<html>
<head>
<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
<div id="social">
<ul>
<li class="share">
<p>shares<p>
</li>
<li class="twitter"><p>tweets</p></li>
<li class="facebook"><p>likes</p></li>
</ul>
</div>
<!-- <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/app.js"></scrpt>-->
</body>
</html>
jQuery
var fbCount,twCount,totalCount,
urlDebug = 'http://www.google.com',
urlCurrent = window.location.href,
twitterCountUrl = 'http://urls.api.twitter.com/1/urls/count.json?url=' + urlDebug + '&callback=?',
facebookCountUrl = 'https://graph.facebook.com/fql?q=SELECT%20share_count,%20like_count,%20comment_count,%20total_count,commentsbox_count,%20comments_fbid,%20click_count%20FROM%20link_stat%20WHERE%20url=%27' + urlDebug + '%27',
fbShareUrl = "https://www.facebook.com/sharer/sharer.php?u=" + urlDebug + "&t=" + document.title + 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=300,width=600',
twShareUrl = "https://twitter.com/intent/tweet?text=" + document.title + "url=" + urlDebug;
$('.sharelink').on('click', function() {
window.open( $(this).attr('href') );
return false;
});
function getnumString(num) {
var numString;
if (num < 1000) {
numString = num;
} else if (num < 10000) {
// removed my rube goldberg contraption and lifted
// CMS version of this segment
numString = num.charAt(0) + ',' + num.substring(1);
} else if (num < 1000000) {
numString = (Math.round((num / 1000) * 10) / 10) + "k"
} else {
numString = (Math.round((num / 1000000) * 10) / 10) + "M"
}
return numString.toString();
}
$.when(
$.getJSON(twitterCountUrl, function twitterCount(data) {
twCount = data.count;
$('.twitter').append('<p class="num">' + getnumString(twCount) + '</p>');
}),
$.getJSON(facebookCountUrl,
function facebookCount(data) {
fbCount = data.data[0].like_count;
$('.facebook').append('<p class="num">' + getnumString(fbCount) + '</p>');
})).done(function(response) {
totalCount = fbCount + twCount;
$('.share').append('<p class="num">' + getnumString(totalCount) + '</p>');
});
$('#social ul').on('mouseover touchstart focusin', function() {
$('.facebook, .twitter').slideDown("slow");
}).on('mouseleave touchend focusout', function() {
$('.facebook, .twitter').hide();
});
$('#social .twitter').on('mouseenter focusin', function() {
$(this).html('TWEET<br>LINK');
$(this).children('a').addClass('sharelink');
}).on('mouseleave focusout', function() {
$(this).children('a').removeClass('sharelink');
$(this).html('<p> tweets</p>').append('<p class="num">' + getnumString(twCount) + '</p>');
});
$('#social .facebook').on('mouseenter focusin', function() {
$(this).html('SHARE<BR>ON FB');
$(this).children('a').addClass('sharelink');
}).on('mouseleave focusout', function() {
$(this).children('a').removeClass('sharelink');
$(this).html('<p>likes</p>').append('<p class="num">' + getnumString(fbCount) + '</p>');
});
When you add dynamic elements to DOM jQuery actually never cached that. You need to use delegated events so that when you add dynamic elements they are in scope and jQuery is listening
Case 1 (direct):
$("div#social .twitter").on("mouseenter focusin", function() {...});
== Hey! I want every span.twitter inside div#social to listen up: when you get mouseenter on, do X.
Case 2 (delegated):
$("div#social").on("mouseenter focusin", "span.twitter", function() {...});
== Hey, div#target! When any of your child elements which are "span.twitter" get mouseentered, do X with them.
Summary
In case 1, each of those spans has been individually given instructions. If new spans get created, they won't have heard the instruction and won't respond to clicks. Each span is directly responsible for its own events.
In case 2, only the container has been given the instruction; it is responsible for noticing clicks on behalf of its child elements. The work of catching events has been delegated.
Related
I need some help with JQuery.
In my site I have a button that repeats in a layout. I decided to differentiate them by adding a class to each of them with a number with this code below which works very well.
jQuery(document).ready(function() {
// each button in the Machine loop get a unique CLASS
jQuery(".rv_button").each(function(i) {
jQuery(this).addClass("item" + (i + 1));
var its = ("item" + (i + 1));
console.log("." + its);
});
});
This button will be used to make appear or disappear a section that I also decided to differentiate them by adding a class to each of them with a number with this code below which works very well.
jQuery(".reveal").each(function(f) {
// each section in the Machine loop get a unique CLASS
jQuery(this).addClass("rive" + (f + 1));
var id = ("rive" + (f + 1)); // each section in the Machine loop get a unique CLASS
console.log("." + id);
});
I would like to create a code which has the function of when I click on item1 -> rive1 appears and disappears etc ...
here is my test code which does not work because I do not know how to include the variable included previously.
var id;
var its;
jQuery(document).ready(function() {
// The section is HIDE with the new class
jQuery("." + id).hide();
// The click function on the new button class
jQuery("." + its).click(function(e) {
// when i click on the new class button, the section appaear or desapear.
e.preventDefault();
jQuery("." + id).slideToggle();
jQuery("." + its).toggleClass('opened closed');
});
});
Any idea on how to passing the Variable into the last function ?
thanks all !
This the entire code :
jQuery(document).ready(function() {
// each button in the Machine loop get a unique CLASS
jQuery(".rv_button").each(function(i) {
jQuery(this).addClass("item" + (i + 1));
var its = ("item" + (i + 1));
console.log("." + its);
});
jQuery(".reveal").each(function(f) {
// each section in the Machine loop get a unique CLASS
jQuery(this).addClass("rive" + (f + 1));
var id = ("rive" + (f + 1)); // each section in the Machine loop get a unique CLASS
console.log("." + id);
});
var id;
var its;
jQuery(document).ready(function() {
// The section is HIDE with the new class
jQuery("." + id).hide();
// The click function on the new button class
jQuery("." + its).click(function(e) {
// when i click on the new class button, the section appaear or desapear.
e.preventDefault();
jQuery("." + id).slideToggle();
jQuery("." + its).toggleClass('opened closed');
});
});
});
I am creating an app that allows the user to check the local weather and temperature in celsius or fahrenheit. However, I am having a problem when toggling between the two unit types when the temperature is clicked on. This is the link to my demo.
And here is my Javascript code:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
$.getJSON("https://crossorigin.me/http://api.openweathermap.org/data/2.5/weather?lat=" + position.coords.latitude + "&lon=" + position.coords.longitude + "&units=imperial&appid=a62849f462c6573114f32a691f5d3c3f", function(json) {
var all = JSON.stringify(json);
var weather = JSON.stringify(json.weather[0]["description"]);
weather = weather.slice(1, -1);
var tempFahrenheit = JSON.stringify(json.main.temp);
var tempCelsius = JSON.stringify(json.main.temp * 2);
$("#weather").html(weather);
$("#temp").html(Math.floor(tempFahrenheit) + " °<span id='units'>F</span>");
$("#units").on('click', function() {
if ($(this).text() == "F") {
$("#temp").html(Math.floor(tempCelsius) + " °<span id='units'>C</span>");
} else {
$("#temp").html(Math.floor(tempFahrenheit) + " °<span id='units'>F</span>");
}
});
});
});
}
When you replace the html contents of the #temp div, you lose your event handler on the units div as well. Use event delegation instead. Assign the event on the body tag, but listen for events on the #units div.
Updated code:
$("body").on('click', '#units', function() {
if ($(this).text() == "F") {
$("#temp").html(Math.floor(tempCelsius) + " °<span id='units'>C</span>");
} else {
$("#temp").html(Math.floor(tempFahrenheit) + " °<span id='units'>F</span>");
}
});
Working fork of your Codepen: https://codepen.io/anon/pen/AXzYzR?editors=0010
I've created a JSfiddle here:
basically I have a form that will allow users to input additional sections... but when I have added more than 2 units and then proceed to click on the 'plus' (+) icon I get more than 1 element created in that section... its probably something elementary, but any info will help.
Move your Click functions out of the click function
//add unit input box and increment click counter by one.
addUnit.click(function () {
unitCounter += 1;
unitElementCount = jQuery(".unit-element").length;
if (unitCounter <= 4) {
error.hide();
container.append('<table id="unit-' + unitCounter + '-div" class="create-course-table-element unit-element"><tr><td><label class="unit-label">Unit ' + unitCounter + '</label></td><td><input class="create-course-input-element unit-input" id="unit-id-' + unitCounter + '" name="unit-' + unitCounter + '" /><div id="delete-unit-' + unitCounter + '" class="ui-icon ui-icon-circle-close del-unit" title="Delete unit"></div></td></tr><tr><td align="center">Sections</td><td><div id="add-section-icon-' + unitCounter + '" class="ui-icon ui-icon-plus add-section-icon"></div></td></tr></table><div id="section-id-' + unitCounter + '-div" class="this-section"></div>');
} else if (unitElementCount == 4) {
unitCounter = 5;
error.html("");
error.fadeIn(1500);
error.append("<p class='error-message'>Note: You are only able to add 4 units to a given course. Each unit allows you to add 10 separate sections of content; therefore you may add a total of 40 different sections to a given course. If the material requires more units, you should consider dividing the course into 2 parts.</p>");
}
});
//This part has been slightly modified and moved out of the addUnit.click() function
var counterSecTwo = 0;
var counterSecThree = 0;
var counterSecFour = 0;
jQuery(document).on("click", "#add-section-icon-2",function () {
counterSecTwo += 1;
var container = jQuery("#section-id-2-div");
container.append("<p>test "+counterSecTwo+"</p>");
});
jQuery(document).on("click", "#add-section-icon-3",function () {
counterSecThree += 1;
var container = jQuery("#section-id-3-div");
container.append("<p>test "+counterSecThree+"</p>");
});
jQuery(document).on("click", "#add-section-icon-4",function () {
counterSecFour += 1;
var container = jQuery("#section-id-4-div");
container.append("<p>test "+counterSecFour+"</p>");
});
});
Here I am binding the click handlers to Document as the elements do not exist yet: you could also add the event listener when you create the actual element.
Modified fiddle: http://jsfiddle.net/vewP7/
Long back I used JSON and was successful to get the hash tag feeds from twitter and facebook. But presently I am just able to get the feeds but its not being updated constantly that means it not been update dynamically. I guess I need to ajaxify it, but I am not able to do that since I am not aware of ajax. Here is the code which I have used to get the twitter search feeds.
$(document).ready(function()
{
$("#Enter").click(function(event){
var searchTerm = $("#search").val() ;
var baseUrl = "http://search.twitter.com/search.json?q=%23";
$.getJSON(baseUrl + searchTerm + "&rpp=1500&callback=?", function(data)
{
$("#tweets").empty();
if(data.results.length < 1)
$('#tweets').html("No results JOINEVENTUS");
$.each(data.results, function()
{
$('<div align="justify"></div>')
.hide()
.append('<hr> <img src="' + this.profile_image_url + '" width="40px" /> ')
.append('<span><a href="http://www.twitter.com/'
+ this.from_user + '">' + this.from_user
+ '</a> ' + makeLink(this.text) + '</span>')
.appendTo('#tweets')
.fadeIn(800);
});
});
});
});
function makeLink(text)
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp,"<a href='$1'>$1</a>");
}
The code below should help you. What I've done is moved the code which fetches the tweets into a function. This function is then called every X seconds to update the box. When the user enters a new search term and clicks "Enter", it will reset the timer.
var fetchSeconds = 30; //Number of seconds between each update
var timeout; //The variable which holds the timeout
$(document).ready(function() {
$("#Enter").click(function(event){
//Clear old timeout
clearTimeout(timeout);
//Fetch initial tweets
fetchTweets();
});
});
function fetchTweets() {
//Setup to fetch every X seconds
timeout = setTimeout('fetchTweets()',(fetchSeconds * 1000));
var searchTerm = $("#search").val();
var baseUrl = "http://search.twitter.com/search.json?q=%23";
$.getJSON(baseUrl + searchTerm + "&rpp=1500&callback=?", function(data) {
$("#tweets").empty();
if (data.results.length < 1) {
$('#tweets').html("No results JOINEVENTUS");
}
$.each(data.results, function() {
$('<div align="justify"></div>').hide()
.append('<hr> <img src="' + this.profile_image_url + '" width="40px" /> ')
.append('<span>' + this.from_user + ' ' + makeLink(this.text) + '</span>')
.appendTo('#tweets')
.fadeIn(800);
});
});
}
function makeLink(text) {
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp,"<a href='$1'>$1</a>");
}
Hope this helps
I'm trying to limit inserting elements to the page:
<script type="text/javascript">
$(function() {
var i = 1;
//allow only 3 elements
if (i < 4) {
$('#add').click(function() {
var add_input = '<input type="file" />'
var add_link = 'Remove'
$('body').append('<p>' + add_input + add_link + '</p>');
});
i++;
}
$('.remove').live('click', function() {
$(this).parent('p').remove();
});
});
</script>
But I can still add element a lot more than 4.
You need to check your variable i within your event handler.
$('#add').click(function() {
if(i < 4){
var add_input = '<input type="file" />'
var add_link = 'Remove'
$('body').append('<p>' + add_input + add_link + '</p>');
i++;
}
});
And you should decrease i within your live() handler.
See a working example : http://jsfiddle.net/CtGgg/
You could count the number of elements already on the page and limit it that way. Personally, I like treating the DOM itself as the canonical representation of user state. If that's important to you, you could do something like the following, even though it's a little less performant:
$('#add').live('click', function (evt) {
if ($('input[type=file]').length < 4) {
$('body').append('<p><input type="file"> Remove</p>');
}
evt.preventDefault();
});