How to bind events to dynamically created JQuery DOM elements - javascript

I'm having trouble referencing an object from within the plugin I'm attempting to make.
The plugin is assosciated with a div container.
When the dom is ready it loads in startup defaults - creates its own div with id's it knows and an un ordered list. I can add list items and they work correctly using $this.append(..). However I want to add a feature where a click on an individual list item does something.. for now alert will suffice.
Normally I would be able to do:
$("#myId").click(function(){...
How would i add such functionality to a plugin?
I want that action set by the plugin itself, so clicking on list items created by the plugin are already attached to some functionality which I have written into the jquery plugin.

Based on your comment, you could store the new tab in a variable:
var newTab = $("<li id='tab#" + o.tabCount + "' myTabPane='" +
o.tabId + o.tabCount + "' class='tab'><h3>Tab " + o.tabCount
+ "</h3></li>");
$('#' + o.tabListId).append(newTab);
newTab.click(function() {
var paneId = '#' + $(this).attr('myTabPane');
$(paneId).siblings().hide();
$(paneId).show();
});
Link to working example at jsfiddle.
By the way, your original script had the second ' in the wrong place:
$("<li id='tab#'" + o.tabCount + " class='tab'><h3>Tab "
^^^

You would want to reference them after doing the append by tag name not by ID.
$(this).find("li").click(function(){ /* do work */});
If you absolutely have to reference it by ID you can do:
$(this).find("li").each(function(){
var id = $(this).attr("id");
/* do work */
});

Related

How to us $.data in a loop to display correctly for each div

When I click a marker on my map, I want to display data from the database associated with that marker. Currently I am doing this for the divs that I create. I am having a problem when I click on a div to open my form under it, I want to load the same data into the form, but currently the only data that will load into each for is the first one that ran through the loop.
Another words, my venue-list div might hold 3 venues for this one location, and I can click on each div and display a form under it, but if "Sally's Salon" is the first div in the list, every form will display "Sally's Salon" instead of their own name. Here is my code:
// initially detach form to be attached to each div on click
var editForm = $('.edit-container').detach();
function fillForm(title, priority) {
$('.venue-input').val(title);
$('.priority-input').val(priority);
}
for(var i = array.length -1; i>=0; i--) {
var prop = array[i].feature.prop
if(prop.title) {
// create variable to hold html
var html = $([
"<div class='venue-item'>",
" <span><strong>Venue Name</strong></span>",
" <span class='venue-name venue-title' data-title=" + prop.title + ">" + prop.title + "</span>",
"<span class='venue-priority' data-priority=" + prop.prioritylevel + "><strong>Priority</strong>" + ' ' + prop.prioritylevel + "</span></div>"].join("\n"));
// append venue item to venue list div with event handler to add form and prefill when clicked
$(html).appendTo('.venue-list').on('click', function() {
$(this).after(editForm);
fillForm($('.venue-title').data('title'), $('.venue-priority').data('priority'));
});
}
any input would be helpful, I've been battling this for a couple days now, not sure if I am even attaching the html elements correctly but I mainly just want to be able to click on one of the html elements I create and then the data gets loaded into the form so it can be manipulated.
You are appending multiple copies of your content, however there are 2 elements using the same id (venue-priority & venue-title) - which should be unique on a web page.
Thereafter, you use jQuery to get those elements, however as jQuery expects id's to be unique, it will just grab the first (or last, im not sure) element with that Id.
The solution is not to use duplicated id's in your markup.
You seem to have a syntax error on line 6. You can view errors in a browser using developer tools in case there are others.
$('#priority-input.val('priority);
should be
$('#priority-input').val('priority');
Actually, if you want to set the value to the value of the parameter, you should use
$('#priority-input').val(priority);
not
$('#priority-input').val('priority');

Adding additional html list elements using JSON and JavaScript

I can currently add a <li> element to my webpage using Javascript with information from a JSON file.
However, when I try and add another <li> element underneath the first one using the same methods it replaces the first one instead of adding it below the first one.
How do I get it to add another instead of replacing it?
Here is my Javascript code:
$('#links').html('<li>' + jsonObj.pageText[5].ref1 + '</li>')
$('#links').html('<li>' + jsonObj.pageText[5].ref2 + '</li>')
ref2 replaces the first one.
Use append or preppend instead of html
The .html(...) command replaces the html, so you would need to:
$('#links').html('<li>' + jsonObj.pageText[5].ref1+'</li>')
$('#links').html($('#links').html() + '<li>' + jsonObj.pageText[5].ref2+'</li>')
...or:
$('#links').append($('<li>').html(jsonObj.pageText[5].ref1))
$('#links').append($('<li>').html(jsonObj.pageText[5].ref2))

TinyMCE Replace Parent Node

I'm developping a WordPress plugin which adds a button to the TinyMCE editor. When that button is clicked the desired behaviour should be:
1. If the selected text is not part of a short (or is the short) then the shortcode should be inserted into the DOM.
2 If not, the shortcode should be replaced with the new one.
The first requirement is fufilled, but the second not. When inserted, it show up in the visual editor but it not saved or displayed when saving or switching to text. This leads me to believe that im not directly editting the object underneath the editor, only that which is displayed. What is the correct way to go about it. Please see the following function:
...
insertContent: function(){
var atts = '';
var node = tinyMCE.activeEditor.selection.getNode();
var edit = $(node).is('div.wp-arv-faq');
jQuery('./$p/-sc-input').each(function() {
atts = atts + jQuery(this).attr('name') + '=\"' + $(this).val() + "\" ";
});
var caption = 'F.A.Q. ' + $('./$p/-sc-input[name="tax"] option:selected').text();
var style = $('./$p/-sc-input[name="style"] option:selected').text();
atts += ' caption="' + caption + ' (' + style + ')"';
if (edit){
$(node).empty();
tinyMCE.activeEditor.selection.setContent('[arv-faq ' + atts + '][/arv-faq]');
/$p/faqMCE.closeModal();
},
...
Please note, that the '/$p/' is unique to my build process and should be ignored. Thanks in advance
From your question it is not perfectly clear what you are trying to do, but i guess you are trying to insert html code into the editor.
Be sure to have the selection set right after calling $(node).empty();
Note: All your tags and attributes need to be configured as allowed tags and attributes using valid_elements and valid_children configuration paramters.

More convert jquery object to string

Yes I have see the post here
And I tried that but the problem is, my jquery object looks more like this:
var $foo = $('<ul><li id="' + line.id + '" label="' + label + '" rel="file">' + line.title + '</li></ul>');
$foo.click(function() { openLink(line.url) });
$foo.appendTo($myDiv);
When $myDiv is fully populated I can do this:
var html = $('<div>').append($('#foo').clone()).remove().html();
And I will see all of the lovely HTML, but I don't know if the click stuff will be preserved. See, I want to save the entire DOM modification to localStorage so I can retrieve it quickly since it's pretty static. I need to be able to store it and all its attributes, then yank it back out and restore it, clicks and all.
Does that make sense?
The only way to do this would be to use inline event handlers, which is a bad (and slow) idea.
Instead, you can convert all of your event handlers to live handlers; they will then automatically apply to all matching elements without having to rebind them after changing the DOM.

jQuery + InnovaStudio WYSIWYG Editor

I am trying to avoid hard-coding each instance of this WYSIWYG editor so I am using jQuery to create an each() loop based on function name. Annoyingly InnovaStudio seems to explode when I try.
Documentation
Attempt #1
<script type="text/javascript">
/*
id = $(this).attr('id');
if(id.length == 0)
{
id = 'wysiwyg-' + wysiwyg_count;
$(this).attr('id', id);
}
WYSIWYG[wysiwyg_count] = new InnovaEditor('WYSIWYG[' + wysiwyg_count + ']');
WYSIWYG[wysiwyg_count].REPLACE(id);
*/
var demo = new InnovaEditor('demo');
demo.REPLACE('wysiwyg-1');
console.log('loop');
</script>
Effect
Works fine, but of course only works for a single instance of the editor. If I want multiple instances I need to use an each.
Attempt #2:
<script type="text/javascript">
var wysiwyg_count = 1;
//var WYSIWYG = [];
var demo;
(function($) {
$(function() {
$('.wysiwyg-simple').each(function(){
/*
id = $(this).attr('id');
if(id.length == 0)
{
id = 'wysiwyg-' + wysiwyg_count;
$(this).attr('id', id);
}
WYSIWYG[wysiwyg_count] = new InnovaEditor('WYSIWYG[' + wysiwyg_count + ']');
WYSIWYG[wysiwyg_count].REPLACE(id);
*/
demo = new InnovaEditor('demo');
demo.REPLACE('wysiwyg-1');
console.log('loop');
});
});
})(jQuery);
</script>
Effect
Replaces the entire HTML body of my page with JUST WYSIWYG related code and complains as no JS is available (not even Firebug, so can't debug).
Notice that I am hardcoding the name still. I only have one instance on the page I am testing it on, so when I get this hard-coded name working I will get the commented out code working along the same lines.
Does anybody know what the hell is going on here?
Solution: Don't bother trying to use InnovaStudio, went with CKEditor instead.
Even though you went for CKEditor you might be interested in a solution. You can supply a second argument to the REPLACE function. This second argument should also be a id, id from a element able to accept html output (like div, span, p).
demo = new InnovaEditor('demo');
demo.REPLACE('wysiwyg-1', 'wysiwyg-1-replaceDiv');
When the second argument is left out, InnovaStudio, writes the html output to the document by simply using:
document.write();
Hope this helps!
Why don't you use their own initialization code since version 4.3:
<textarea class="innovaeditor">
content here...
</textarea>
<script>
oUtil.initializeEditor("innovaeditor",
{width:"700px", height:"450px"}
);
</script>
The method is oUtil.initializeEditor(selector, option). The first parameter is selector and second is editor properties in JSON format.
The selector can be:
Css class name, if class name is specified all textareas with specified class name will be replaced with editor.
Textarea Id. If it is an Id, a prefix '#' must be added, for example oUtil.initializeEditor("#mytextarea").
Textarea object.
The second parameter is editor's properties. All valid editor's properties can be specified here for example width, height, cmdAssetManager, toolbarMode, etc.
Note that this method can be called from page onload or document ready event or during page load (as long as the object referred by selector are already rendered). This method available automatically when the page include the editor script.

Categories