use multiple image lightboxes on one page without knowing how much - javascript

I'm using a lightbox script which uses a data attribut to know which images are part of a gallery.
To initialize a gallery, I have to do the following:
var selector = 'a[data-imagelightbox="a"]';
var lightbox = $( selector ).imageLightbox({});
If I wan't another gallery on the same page I have to add another:
var selector = 'a[data-imagelightbox="b"]';
var lightbox = $( selector ).imageLightbox({});
I tried to use another selector and the .each function to get it working without writing this 2 code lines for each gallery. But it is not working. The problem is the data attribute groups all images with this attribute to one gallery. If I'm trying it without a, b, c or d - i always get one large gallery and not 3 seperate gallerys.
So, does anybody have a solution how I can use an unknown number of gallerys on one page, without having to define each gallery in Javascript?
I made a JSBIN, so it should be easier to try it out:
http://jsbin.com/goqije/1/
Thanks for your help!

Fixed it myself by doing it this way:
$('ul').each( function() {
var id = $(this).find('a').attr('data-imagelightbox');
var selector = 'a[data-imagelightbox="' + id +'"]';
var lightbox = $( selector ).imageLightbox({
quitOnDocClick: false,
onStart: function() { overlayOn(); closeButtonOn( lightbox ); arrowsOn( lightbox, selector ); },
onEnd: function() { overlayOff(); closeButtonOff(); arrowsOff(); },
onLoadStart: function() { },
onLoadEnd: function() { $( '.imagelightbox-arrow' ).css( 'display', 'block' ); }
});
});

Attribute selector maybe?
instead of doing :
var selector = 'a[data-imagelightbox="b"]';
var lightbox = $( selector ).imageLightbox({});
and
var selector = 'a[data-imagelightbox="b"]';
var lightbox = $( selector ).imageLightbox({});
Just do it with a attribute selector :
var selector = 'a[data-imagelightbox]';
var lightbox = $( selector ).imageLightbox({});
Or even better, you can use a naming convention for all the gallery data attributes as follows:
gallery-1 , galery-2 , gallery-3 and then use a attribute selector as follows:
var selector = 'a[data-imagelightbox^="gallery"]';
var lightbox = $( selector ).imageLightbox({});
Solution two
The above solution seems to have a conflict, here's a slightly different solution that leverages "naming convention" (gallery-1 , gallery-2 ... etc.) and a for loop , see this example here. Notice how I am using a for loop to iterate over all the a elements and turn their color red:
HTML code here:
One
Two
Three
jQuery code here:
$(function () {
str_elm = $('a');
for (var i = 0; i < str_elm.length ; i++) {
data_val = $(str_elm[i]).attr('data-test');
str_temp = "a[data-test=" + '"'+ data_val + '"' + "]";
$(str_temp).css({'color' : 'red'});
};
});
Fiddle here.
You can change the JS as follows to suit your needs:
$(function () {
str_elm = $('a[data-imagelightbox^="gallery"]');
for (var i = 0; i < str_elm.length ; i++) {
data_val = $(str_elm[i]).attr('data-test');
str_temp = "a[data-test=" + '"'+ data_val + '"' + "]";
$(str_temp).imageLightbox({}); // initialization here
};
});

Related

jQuery addClass on user control list

I have a list on a user control and a jquery script that works when an li is clicked. This works fine. I want to change the class on the selected li but having trouble making this work. I tried this in a fiddle and no problem - but in my actual page - no good.
the fiddle is at https://jsfiddle.net/u6sykb8d/7/
the actual jquery script is
$(document).ready(function () {
$('.listButtons li').on("click", function () {
$('.selected').removeClass("selected");
$(this).addClass("selected");
var tabid = $(this).attr('id');
var cont = $(this).closest($(".container"));
var tabs = ["tabAddress", "tabPeople0", "tabPeople1", "tabPeople2", "tabPeople3", "tabPeople4"];
var divs = ["divAddress0", "divPeople_0", "divPeople_1", "divPeople_2", "divPeople_3", "divPeople_4"];
var indx = tabs.indexOf(tabid);
for (var i = 0; i < divs.length; i++) {
if (i == indx) {
cont.find($("div[id$='" + divs[i] + "']")).show();
}
else {
cont.find($("div[id$='" + divs[i] + "']")).hide();
}
}
});
});
the rest of the script works, the lines removing and adding the class don't seem to work.
Any ideas?
embarrassed to say but after digging through the code the problem turned out to be an extra space in the css file 'li .selected' instead of 'li.selected' . Thanks for the help

Bootstrap carousel with thumbnails (Multiple Carousel)

I was looking up how to create a Bootstrap carousel with thumbnails, and I came across this:
http://jsfiddle.net/xuhP9/67/
$('#myCarousel').carousel({
interval: 4000
});
$('[id^=carousel-selector-]').click(function () {
var id_selector = $(this).attr("id");
var id = id_selector.substr(id_selector.length - 1);
id = parseInt(id);
$('#myCarousel').carousel(id);
$('[id^=carousel-selector-]').removeClass('selected');
$(this).addClass('selected');
});
$('#myCarousel').on('slid', function (e) {
var id = $('.item.active').data('slide-number');
id = parseInt(id);
$('[id^=carousel-selector-]').removeClass('selected');
$('[id^=carousel-selector-' + id + ']').addClass('selected');
});
Which works well, however, I need to have multiple carousel in a page, and I am not quite sure how I can accomplish this. I tired to switch the id selector into a class selector so I can create more than one. But I am not sure how to actually fix the JS functionality to make it work since they seem to be blinded together.
Basically, this is what I am trying to accomplish: http://jsfiddle.net/xuhP9/70/ but without repeating the JS for each independent carousel I create.
Thanks in advance!
This method requires your carousels to have ID = myCarousel1, myCarousel2 etc.
and your selectors for the corresponding carousel to be carousel-selector1-1, carousel-selector1-2 ... and carousel-selector2-1, carousel-selector2-2
Updated Fiddle: http://jsfiddle.net/xuhP9/77/
$('.customCarousel').carousel({
interval: 4000
});
// handles the carousel thumbnails
$('[id^=carousel-selector]').click(function () {
var id_selector = $(this).attr("id");
var id = id_selector.substr(id_selector.length - 1);
id = parseInt(id);
var parent = $(this).closest('ul').data('carousel');
$('#myCarousel' + parent).carousel(id);
$('[id^=carousel-selector' + parent +'-]').removeClass('selected');
$(this).addClass('selected');
});
// when the carousel slides, auto update
$('.customCarousel').on('slid', function (e) {
var cont = $(this).data('carousel');
var id = $('#myCarousel'+ cont +' .item.active').data('slide-number');
id = parseInt(id);
$('[id^=carousel-selector' +cont+'-]').removeClass('selected');
$('[id^=carousel-selector'+cont+'-' + id + ']').addClass('selected');
});

Converting Classes All at Once

I have four classes show,hide1,hide2, and hide3. I want to change each of these classes and replace it with the one next to it. In other words, my jQuery code looks like this...
$(".show").removeClass("show").addClass("hide1");
$(".hide1").removeClass("hide1").addClass("hide2");
$(".hide2").removeClass("hide2").addClass("hide3");
$(".hide3").removeClass("hide3").addClass("show");
The problem is that the four classes end up all having the show class which is not what I want. I just want the classes of show to convert to hide1, hide1 convert into hide2, etc. How could I write the code so that those four lines all happen at once, instead of one at a time?
Just select each group first, then alter:
// read
var $show = $('.show');
var $hide1 = $('.hide1');
var $hide2 = $('.hide2');
var $hide3 = $('.hide3');
// write
$show.removeClass('show').addClass('hide1');
$hide1.removeClass('hide1').addClass('hide2');
$hide2.removeClass('hide2').addClass('hide3');
$hide3.removeClass('hide3').addClass('show');
If you save the classes in an array like this:
var classes = ['show','hide1','hide2','hide3'];
You can do fancy stuff like this:
$('.'+classes.join(',.')).attr('class', function(i) {
return classes[i+1] || classes[0];
});​
Demo: http://jsfiddle.net/7DuEV/
Do it this way,
function circulateClass(c){
var i, cl=[];
for(i=0;i<c.length;i++)
cl[c[i]]=$("."+c[i]);
for(i=0;i<c.length;i++)
cl[c[i]].removeClass(c[i]).addClass(c[(i+1)%c.length]));
}
circulateClass(["show","hide1", "hide2", "hide3"]);
Just change the order...
$(".show").removeClass("show").addClass("hide1");
$(".hide3").removeClass("hide3").addClass("show");
$(".hide2").removeClass("hide2").addClass("hide3");
And for the last one, filter by the class name:
$(".hide1").filter(function(){
return !$(this).hasClass('show');
}).removeClass("hide1").addClass("hide2");
jsBin demo
c = 0; // zero based index n (set initial one)
var $el = $( '#parent' ).find( 'div' );
$el.hide().eq( c ).show();
$( '#button' ).click( function() {
$el.hide().eq( ++c % $el.length ).show();
});

create id dynamically

I am creating a element dynamically how would i give this an id?
_addQuestionElement : function() {
var el = new Element('div');
el.addClass('dg-question-label');
el.set('html', this._getCurrentQuestion().label);
$(this.html.el).adopt(el);
},
im using moo tools and jquery.
Many Thanks
Your code looks like Mootools, here's how I'd do it (cleaned up your code a bit)
_addQuestionElement: function() {
var el = new Element('div', {
'class': 'dg-question-label',
html: this._getCurrentQuestion().label,
id: 'yourId'
});
$(this.html.el).adopt(el);
}
If you're generating the same element multiple times, your id will need to somehow be unique each time.
You could also do without that el variable (unless of course it's used somewhere further in the function that you didn't include)
_addQuestionElement: function() {
$(this.html.el).adopt(new Element('div', {
'class': 'dg-question-label',
html: this._getCurrentQuestion().label,
id: 'yourId'
}));
}​
Just assign the id via (if you created the element with new Element()):
var yourCustomId = "myId";
el.id = yourCustomId;
Or use Mootools attr-setting capabilities:
var yourCustomId = "myId";
el.setProperty("id", yourCustomId);
You can give it like this,
var uniqueNumber = 1; //define uniqueNumber globally and increament at each element creation
With javascript
el.id = 'idprefix' + uniqueNumber++)
With jQuery
$(el).attr('id','idprefix' + uniqueNumber++);
In jQuery, to create a div with an ID, you would do something like this:
function createDiv(id) {
$("body").append("<div id=" + id + "></div>");
}
createDiv("myNewDivId");
_addQuestionElement, I think you need to generate a unique id for each question element.
var IDs = 0;
var pfx = "id_";
_addQuestionElement : function() {
...
el.attr("id", pfx + ++IDs);
var el = $('<div />') .attr('id', myVal);
all elements created or accessed by MooTools automatically get a unique uid (for the DOM) anyway, saves you from having to keep state yourself (if you want to be doing this automatically).
console.log( Slick.uidOf( new Element('div') ) )
so...
_addQuestionElement: function() {
var el = new Element('div.dg-question-label', {
html: this._getCurrentQuestion().label
});
// prefix number with uid-
el.set('id', 'uid' + Slick.uidOf(el)).inject(this.html.el);
},
to give it an id via the combined element constructor, it goes:
var el = new Element('div#someid.dg-question-label') or add it in the properties passed to the constructor:
new Element('div', { id: 'foo' })
You can use the jQuery plugin idfy.
Full Disclosure: I wrote that plugin :)

Getting initial selector inside jquery plugin

I got some help earlier regarding selectors, but I'm stuck with the following.
Lets say you have a plugin like this
$('#box').customplugin();
how can I get the #box as a string in the plugin?
Not sure if that's the correct way of doing it, and any other solution would be great as well.
Considering #box is a select dropdown,
The problem I'm having is if I do the regular javascript
$('#box').val(x);
The correct option value gets selected,
but if i try the same inside a plugin
.....
this.each(function() {
var $this = $(this);
$this.val(x);
the last code doesn't really do anything.
I notice I'm having trouble targeting #box inside the plugin because it's a object and not a string...
Any help would be appreciated.
Thanks!
Edit:: Putting in the code I'm working in for better understanding
(function($){
$.fn.customSelect = function(options) {
var defaults = {
myClass : 'mySelect'
};
var settings = $.extend({}, defaults, options);
this.each(function() {
// Var
var $this = $(this);
var thisOpts = $('option',$this);
var thisSelected = $this[0].selectedIndex;
var options_clone = '';
$this.hide();
options_clone += '<li rel=""><span>'+thisOpts[thisSelected].text+'</span><ul>'
for (var index in thisOpts) {
//Check to see if option has any text, and that the value is not undefined
if(thisOpts[index].text && thisOpts[index].value != undefined) {
options_clone += '<li rel="' + thisOpts[index].value + '"><span>' + thisOpts[index].text + '</span></li>'
}
}
options_clone += '</ul></li>';
var mySelect = $('<ul class="' + settings.myClass + '">').html(options_clone); //Insert Clone Options into Container UL
$this.after(mySelect); //Insert Clone after Original
var selectWidth = $this.next('ul').find('ul').outerWidth(); //Get width of dropdown before hiding
$this.next('ul').find('ul').hide(); //Hide dropdown portion
$this.next('ul').css('width',selectWidth);
//on click, show dropdown
$this.next('ul').find('span').first().click(function(){
$this.next('ul').find('ul').toggle();
});
//on click, change top value, select hidden form, close dropdown
$this.next('ul').find('ul span').click(function(){
$(this).closest('ul').children().removeClass('selected');
$(this).parent().addClass("selected");
selection = $(this).parent().attr('rel');
selectedText = $(this).text();
$(this).closest('ul').prev().html(selectedText);
$this.val(selection); //This is what i can't get to work
$(this).closest('ul').hide();
});
});
// returns the jQuery object to allow for chainability.
return this;
}
Just a heads-up: .selector() is deprecated in jQuery 1.7 and removed in jQuery 1.9: api.jquery.com/selector.
– Simon Steinberger
Use the .selector property on a jQuery collection.
Note: This API has been removed in jQuery 3.0. The property was never a reliable indicator of the selector that could be used to obtain the set of elements currently contained in the jQuery set where it was a property, since subsequent traversal methods may have changed the set. Plugins that need to use a selector string within their plugin can require it as a parameter of the method. For example, a "foo" plugin could be written as $.fn.foo = function( selector, options ) { /* plugin code goes here */ };, and the person using the plugin would write $( "div.bar" ).foo( "div.bar", {dog: "bark"} ); with the "div.bar" selector repeated as the first argument of .foo().
var x = $( "#box" );
alert( x.selector ); // #box
In your plugin:
$.fn.somePlugin = function() {
alert( this.selector ); // alerts current selector (#box )
var $this = $( this );
// will be undefined since it's a new jQuery collection
// that has not been queried from the DOM.
// In other words, the new jQuery object does not copy .selector
alert( $this.selector );
}
However this following probably solves your real question?
$.fn.customPlugin = function() {
// .val() already performs an .each internally, most jQuery methods do.
// replace x with real value.
this.val(x);
}
$("#box").customPlugin();
This page talks about getting the selector:
http://api.jquery.com/selector/
That's how I get selector strings inside my plugins in 2017:
(function($, window, document, undefined) {
$.fn._init = $.fn.init
$.fn.init = function( selector, context, root ) {
return (typeof selector === 'string') ? new $.fn._init(selector, context, root).data('selector', selector) : new $.fn._init( selector, context, root );
};
$.fn.getSelector = function() {
return $(this).data('selector');
};
$.fn.coolPlugin = function() {
var selector = $(this).getSelector();
if(selector) console.log(selector); // outputs p #boldText
}
})(jQuery, window, document);
// calling plugin
$(document).ready(function() {
$("p #boldText").coolPlugin();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>some <b id="boldText">bold text</b></p>
The idea is to conditionally wrap jQuery's init() function based on whether a selector string is provided or not. If it is provided, use jQuery's data() method to associate the selector string with the original init() which is called in the end. Small getSelector() plugin just takes previously stored value. It can be called later inside your plugin. It should work well with all jQuery versions.
Because of the deprecation and removal of jQuery's .selector, I have experimented with javascript's DOM Nodes and came up with a 2017 and beyond solution until a better way comes along...
//** Get selector **//
// Set empty variables to work with
var attributes = {}, // Empty object
$selector = ""; // Empty selector
// If exists...
if(this.length) {
// Get each node attribute of the selector (class or id)
$.each(this[0].attributes, function(index, attr) {
// Set the attributes in the empty object
// In the form of name:value
attributes[attr.name] = attr.value;
});
}
// If both class and id exists in object
if (attributes.class && attributes.id){
// Set the selector to the id value to avoid issues with multiple classes
$selector = "#" + attributes.id
}
// If class exists in object
else if (attributes.class){
// Set the selector to the class value
$selector = "." + attributes.class
}
// If id exists in object
else if (attributes.id){
// Set the selector to the id value
$selector = "#" + attributes.id
}
// Output
// console.log($selector);
// e.g: .example #example
So now we can use this for any purpose. You can use it as a jQuery selector... eg. $($selector)
EDIT: My original answer would only get the attribute that appears first on the element. So if we wanted to get the id that was placed after the class on the element, it wouldn't work.
My new solution uses an object to store the attribute information, therefore we can check if both or just one exists and set the required selector accordingly. With thanks to ManRo's solution for the inspiration.

Categories