I am trying to loop functionality for buttons I've made. I have 3 video collections. and they all need the same script for next and previous.
What I want is that I only have to make one next button and one prev button.
This is what it should do:
$("#next-1").click(function(){
var $this = $(".video-album-1");
callback = function() {
$this.insertBefore($this.siblings(':eq(2)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
$("#prev-1").click(function(){
var $this = $(".video-album-1");
callback = function() {
$this.insertAfter($this.siblings(':eq(3)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
$("#next-2").click(function(){
var $this = $(".video-album-2");
callback = function() {
$this.insertBefore($this.siblings(':eq(2)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
$("#prev-2").click(function(){
var $this = $(".video-album-2");
callback = function() {
$this.insertAfter($this.siblings(':eq(3)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
I've already tried to loop it, but this doesn't work:
for (i = 0; i < 3; i++) {
$("#next-"+i).click(function(){
var $this = $(".video-album-"+i);
callback = function() {
$this.insertBefore($this.siblings(':eq(2)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
$("#prev-"+i).click(function(){
var $this = $(".video-album-"+i);
callback = function() {
$this.insertAfter($this.siblings(':eq(3)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
}
Is there anyone that could tell me a solution? I do not want to repeatedly create #next-3 #next-4 ids etc..
Thanks in advance.
Can you take a look at below approach:
$("[id^=next-]").click(function(){
var current_id = $(this).attr("id");
var number = current_id.replace("next-","");
var $this = $(".video-album-"+number);
callback = function() {
$this.insertBefore($this.siblings(':eq(2)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
$("[id^=prev-]").click(function(){
var current_id = $(this).attr("id");
var number = current_id.replace("prev-","");
var $this = $(".video-album-"+number);
callback = function() {
$this.insertAfter($this.siblings(':eq(3)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
Here we are using jQuery's starts with selector to attach the event to required DOM elements and within event handler we are grabbing the associated number for further process.
Use a class with next(),prev(),find() to get the video album class based on the next/prev elements or use this hack
$('[id^="next-"]').click(function(){
var i = $(this).attr('id').split('-')[1];
var $this = $(".video-album-"+i);
callback = function() {
$this.insertBefore($this.siblings(':eq(2)'));
}
$this.fadeOut(200, callback).fadeIn(400);
});
$('[id^="prev-"]').click(function(){
var i = $(this).attr('id').split('-')[1];
var $this = $(".video-album-"+i);
callback = function() {
$this.insertAfter($this.siblings(':eq(3)'));
}
$this.fadeOut(200, callback).fadeIn(400);
I'll emphasize now this is just one way, there might be better ones
Assuming these are your buttons
<button class="next" data-videocollectionname="video1">next</button>
<button class="next" data-videocollectionname="video2">next</button>
<button class="next" data-videocollectionname="video3">next</button>
<button class="previous" data-videocollectionname="video1">previous</button>
<button class="previous" data-videocollectionname="video2">previous</button>
<button class="previous" data-videocollectionname="video3">previous</button>
I've given each button a data attribute to say which collection the button is relevant too.
Forgive me if I've miss understood the question
$(".next").click(function(){
var videoCollectionName = $(this).data("videocollectionname");
var videoElement = $("#"+videoCollectionName);
//do whatever code you want for the videocollection
});
$(".previous").click(function(){
var videoCollectionName = $(this).data("videocollectionname");
var videoElement = $("#"+videoCollectionName);
//do whatever code you want for the videocollection
});
This question and its answers explain why your attempt didn't work correctly.
Based on your attempted for loop, this will work:
$("[id^=next-]").click(function() {
var i = this.id.substring(5);
var album = $(".video-album-" + i);
callback = function() {
album.insertBefore(album.siblings(':eq(2)'));
};
album.fadeOut(200, callback).fadeIn(400);
});
$("[id^=prev-]").click(function() {
var i = this.id.substring(5);
var album = $(".video-album-" + i);
callback = function() {
album.insertAfter(album.siblings(':eq(3)'));
};
album.fadeOut(200, callback).fadeIn(400);
});
That works by using an attribute starts with selector to match all of your next- (and prev-) buttons, then figures out the index from the id of the button actually clicked.
But there's probably a better answer we could give you if you quote your HTML.
Related
I want to loop my click events, to make the code shorter. I might have 30 of these values later on.
My working code
$(document).ready(function () {
var last_click = '';
$("#title").click(function() { last_click = 'title'; });
$("#subtitle").click(function() { last_click = 'subtitle'; });
$("#test").click(function() { last_click = 'test'; });
});
This is how I want it (not working)
My guess is that the each-loop runs on dom ready and then never again and that way the click-event can never be triggered?
$(document).ready(function () {
var last_click = '';
var contents = new Array();
contents = ['title', 'subtitle', 'test'];
$.each(contents , function(index, value){
$("#" + value).click(function() { last_click = value; });
});
});
If there is not solved like I would, I would be thankful for a nice workaround.
I would rather add a class to all elements you want to bind this to, eg class="last-click"
and define the binding once as:
$(".last-click").on('click', function() {
last_click = this.id;
}
If you really wanted to make it shorter, give them all a similar class.
$(document).ready(function () {
var last_click = '';
$(".theclass").click(function() {
last_click = this.id;
});
});
if you have value attribute for your buttons or elements, you can do it:
$(document).ready(function() {
var last_click = '';
$("input").click(function() {
last_click = $(this).attr('value');
alert(last_click);
});
});
I assumed that you are using "input type="button". Also here is the demo you can see it in action: http://jsfiddle.net/rS2Gb/5/
I have two click-events, that are nearly similar, but not quite. I am wondering how to refactor them best:
$('.remove_fields.dynamic').live('click', function(e) {
var $this = $(this);
var after_removal_trigger_node = $this.closest(".nested-fields").parent();
trigger_removal_callback($this);
e.preventDefault();
$this.closest(".nested-fields").remove();
trigger_after_removal_callback(after_removal_trigger_node);
});
$('.remove_fields.existing').live('click', function(e) {
var $this = $(this);
var after_removal_trigger_node = $this.closest(".nested-fields").parent();
trigger_removal_callback($this);
e.preventDefault();
$this.prev("input[type=hidden]").val("1");
$this.closest(".nested-fields").hide();
trigger_after_removal_callback(after_removal_trigger_node);
});
As you can tell there is a fair bit of overlap. I am wondering what the best/nicest way would be to refactor this code.
Do a class check in the .remove_fields click function.
$('.remove_fields').click(function(e) {
var $this = $(this);
var after_removal_trigger_node = $this.closest(".nested-fields").parent();
trigger_removal_callback($this);
e.preventDefault();
if($this.hasClass("dynamic") {
$this.closest(".nested-fields").remove();
} else if($this.hasClass("existing")) {
$this.prev("input[type=hidden]").val("1");
$this.closest(".nested-fields").hide();
}
trigger_after_removal_callback(after_removal_trigger_node);
});
Combine the selectors into $('.remove_fields.dynamic, .remove_fields.existing').
Then, test if $this has class existing. If so, run $this.prev("input[type=hidden]").val("1");.
Done.
taking cleaning a bit more:
$('.remove_fields').click(function(e) {
e.preventDefault();
var $this = $(this);
var $nestedFields = $this.closest(".nested-fields");
trigger_removal_callback($this);
if($this.hasClass("dynamic") {
$nestedFields.remove();
} else if($this.hasClass("existing")) {
$this.prev("input[type=hidden]").val("1");
$nestedFields.hide();
}
trigger_after_removal_callback($nestedFields.parent());
});
I'm trying to add some functionality to be able to edit comments inline. So far it's pretty close, but I'm experiencing issues trying to trigger a second event. It works the first time, but after that, fails.
$(function() {
var $editBtn = $('.js-edit-comment-btn');
var clicked = false;
$editBtn.on('click', $editBtn, function() {
clicked = true;
var $that = $(this);
var $form = $that.closest('.js-edit-comment');
var $commentTextBody = $that.closest('div').find('.js-comment-body');
var commentText = $commentTextBody.text();
var $editableText = $('<textarea />');
if ($that.text() === 'Save Edits') {
$that.text('Saving...').attr('disabled', true);
} else {
$that.text('Save Edits').attr('alt', 'Save your edits');
}
// Replace div with textarea, and populate it with the comment text
var makeDivTextarea = function($editableText, commentText, $commentTextBody) {
$editableText.val(commentText);
$commentTextBody.replaceWith($editableText);
$editableText.addClass('gray_textarea js-edited-comment').width('100%').css('padding', '4px').focus();
};
makeDivTextarea($editableText, commentText, $commentTextBody);
var saveEdits = function($that, $editableText) {
$that.on('click', $that, function() {
if (clicked) {
var comment = $that.closest('div').find('.js-edited-comment').val();
$editableText.wrap('<div class="js-comment-body" />').replaceWith(comment);
$that.text('Edit').attr('alt', 'Edit Your Comment').attr('disabled', false);
$('#output').append('saved');
clicked = false;
return false;
}
});
};
saveEdits($that, $editableText);
return false;
});
});
jsfiddle demo here
Hiya demo for your working solution: http://jsfiddle.net/8P6uz/
clicked=true was the issue :)) I have rectified another small thing. i.e. $('#output') is set to empty before appending another saved hence text **saved** will only appear once.
small note: If I may suggest use Id of the button or if there are many edit buttons try using this which you already i reckon; I will see if I can write this more cleaner but that will be sometime latter-ish but this should fix your issue. :) enjoy!
Jquery Code
$(function() {
var $editBtn = $('.js-edit-comment-btn');
var clicked = false;
$editBtn.on('click', $editBtn, function() {
clicked = true;
var $that = $(this);
var $form = $that.closest('.js-edit-comment');
var $commentTextBody = $that.closest('div').find('.js-comment-body');
var commentText = $commentTextBody.text();
var $editableText = $('<textarea />');
if ($that.text() === 'Save Edits') {
$that.text('Saving...').attr('disabled', true);
} else {
$that.text('Save Edits').attr('alt', 'Save your edits');
}
// Replace div with textarea, and populate it with the comment text
var makeDivTextarea = function($editableText, commentText, $commentTextBody) {
$editableText.val(commentText);
$commentTextBody.replaceWith($editableText);
$editableText.addClass('gray_textarea js-edited-comment').width('100%').css('padding', '4px').focus();
};
makeDivTextarea($editableText, commentText, $commentTextBody);
var saveEdits = function($that, $editableText) {
$that.on('click', $that, function() {
if (clicked) {
var comment = $that.closest('div').find('.js-edited-comment').val();
$editableText.wrap('<div class="js-comment-body" />').replaceWith(comment);
$that.text('Edit').attr('alt', 'Edit Your Comment').attr('disabled', false);
$('#output').text("");
$('#output').append('saved');
clicked = true;
return false;
}
});
};
saveEdits($that, $editableText);
return false;
});
});
I am using the ajaxify.js plugin https://github.com/browserstate/ajaxify to load content dynamically.
I have a number of click functions that I bind on document ready, but have to additionally put those functions inside of my ajax load function to re-bind the click events to the newly added content. I had tried using a single set of live functions previously but they didn't work.
Anyway I have the following code twice, once inside of a document.ready(function(){ }) and once again inside of ajaxify.js after the content loads.
I know it's superfluous, but I'm not sure of how to go about writing the functions just once so I can "include" them elsewhere. How can I optimize these functions so I can consolidate them and use them over again in an efficient manner?
Thank you!
var $filterclear = $('.filters .filter-clear'),
filtercount = $filterclear.length,
$searchedfor = $('.searched-for'),
is_search = $searchedfor.length;
$filterclear.bind('click', function(){
var $me = $(this);
if(filtercount == 3) {
$('.clear-all.filter-clear').addClass('filter-out').fadeOut('fast');
$(this).addClass('filter-out').fadeOut('fast');
} else {
$(this).addClass('filter-out').fadeOut('fast');
}
if($me.hasClass('clear-all') || filtercount == 1) {
$filterclear.addClass('filter-out').fadeOut('fast');
if(is_search !== 0) {
$('.filters').fadeOut();
}
}
});
$('.tag.remove-term').bind('click', function(){
var $me = $(this),
mytext = $me.text(),
$myfilter = $('.filters .filter-clear:contains("'+ mytext +'")');
if(filtercount == 3) {
$('.clear-all.filter-clear').addClass('filter-out').fadeOut('fast');
$myfilter.addClass('filter-out').fadeOut('fast');
} else {
$myfilter.addClass('filter-out').fadeOut('fast');
}
});
$searchedfor.find('.filter-clear').bind('click',function(){
$searchedfor.fadeOut();
});
Defining a new function should work (I didn't test it):
var $filterclear = $('.filters .filter-clear'),
filtercount = $filterclear.length,
$searchedfor = $('.searched-for'),
is_search = $searchedfor.length;
var doSomething($myfilter) {
if(filtercount == 3) {
$('.clear-all.filter-clear').addClass('filter-out').fadeOut('fast');
}
$myfilter.addClass('filter-out').fadeOut('fast');
};
$filterclear.bind('click', function() {
var $me = $(this);
doSomething($me);
if($me.hasClass('clear-all') || filtercount == 1) {
$filterclear.addClass('filter-out').fadeOut('fast');
if(is_search !== 0) {
$('.filters').fadeOut();
}
}
});
$('.tag.remove-term').bind('click', function(){
var $me = $(this),
mytext = $me.text(),
$myfilter = $('.filters .filter-clear:contains("'+ mytext +'")');
doSomething($me);
});
$searchedfor.find('.filter-clear').bind('click',function(){
$searchedfor.fadeOut();
});
I have some jQuery plugin that changes some elements, i need some event or jQuery plugin that trigger an event when some text input value changed.
I've downloaded jquery.textchange plugin, it is a good plugin but doesn't detect changes via external source.
#MSS -- Alright, this is a kludge but it works:
When I call boxWatcher() I set the value to 3,000 but you'd need to do it much more often, like maybe 100 or 300.
http://jsfiddle.net/N9zBA/8/
var theOldContent = $('#theID').val().trim();
var theNewContent = "";
function boxWatcher(milSecondsBetweenChecks) {
var theLoop = setInterval(function() {
theNewContent = $('#theID').val().trim();
if (theOldContent == theNewContent) {
return; //no change
}
clearInterval(theLoop);//stop looping
handleContentChange();
}, milSecondsBetweenChecks);
};
function handleContentChange() {
alert('content has changed');
//restart boxWatcher
theOldContent = theNewContent;//reset theOldContent
boxWatcher(3000);//3000 is about 3 seconds
}
function buttonClick() {
$('#theID').value = 'asd;lfikjasd;fkj';
}
$(document).ready(function() {
boxWatcher(3000);
})
try to set the old value into a global variable then fire onkeypress event on your text input and compare between old and new values of it. some thing like that
var oldvlaue = $('#myInput').val();
$('#myInput').keyup(function(){
if(oldvlaue!=$('#myInput').val().trim())
{
alert('text has been changed');
}
});
you test this example here
Edit
try to add an EventListner to your text input, I don't know more about it but you can check this Post it may help
Thanks to #Darin because of his/her solution I've marked as the answer, but i have made some small jQuery plugin to achieve the same work named 'txtChgMon'.
(function ($) {
$.fn.txtChgMon = function (func) {
var res = this.each(function () {
txts[0] = { t: this, f: func, oldT: $(this).val(), newT: '' };
});
if (!watchStarted) {
boxWatcher(200);
}
return res;
};
})(jQuery);
var txts = [];
var watchStarted = false;
function boxWatcher(milSecondsBetweenChecks) {
watchStarted = true;
var theLoop = setInterval(function () {
for (var i = 0; i < txts.length; i++) {
txts[i].newT = $(txts[i].t).val();
if (txts[i].newT == txts[i].oldT) {
return; //no change
}
clearInterval(theLoop); //stop looping
txts[i].f(txts[i], txts[i].oldT, txts[i].newT);
txts[i].oldT = $(txts[i].t).val();
boxWatcher(milSecondsBetweenChecks);
return;
}
}, milSecondsBetweenChecks);
}