Bind the event handler to the wrapper of the dynamic content instead of the content that does not yet exist (and thus cannot be bound to)
$('.flags button').click(function() {
$("p:lang(fr)").hide();
$("p:lang(gb)").show();
$('span.flags').html('<button type="button" class="close"></button>');
});
$('span.flags').on('click','button.close',function() {
$("p:lang(fr)").show();
$("p:lang(gb)").hide();
});
EDIT: A better way (perhaps)
To answer your question, is there a better way? Well perhaps if more flexible/modular is a better way then we might do that.
Here is the example in action: https://jsfiddle.net/MarkSchultheiss/y11qpd1L/
Bottom line is you want a language selector. We can debate what languages you have/want but really that depends on your data; so let's let the data determine the "flags" and you can decide if you wish to keep the "default" - I have simply put that in the data as well (in the markup).
Here is a sample markup: It is less than trivial because, well people do that often and I wanted to show a "group" of "buttons/flags" for each article and make it easy to see that. Notice the data-languagedefault="fr"
on the .article
element. Now the buttons/flags whatever you call them outside the "Default" one (your X button) are not shown, they are generated from the content's data. You can enhance that to use images etc. but I used text for simplicity in the example.
<div id="articles">
<div class="article" data-languagedefault="fr">
<div class="flags">
<ul class="myflags">
<li>
<button class="default" type="button">Default</button>
</li>
</ul>
</div>
<div class="container">
<span class="content" lang="fr" data-language="fr">I am french</span>
<span class="content" lang="gb" data-language="gb">I am gb</span>
<span class="content" lang="tr" data-language="tr">I am tr</span>
<span class="content" lang="en-us" data-language="en-us">I am en-us</span>
<span class="content" lang="en-gb" data-language="en-gb">I am en-gb</span>
</div>
</div>
</div>
Now how do we utilize that? We create some buttons from the .content
spans data attributes, then use those to drive what is showing etc.
I borrowed the jQuery extension filterByData
from an answer on this page: https://stackoverflow.com/a/22209579/125981
$(document).ready(function() {
(function($) {
$.fn.filterByData = function(prop, val) {
var $self = this;
if (typeof val === 'undefined') {
return $self.filter(function() {
return typeof $(this).data(prop) !== 'undefined';
});
}
return $self.filter(function() {
return $(this).data(prop) == val;
});
};
})(window.jQuery);
// setup all flags from data
$('#articles').find('.article').find('.content').each(function(index) {
var lang = $(this).data('language');
$('.flags').find('.myflags')
.append('<li><button class="flag" data-language="' + lang + '" type="button">' + lang + '</button></li>');
});
// show active button
$('li').on('activate', function() {
$(this).addClass('active').siblings().removeClass('active');
});
//set currently active language indicator and language
function setLang(me) {
var lang = $(me).data('language');
$(".content:lang(" + lang + ")").show().siblings('.content').hide();
$(me).parent('li').trigger('activate');
var defaultLang = $(me).parents('.article').eq(0).data('languagedefault');
var isDefault = defaultLang == lang;
$('#articles').find('.article').find('.myflags').find('button.default').toggle(!isDefault);
}
$('#articles').find('.article').find('.myflags').on('click', 'button.flag', function() {
setLang(this);
});
$('#articles').find('.article').find('.myflags').on('click', 'button.default', function() {
var defaultLang = $(this).parents('.article').eq(0).data('languagedefault');
var flag = $('.flag').filterByData('language', defaultLang);
setLang(flag);
});
});
EDIT: Note, if you want the "default" to be selected, simply trigger the click on that "button/flag"
$('#articles').find('.article').find('.myflags').find('button.default').trigger('click');
OR, even on some other language (as an option)
$('.flag').filterByData('language', 'gb').trigger('click');