jQuery own plugin help - refer to wrong element - javascript

I have written a plugin that looks like this so far:
(function($) {
var textarea;
$.fn.bbcode = function(opt)
{
var i = 0;
return this.each(function(i) {
textarea = this;
var strHTML = '<div id="editor" class="editor-instance-' + i + '">';
strHTML += '<div class="btn bold" title="Bold"></div>';
strHTML += '<div class="btn italic" title="Italic"></div>';
strHTML += '<div class="btn underline" title="Underline"></div>';
strHTML += '<div class="btn link" title="Link"></div>';
strHTML += '<div class="btn quote" title="Quote"></div>';
strHTML += '</div>';
$(strHTML).prependTo($(this).parent().parent());
$('div.editor-instance-' + i + ' div').live('click', function(){
var type = $(this).attr('class').substr(4);
switch (type) {
case 'bold':
simpleReplace('b');
break;
}
});
});
};
function simpleReplace(wrapper) {
$(textarea).val(wrapper);
}
})(jQuery);
I call this plugin on 2 textarea's like this:
$(document).ready(function(){
$('.form_add_comment textarea, .form_reply_comment textarea').bbcode({
start: true
});
});
The problem I am having is that clicking on bold which calls simpleReplace() is only setting the value of the 2nd textarea to 'b' despite when I click on the first one.
I think the textarea variable is being overwritten the second time it loops so I probably have my functions in the wrong place.
Any help would be great!

You are right, textarea is overwritten. A solution would be to pass the current textarea to the function:
$('div.editor-instance-' + i + ' div').live('click', {textarea: this}, function(e){
var type = $(this).attr('class').substr(4);
switch (type) {
case 'bold':
simpleReplace(e.data.textarea, 'b');
break;
}
});
Note that the current textarea is passed to the event handler via the event data option.
Then:
function simpleReplace(element, wrapper) {
$(element).val(wrapper);
}
Of course you could also put the simpleReplace function inside the for loop. This way, every textarea gets its "own" simpleReplace function. But this will also increase the memory footprint.

Related

(event.Target === document.getElementById("id")) returns false even though they are pointing at the same element

guys! First time here and thanks for reading in advance.
I have generated some elements dynamically and used event binding to add events to them as shown below.
for(var i = 0, length = list.length || 0; i < length; i++){
str += "<li class = 'mb-2' data-reply_id ='" + list[i].reply_id + "'>";
str += "<div><div class = 'width100 reply_info'><span><strong>" + list[i].replyer +"</strong></span>";
str += "<span><small>" + replyService.formatDate(list[i].reply_date) + "</small></span>";
str += "<button class = 'basic_btn btn btn-primary' id = 'reply_modify'>modify</button><button class = 'basic_btn btn btn-primary' id = 'reply_delete'>delete</button></div>";
str += "<div class='comment-content comment col-md-10 col-sm-9 col-12 width100'><p class = 'fn'>";
str += list[i].reply + "</p></div></div></li>";
}
replyUL.html(str);
$("#comments").on("click", "li", function(e){
var reply_idValue = $(this).data("reply_id");
console.log(reply_idValue);
console.log(e.target);
console.log(typeof(e.target));
console.log("");
console.log(document.getElementById("reply_delete"));
console.log(typeof(document.getElementById("reply_delete")));
if(e.target === document.getElementById("reply_delete")){
console.log("worked!");
if(confirm("Are you sure?")){
replyService.remove(reply_idValue, function(result){
alert(result);
showList(1);
})
}else{
console.log("not working!");
}
But the problem is, (e.target === document.getElementById("reply_delete")) returns false,
even though console.log(e.target); and console.log(document.getElementById("reply_delete")); are returning the same button element(and of course the same type, too).
Does anybody know why this is happening and how to fix this?
Looks like you create multiple elements with the same id. Don't do that - id must be unique. I would suggest to use classes instead:
<button class='basic_btn btn btn-primary reply_delete'>
And then you could write: if (e.target.classList.contains('reply_delete')) { ... }
References: Element.id, Element.classList

Javascript function isn't recognized

I don't have many knowlege in javascript so I don't know what is the problem here,
I create divs dynamically in js and each div call a function when is clicked but the function is not recongized. This is part of the code
for (......) {
var listatema = document.createElement("div");
listatema.innerHTML += "<a href='javascript: void(0)' onClick='functest(" + pag + ")'>" + temat + "</a>";
document.getElementById('menu').appendChild(listatema);}
}
"tema" is a text, the function "functest" has an argument "pag[aux]", this is a number.
The function is:
function functest(arg){
console.log(arg)
}
other alternative that i tried is change that: onClick='"+ functest(pag) +"':
i change the position of Quotation marks "" and the function work good but it is executed when the page is loaded, it don't wait to do click.
Your code should work if you're doing something like:
function functest(arg) {
console.log(arg);
}
for (var i = 0; i < 10; i++) {
var listatema = document.createElement("div");
listatema.innerHTML += "<a href='javascript: void(0)' onClick='functest(" + i + ")'>" + i + "</a>";
document.getElementById('menu').appendChild(listatema);
}
<div id="menu"></div>
I would, however, recommend using addEventListener or setting the onClick handler on the document element object rather than setting the innerHTML. Note that setting innerHTML is not advised, especially when rendering user input. See https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#Security_considerations. In your case, it probably isn't really an issue, but it's good practice to avoid it if you can :)
for (var i = 0; i < 5; i++) {
var wrapper = document.createElement("div");
var listatema = document.createElement("a");
listatema.textContent = i;
listatema.href = "javascript:void(0)";
listatema.addEventListener('click', function(e) {
console.log(this.i);
}.bind({ i : i }));
wrapper.appendChild(listatema);
document.getElementById('menu').appendChild(wrapper);
}
<div id="menu"></div>
onClick='functest(\""+ pag +"\")'
you forgot to quote the parameter.

how do i capture which number <div> got clicked on inside my container <div> and store it in a variable

edit: my code is all held inside a $(document).ready(function() {} because of this, and because my html code is generated inside my javascript file on the fly, i am experiencing issues using .click() when applying the answer that was given to use
$('.movies_cell').click(function(){
var tmp = $(this).index();
});
original:
i have 20 div elements on a page with a class of .movies_cell that are all generated from an ajax file. All of the div's are created within container div called #movies.
any of the .movies_cell div's can be clicked to bring up a modal box, because i am going to place information from my json file in that modal depending on what gets clicked i need to know which div got clicked, for instance, if it was the 5th div i want to know that the 5th div was clicked and then store that number in a variable, if it was the 2nd, or 3rd i want that number to be stored in a variable and then clear when another .movies_cell div gets clicked.
how would i write a javascript or jquery script to accomplish this? :(
thanks!
$('#myMovies').click(function () {
$.getJSON('data/movies.json', function (allData) {
$.each(allData, function (i, field) {
$('#movies').append(function () {
var movies = '<div class="movies_cell">';
movies += '<div class="movies_image">';
movies += '<img src="img/movies/' + (field.image) + '" alt="' + (field.name) + ' Poster" style="width: 100%; height: 100%">';
movies += '</div>';
movies += '<div class="movies_detail">';
movies += '<h1>' + (field.name) + '</h1>';
movies += '<img src="img/rating/' + (field.myRating) + '.png" alt="movie rating" style="margin: auto;">';
movies += '</div>';
movies += '</div>';
counter++;
console.log(counter);
return movies;
});
});
});
});
Use event delegation.(https://api.jquery.com/on#direct-and-delegated-events) At the top
$('#movies').on( "click", ".movies_cell > div", function() {
var tmp = $(".movies_cell > div").index(this);
console.log(tmp);
});
then
$('#myMovies').click(function () {
//rest of code
Can you use .index() ? It is a zero-based index of the collection of items with, for example, class="movies_cell"
$('.movies_cell').click(function(){
var tmp = $(this).index();
});
jsFiddle Demo

Dynamically build Twitter Bootstrap modal

I am building a Rails application, and I want to place the content from a Rails partial into the modal via AJAX.
In a Twitter Bootstrap 2.3.2 modal, I read via the documentation that you can load content via ajax using the remote key.
http://getbootstrap.com/2.3.2/javascript.html#modals
However, this only allows content to be injected into the .modal-body, rather than building the whole modal dynamically.
Is there a way to build the entire modal, including .modal-header, .modal-footer, dynamically with JS?
It seems very clunky to do this with a string, like follows:
partial = render_to_string(:partial => 'some-partial').gsub(%{"}, %{'}).gsub(/'/,"\\\\'").gsub("\n", "")
Update:
Since posting this, I've found an elegant bootstrap 3 modal wrapper function here, which doesn't require adding a div to the html code.
Here's a code sample that demonstrates this. To use, just add a div in your <body> (inside bootstrap's <div class="container">, for example:
<div id="idMyModal"></div>
and then you can use it via:
var header = "This is my dynamic header";
var content = "This is my dynamic content";
var strSubmitFunc = "applyButtonFunc()";
var btnText = "Just do it!";
doModal('idMyModal', header, content, strSubmitFunc, btnText);
To close the modal, issue a call to hideModal, also defined below:
function doModal(placementId, heading, formContent, strSubmitFunc, btnText)
{
var html = '<div id="modalWindow" class="modal hide fade in" style="display:none;">';
html += '<div class="modal-header">';
html += '<a class="close" data-dismiss="modal">×</a>';
html += '<h4>'+heading+'</h4>'
html += '</div>';
html += '<div class="modal-body">';
html += '<p>';
html += formContent;
html += '</div>';
html += '<div class="modal-footer">';
if (btnText!='') {
html += '<span class="btn btn-success"';
html += ' onClick="'+strSubmitFunc+'">'+btnText;
html += '</span>';
}
html += '<span class="btn" data-dismiss="modal">';
html += 'Close';
html += '</span>'; // close button
html += '</div>'; // footer
html += '</div>'; // modalWindow
$("#"+placementId).html(html);
$("#modalWindow").modal();
}
function hideModal()
{
// Using a very general selector - this is because $('#modalDiv').hide
// will remove the modal window but not the mask
$('.modal.in').modal('hide');
}
Update
I recently stumbled upon bootbox.js which is a whole library dedicated to dynamically creating bootstrap modals and reacting to users interaction with them. Though different than the method below, bootbox accepts callbacks rather than a function name. I haven't personally used it yet because I can't justify a 26kb library to essentially do what the function below does. But I thought somebody might find it useful.
Update 8/17/2016
I now use bootbox for pretty much every project I need dynamic modals. Works great a I highly recommend it.
Update 10/1/2018
Bootbox doesn't officially support bootstrap 4 yet but there is a bootbox v5.x branch where they are working on bootstrap 4 support. According to the 5.0.0 roadmap and Bootbox 5.0 ship list ticket it sounds like the branch is pretty much ready to go but they haven't released it yet. But there are some instructions on how to use it. Disclaimer: I have not yet used to v5.x branch and can't vouch for its completeness.
Update 3/25/2019
Bootbox 5.0 was released which supports Bootstrap 4.
Original Post
Code take from Ammon's answer above. Update for bootstrap 3.0
function doModal(placementId, heading, formContent, strSubmitFunc, btnText)
{
html = '<div id="modalWindow" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirm-modal" aria-hidden="true">';
html += '<div class="modal-dialog">';
html += '<div class="modal-content">';
html += '<div class="modal-header">';
html += '<a class="close" data-dismiss="modal">×</a>';
html += '<h4>'+heading+'</h4>'
html += '</div>';
html += '<div class="modal-body">';
html += formContent;
html += '</div>';
html += '<div class="modal-footer">';
if (btnText!='') {
html += '<span class="btn btn-success"';
html += ' onClick="'+strSubmitFunc+'">'+btnText;
html += '</span>';
}
html += '<span class="btn" data-dismiss="modal">';
html += <?php echo "'".__t("Close")."'"; ?>;
html += '</span>'; // close button
html += '</div>'; // footer
html += '</div>'; // content
html += '</div>'; // dialog
html += '</div>'; // modalWindow
$("#"+placementId).html(html);
$("#modalWindow").modal();
$("#dynamicModal").modal('show');
}
This is what I ended up using for my needs. Also includes an event handler for removing the modal from the DOM once it is closed. I just needed an info modal, so I took out the submit function and button text arguments.
function doModal(heading, formContent) {
html = '<div id="dynamicModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirm-modal" aria-hidden="true">';
html += '<div class="modal-dialog">';
html += '<div class="modal-content">';
html += '<div class="modal-header">';
html += '<a class="close" data-dismiss="modal">×</a>';
html += '<h4>'+heading+'</h4>'
html += '</div>';
html += '<div class="modal-body">';
html += formContent;
html += '</div>';
html += '<div class="modal-footer">';
html += '<span class="btn btn-primary" data-dismiss="modal">Close</span>';
html += '</div>'; // content
html += '</div>'; // dialog
html += '</div>'; // footer
html += '</div>'; // modalWindow
$('body').append(html);
$("#dynamicModal").modal();
$("#dynamicModal").modal('show');
$('#dynamicModal').on('hidden.bs.modal', function (e) {
$(this).remove();
});
}
Using DOM, I have created the Button as well as the Bootstrap modal that pops up as soon as the Button is clicked.
Also include these in the head section of HTML page:
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script
src= "https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<script
src= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js">
</script>
Whole of this code needs to be written in JS file.
//Firstly, creating a button which on click displays the Bootstrap Modal
var button = document.createElement("input");
button.className = 'btn btn-info btn-lg';
button.setAttribute("type", "button");
button.setAttribute("data-toggle", "modal");
button.setAttribute("data-target", "#myModal");
button.setAttribute("value", "More Information...");
document.getElementsByTagName('body')[0].appendChild(button);
//MODAL CREATION:
var div1 = document.createElement('div');
div1.id = 'myModal';
div1.className = 'modal fade';
div1.setAttribute("role", "dialog");
var innerDiv1m = document.createElement('div');
innerDiv1m.className = 'modal-dialog modal-sm';
div1.appendChild(innerDiv1m);
var innerDiv2m = document.createElement('div');
innerDiv2m.className = 'modal-content';
innerDiv1m.appendChild(innerDiv2m);
var innerDiv3 = document.createElement('div');
innerDiv3.className = 'modal-header';
innerDiv2m.appendChild(innerDiv3);
var buttonM = document.createElement("button");
buttonM.className = 'close';
buttonM.setAttribute("data-dismiss", "modal");
buttonM.setAttribute("aria-hidden", "true");
buttonM.setAttribute("value", "Close");
innerDiv3.appendChild(buttonM);
var headerM = document.createElement("H4");
headerM.className = 'modal-title';
innerDiv3.appendChild(headerM);
var innerDiv31 = document.createElement('div');
innerDiv31.className = 'modal-body';
innerDiv2m.appendChild(innerDiv31);
var para = document.createElement('p');
innerDiv31.appendChild(para);
para.innerHTML = "paragraph";
var innerDiv32 = document.createElement('div');
innerDiv32.className = 'modal-footer';
innerDiv2m.appendChild(innerDiv32);
var closeButton = document.createElement("input");
closeButton.className = 'btn btn-default';
closeButton.setAttribute("data-dismiss", "modal");
closeButton.setAttribute("type", "button");
closeButton.setAttribute("value", "Close");
innerDiv32.appendChild(closeButton);
document.getElementsByTagName('body')[0].appendChild(div1);
//Therefore, on clicking the created button, the modal pops up on the sreen.
Very similar theme to accepted answer but written as a jQuery plugin. I was looking for some logic to build into a toolkit I'm working up but couldn't find any so wrote this.
There's a lot of code below, but its designed to be written once and then called easily afterwards, so as a spoiler, once you have it all set up it's as easy to use as:
$.fn.alert("utils.js makes this so easy!");
And as a full working example:
https://jsfiddle.net/63zvqeff/
There is no need for any existing <div /> to be on the page, and it works with nested dialogues, its taken from a tool kit I'm working up so I have included all the relevant bits so it's a working copy / paste example.
(function ($)
{
$.utils = {
// http://stackoverflow.com/a/8809472
createUUID: function ()
{
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function")
{
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c)
{
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
}
$.fn.dialogue = function (options)
{
var defaults = {
title: "", content: $("<p />"),
closeIcon: false, id: $.utils.createUUID(), open: function () { }, buttons: []
};
var settings = $.extend(true, {}, defaults, options);
// create the DOM structure
var $modal = $("<div />").attr("id", settings.id).attr("role", "dialog").addClass("modal fade")
.append($("<div />").addClass("modal-dialog")
.append($("<div />").addClass("modal-content")
.append($("<div />").addClass("modal-header")
.append($("<h4 />").addClass("modal-title").text(settings.title)))
.append($("<div />").addClass("modal-body")
.append(settings.content))
.append($("<div />").addClass("modal-footer")
)
)
);
$modal.shown = false;
$modal.dismiss = function ()
{
// loop until its shown
// this is only because you can do $.fn.alert("utils.js makes this so easy!").dismiss(); in which case it will try to remove it before its finished rendering
if (!$modal.shown)
{
window.setTimeout(function ()
{
$modal.dismiss();
}, 50);
return;
}
// hide the dialogue
$modal.modal("hide");
// remove the blanking
$modal.prev().remove();
// remove the dialogue
$modal.empty().remove();
$("body").removeClass("modal-open");
}
if (settings.closeIcon)
$modal.find(".modal-header").prepend($("<button />").attr("type", "button").addClass("close").html("×").click(function () { $modal.dismiss() }));
// add the buttons
var $footer = $modal.find(".modal-footer");
for(var i=0; i < settings.buttons.length; i++)
{
(function (btn)
{
$footer.prepend($("<button />").addClass("btn btn-default")
.attr("id", btn.id)
.attr("type", "button")
.text(btn.text)
.click(function ()
{
btn.click($modal)
}))
})(settings.buttons[i]);
}
settings.open($modal);
$modal.on('shown.bs.modal', function (e) {
$modal.shown = true;
});
// show the dialogue
$modal.modal("show");
return $modal;
};
})(jQuery);
I then wrote a helper function for those times when you just wanted a basic alert()
(function ($)
{
$.fn.alert = function (message)
{
return $.fn.dialogue({
title: "Alert",
content: $("<p />").text(message),
closeIcon: true,
buttons: [
{ text: "Close", id: $.utils.createUUID(), click: function ($modal) { $modal.dismiss(); } }
]
});
};
})(jQuery);
Otherwise you need to build your content as a jQuery object and then pass it in in the form of an object like:
{
title: "", // what ever you want in the title bar
content: $("<p />"), // any DOM structure you can build as a jQuery object
closeIcon: false, // does the dialogue have a X in the tilte bar to close it
id: $.utils.createUUID(), // a reference id
open: function () { }, // a function called after the DOM structure is built but BEFORE rendering
buttons: [ // an array of buttons to include in the footer
// example "close" button, all buttons get a reference to $modal passed into them
// .dismiss() is a function attached to $modal to revert the DOM changes
{ text: "Close", click: function ($modal) { $modal.dismiss(); } }
]
};
I had the same problem, after researching a lot, I finally built a js function to create modals dynamically based on my requirements. Using this function, you can create popups in one line such as:
puyModal({title:'Test Title',heading:'Heading',message:'This is sample message.'})
Or you can use other complex functionality such as iframes, video popups, etc.
Find it on https://github.com/aybhalala/puymodals For demo, go to http://pateladitya.com/puymodals/

Jquery reading input field that was created from JSON loop

I cannot figure out for the life of me why this will not work. I am trying to pull the value of a textfield that was created with a loop from a json file.
In this code, at the very bottom I just do a simple click(function() {alert()} just to see if I can pull a value and its returning undefined. But if I remove '#name' and put in 'input' it captures it, but only for the first of several input fields.
Any help is really appreciated
JSON
{
"Controls": [{
"Button":[{ "Name":"Button", "x": "1","y": "2","width": "3","height": "4","Transition":"" }],
"Image":[{"x": "5","y": "6","width": "7","height": "8"}],
"TextField":[{"x": "9","y": "10","width": "11","height": "12","Rows":""}]
}]
}
The Code(there is soome getJSON stuff above this)
//Slide In Attributes Panel Based on Selected Object
$(document).on('click', '#code li', function () {
var index = $('#code li').index(this);
var selected = $(this).text();
switch (selected) {
case selected:
$('#options').hide();
hidePanels();
$('#temp').remove();
$('#objectAttributes').show("slide", 200);
break;
//If it does work show what variable is being used
default:
alert(selected);
break;
}
//Shows Selected LI Index
$('#codeIndex').text("That was div index #" + index);
//Pull list of Attributes for selected Object
$.getJSON('controls.json', function (data) {
//Build Attributes List
var attributeList = '<div id="temp">';
//Target based on selected object
var target = selected;
attributeList += '<div>' + target + '<div>';
$.each(data.Controls[0][target][0], function (kk, vv) {
attributeList += '<div style="float:right">' + kk + ':' + '<input type="text" id='+ kk + '>' + '</input>' + '</div>';
});
attributeList += '</div></div>';
attributeList += '</div>';
$('#objectAttributes').append(attributeList);
$('#temp').append('<div id="editIndex">'+"Modifying index" + " " +index+'</div>');
$(document).on('click', '#saveAttributes', function () {
var $x = $('#name').val();
alert($x);
})
});
});
Ok, so after a little hacking around with a jsfiddle the answer turned out to be a lot simpler than I first thought. Ever since HTML 4.01 class names and IDs have been case sensitive (reference), which means that your selector $('#name') wasn't matching the JSON Name.
So a simple change, such as in this simplified jsfiddle seems to work as desired. Hopefully this helps!

Categories

Resources