Getting the collection in a jQuery plugin - javascript

Basically, what I am trying to do is create a bbcode editor with a textbox, some buttons and jQuery. Here is my form:
<div class="form-group">
<div class="btn-group btn-group-sm">
<button type="button" class="btn glyphicon bbcode" rel="bold"><b>B</b></button>
<button type="button" class="btn glyphicon bbcode" rel="italic"><i>I</i></button>
</div>
</div>
<div class="form-group">
<textarea class="bbcode" rel="editor" cols="100" rows="12"></textarea>
</div>
and my plugin is called using:
<script>
$('document').ready(function() {
$('.bbcode').bbcode();
});
</script>
and the plugin itself, I am just trying to get the basics done at the minute to update the textbox data when a button is clicked:
(function($) {
"use strict";
$.fn.bbcode = function() {
this.click(function() {
var rel = $(this).attr('rel');
if (rel == 'editor') {
return this;
} else {
alert($(this).attr('rel')); // I can see this pop up so the click event is firing
$('.bbcode[rel=editor]').val('test');
return this;
}
});
}
} (jQuery));
This seems to be the only way I can pick up the textbox, I don't really want to hardcode the class I want like that. I think what I am looking for is a way to get the collection from the function call in the script tags.
This is more than likely something stupid/obvious I have overlooked.

The value of this in the immediate function refers to the collection. However, it is shadowed by the this inside your click handler (which refers to the element being clicked) so you cannot access it.
Create a variable to store this and that'll be your collection.
(function ($) {
"use strict";
$.fn.bbcode = function () {
var $editors = this;
this.click(function () {
var rel = $(this).attr('rel');
if (rel == 'editor') {
return this;
} else {
alert($(this).attr('rel')); // I can see this pop up so the click event is firing
$editors.val('test');
return this;
}
});
}
}(jQuery));

Related

Why my plugin fires multipe callback or clicks

I am creating my simple jQuery plugin that can be use to attach for any action's confirmation. But facing very strange issue, It work fine for single element click, But when i am going to click for second element which also bind with my plugin it work fine but it's also fires for previous clicked element as well.
(function ($) {
$.fn.BootConfirm = function (options) {
// Establish our default settings
var settings = $.extend({
message: 'Are you sure about this ?',
complete: null
}, options);
var self = this;
var cointainer = '\
<div class="modal fade" id="confirmBoot" role="dialog" aria-labelledby="confirmDeleteLabel" aria-hidden="true">\
<div class="modal-dialog">\
<div class="modal-content">\
<div class="modal-header">\
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>\
<h4 class="modal-title">Confirm action</h4>\
</div>\
<div class="modal-body">\
<p>Are you sure about this ?</p>\
</div>\
<div class="modal-footer">\
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>\
<button type="button" class="btn btn-success btn-ok" id="confirm">Ok</button>\
</div>\
</div>\
</div>\
</div>';
return this.each(function () {
var self = this;
$(this).click(function () {
if (!$('#confirmBoot').length) {
$('body').append(cointainer);
}
if (settings.message) {
$('#confirmBoot').find('.modal-body').text($(this).attr('data-confirm'));
}
$('#confirmBoot').modal({ show: true });
if ($.isFunction(settings.complete)) {
$('#confirmBoot').find('.btn-ok').click(function () {
$.when(settings.complete.call(this, self)).done(function () {
$('#confirmBoot').modal("hide"); // Alerts "123"
});
});
}
});
});
}
}(jQuery));
This is my callback function :
function kaushik(myObject) {
ManageAcriveProducts(myObject);
};
and i am calling it by following way
$('a[data-confirm]').BootConfirm({
complete: kaushik
});
For more detail check this js fidder Jsfiddle. Can anyone one share possible solution or better way to do this. Or is there any better way to achieve this ?
The problem is that you're assigning a click on your btn-ok on every click event on a bootconfirmed object. And each click is linked to the object that has been clicked, so it ends up in your callback every time you click btn-ok.
One simple fix, though I'm not sure it's the best, is to remove the click on your btn-ok after the action is complete. Like this:
$.when(settings.complete.call(this, self)).done(function () {
$('#confirmBoot').modal("hide");
$('#confirmBoot').find('.btn-ok').off('click');
});
Working fiddle: http://jsfiddle.net/ywunutyw/
EDIT:
A little improvement on previous solution, it might need some adjustments, since I didn't look into details, but it should give you some ideas. To prevent adding click events and removing them every time user clicks on a button, you can define the click on modal window outside click behavior of each active/inactive button. And on click of active/inactive you define target that will be used in modal confirmation. Like this:
Just before calling behaviors with this.each:
$(document).on('click', '#confirmBoot .btn-ok',
function (e) {
if ($.isFunction(settings.complete)) {
console.log(self)
$.when(settings.complete.call(this, click_origin)).done(function () {
$('#confirmBoot').modal("hide");
});
}
});
Then on the click event of you active/inactive:
click_origin = e.target;
See fiddle: http://jsfiddle.net/ywunutyw/1/

Using the same jQuery functions but causing conflicts in HTML

Title - Sorry about the title, it was difficult for me to actually explain this.
So I recently finished working on a dynamic fields system using jQuery. This is all working great however I'm wanting to re-use the html for the system over and over again on the same page, this causes problems.
Problem
- When you have duplicates of the form on the same page, and you press 'Add Field' it will run the function and apply the functions to the other classes on the page. (See fiddle for example.)
When you just have one form on the DOM it works fine, but I'm wanting to alter the html slightly so I can use it for different scenarios on a page. I don't want to have separate jQuery files to do this because I don't think it's necessary. I was thinking maybe I could target it's parent containers instead of the class directly? Then I could recycle the same code maybe?
Any suggestions on this guys?
HTML:
<form action="javascript:void(0);" method="POST" autocomplete="off">
<button class="add">Add Field</button>
<div class='input_line'>
<input type="text" name="input_0" placeholder="Input1">
<input type="button" class="duplicate" value="duplicate">
<input type="button" class="remove" value="remove">
</div>
</form>
JQUERY:
$(document).ready(function () {
'use strict';
var input = 1,
blank_line = $('.input_line'),
removing = false;
$('.remove').hide();
$('.add').click(function () {
var newElement = blank_line.clone(true).hide();
$('form').append(newElement);
$(newElement).slideDown();
$('.remove').show();
});
$('form').on('click', '.duplicate', function () {
$(this).parent().clone().hide().insertAfter($(this).parent().after()).slideDown();
$('.input_line').last().before($('.add'));
$('.remove').show();
input = input + 1;
});
$('form').on('click', '.remove', function () {
if (removing) {
return;
} else {
if ($('.input_line').length <= 2) {
$('.remove').hide();
}
$(this).parent().slideUp(function () {
$(this).remove();
removing = false;
});
$('.input_line').last().before($('.add'));
input = input - 1;
}
removing = true;
});
});
Working fiddle - JSFiddle
Problem fiddle - JSFiddle
As you can see in the problem fiddle above, when you duplicate the form it start conflicting. I would like each form to work independently.
Any help would be greatly appreciated!
You need to use closest('form') to find the associated form. Also when looking up the other fields, you need to search within the context of the related form, http://jsfiddle.net/95vaaxsL/7/
function addLine($inputLine) {
var $form = $inputLine.closest('form');
var $newElement = $inputLine.clone(true).hide();
$newElement.insertAfter($inputLine);
$newElement.slideDown();
$form.find('.remove').show();
}
$(document).ready(function () {
'use strict';
$('.remove').hide();
$('.add').click(function () {
addLine($(this).closest('form').find('.input_line:last'));
});
$('form').on('click', '.duplicate', function () {
addLine($(this).closest('.input_line'));
});
$('form').on('click', '.remove', function () {
var $inputLine = $(this).closest('.input_line');
var $form = $inputLine.closest('form');
if ($form.find('.input_line').length < 3) {
$form.find('.remove').hide();
}
$inputLine.slideUp(function(){
$inputLine.remove();
});
});
});
Pulled out the function.

Why would an actual mouse click not work, but doing .click() in the JS console does?

When I try to execute some JS, by clicking a button, it doesn't do what I want it to. However, when I fire up the JS console and execute it manually it works.
Here is my entire JS file (included just in case there is a conflict):
var ready;
ready = function() {
// This is the Sidebar toggle functionality that I am most interested in
var toggleSidebar = $("#togglesidebar");
var primary = $("#primary");
var secondary = $("#secondary");
toggleSidebar.on("click", function(){
if(primary.hasClass("col-xs-9")){
primary.removeClass("col-xs-9");
primary.addClass("col-xs-12");
secondary.css('display', 'none');
}
else {
primary.removeClass("col-xs-12");
primary.addClass("col-xs-9");
secondary.css('display', 'inline-block');
}
});
};
$(document).ready(ready);
$(document).on('page:load', ready);
counter = function() {
var body_value = $('#post_body').val();
var title_value = $('#post_title').val();
if (body_value.length == 0) {
$('#wordCountBody').html(0);
$('#totalCharsBody').html(0);
return;
}
if (title_value.length == 0) {
$('#wordCountTitle').html(0);
return;
}
var regex = /\s+/gi;
var wordCountBody = body_value.trim().replace(regex, ' ').split(' ').length;
var totalCharsBody = body_value.length;
var wordCountTitle = title_value.trim().replace(regex, ' ').split(' ').length;
$('#wordCountBody').html(wordCountBody);
$('#totalCharsBody').html(totalCharsBody);
$('#wordCountTitle').html(wordCountTitle);
};
$(document).ready(function () {
$('#count').click(counter);
$('#post_body, #post_title').on('change keydown keypress keyup blur focus', counter);
$('body').tooltip({ selector: "[data-toggle~='tooltip']"});
});
Here is the HTML being triggered:
<div class="hidden-xs col-sm-3 masthead-group-3 pull-left">
<div id="togglesidebar" class="pull-right">
<button class="btn btn-default btn-lg btn-primary"><i class="fa fa-child"></i> Submit News</button>
</div>
</div>
Yet, when I go to my console and do this it works perfectly:
$("#togglesidebar");
[<div id=​"togglesidebar" class=​"pull-right">​…​</div>​]
$("#togglesidebar").click();
[<div id=​"togglesidebar" class=​"pull-right">​…​</div>​]
You can see it live here.
You have two buttons with the same id.
jQuery # selector find only the first match of that id, so the first button that is hidden.
Delete it or change it's name and it should works ;-)
Edit:
You can also change them to a .className rather than an id and all the respective references to classes and it should work.

How to reference button in jQuery?

In the HTML, I have a button defined like this:
<button type="button" onclick="toggleEdit();">Edit</button>
At the end of the page, I have this script I am working on:
<script language="JavaScript">
<!--
function toggleEdit() {
var btn = $(this);
var li = btn.parent();
var textArea = li.children('.readOnly');
...
}
//-->
</script>
I cannot reference the button I have clicked in the script. The btn variable is an object, but I don't know anything else than that.
I found many examples on the internet that are using this approach:
$(document).ready(function () {
$('#buttonID').click(function () {
...
but I cannot reference the button via ID because it is added dynamically. So, how do I reference it? Thanks.
Just to keep it your way, you have to tell the code that this will refer to the button instead of the actual function.
To do this you can just add an extra argument to the toggleEdit function.
The new HTML would look like this (no apply or call function needed):
<button type="button" onclick="toggleEdit(this);">Edit</button>
Then your new JavaScript would look like this:
<script language="JavaScript">
<!--
function toggleEdit(t) {
var btn = $(t);
var li = btn.parent();
var textArea = li.children('.readOnly');
...
}
//-->
</script>
You can pass the event into the function, and then use that.
<button type="button" onclick="toggleEdit( event );">Edit</button>
Then in your function, you can get the target of the event:
function toggleEdit( e ) {
var btn = $( e.target );
var li = btn.parent();
var textArea = li.children('.readOnly');
...
}

How can I manipulate dynamically created elements wth jquery?

I am a jquery newbie and i am creating boxes with jquery and then "deleting" them. But I want to use the same code to delete the box in the scope of the created element and the scope of a already created element.
Html:
<button id="create">Cria</button>
<div id="main">
<div class="box">
<a class="del-btn" href="#">Delete</a>
</div>
</div>
JS:
var box = {
create: function() {
var box = $('<div class="box">');
var delBtn = $('<a class="del-btn" href="#">Delete</a>');
box.appendTo('#main');
delBtn.appendTo(box);
},
destroy: function(elem) {
elem.fadeOut();
}
}
function deleteBox () {
}
$(function() {
$('#create').click(function() {
box.create();
});
$('.del-btn').click(function() {
var elem = $(this).parent();
box.destroy(elem);
return false;
});
});
If I put the delete event inside the create click event, I just can delete the dynamically created element. If I put it outside, then I can just delete the element in the HTML. I know this is a simple question, but I can't figure out how to solve it. Thanks
You can use delegated-events approach:
$("#main").on("click", ".del-btn", function() {
var elem = $(this).parent();
box.destroy(elem);
return false;
});

Categories

Resources