I want to show a button (for example, span.mybutton) next to every instance of a specified element (for example, a table) in TinyMCE—and then, when that button is clicked, grab that specific element's html, process it, and update it in the editor.
I can handle the processing, but I can't figure out how to display the button and pass in grab the specific element's html. If I do this, for example, it adds the html of span.mybutton to TinyMCE as if it were regular content, which I don't want:
jQuery('iframe#content').contents().find('table').append('<span class="mybutton">My button</span>');
Here's what I'm trying to do:
function processElement( element, values ) {
// do stuff to the table html (I don't need help with this part)
return element;
}
function appendButtonToTinyMCEElement ( button, element ) {
// put button next to all instances of the specified element in TinyMCE
// (in this case, put span.mybutton at the corner of all tables)
}
$('.myhelperbutton').click(function(){
var element = ??? // get content of the element whose button was clicked
var element = processElement( element );
// send element back to TinyMCE (not sure how)
});
So, my two questions are:
How can I display the button in the right place without affecting the html that gets saved in TinyMCE? And, when the button is clicked, how do I get/set just that element from TinyMCE?
If I understand correctly you wish to grab all table DOM elements, and place a button next to it which does some stuff.
Below is my first thought. I am going to make convenient assumptions to make it easier, but let me know if I made some wrong assumptions somewhere. I also don't know how much javascript/jquery you already know, so let me know if I didn't explain something clearly.
jQuery('iframe#content').contents().find('table').each(function(index, element) {
// create a new button.
var $btn = $('<input type="button" class="mybutton"></input>');
function action() {
// This is using the `processElement` function you defined in your question,
// I am applying it to the specific table just grabbed.
processElement(element);
}
$btn.click(action);
// This should append the button. See http://api.jquery.com/after/
$(element).after($btn[0]);
});
Let me know if this works for you or not.
Related
How does jQuery differentiate between function calls (e.g. on click) when using variable element IDs?
I have a number of files that are contained in a table, each row containing a checkbox and filename.
Each of these checkbox input elements has a uniquely generated ID which is "Item_" followed by a 5 unique digit number.
Ideally, I'd like to process the state of a checkbox when it the user selects it or deselects it.
If I were to use the following to access when the user clicks on an item from the list, how would jQuery respond to the checkbox set/unset?
$("#Item_" + file_number).some_function_here();
Would jQuery keep track of the elements on the page which have the ID of Item_#### (e.g. Item_100, Item_1234, etc.)? These items would not be dynamic so the page will only contain elements that part of the page when it is loaded, so all the information jQuery needs for the processing is available when the page is first loaded. But I want to avoid generating a processing function for each element in the list to minimize the size of the page and keep the code clean so that the javascript/jquery would be the same across the pages, and only the file items would be changed.
Thank you for any help you can provide.
How does jQuery differentiate between function calls (e.g. on click) when using variable element IDs?
They're stored in a closure inside jQuery's internals. It's not too dissimilar from the following:
const getElements = (selector) => {
const elements = document.querySelectorAll(elements);
return {
someFn() {
// do something with every element in `elements`
}
};
};
For what you're doing, it sounds like you should give each item a class name instead of a separate ID, then add a change listener to all elements with that class. Then, the this inside the listener will refer to the element that was changed:
$('.item').on('change', function() {
console.log(this); // refers to the input
console.log('was just changed to', this.checked);
});
And then you can process the change appropriately, depending on the element and the checkbox state.
I've been using the following code in JavaScript for several months and it appears to work without issue, but I started to wonder why it works and whether or not it is a safe method.
The purpose is simply to keep track of the currently selected HTML element and not perform the function code triggered by an event if the user clicks again upon the currently selected element.
function elem_mouse_evt( evt )
{
if ( evt.currentTarget === elem_mouse_evt.e ) return;
elem_mouse_evt.e = evt.currentTarget;
/* ... */
}
This may be a rather stupid question on my part but why is this different than comparing two objects for equivalence? How does JavaScript make this comparison, since each represents a collection of values?
Thank you.
Addition I left out a very important point that came to mind while considering the posted answer, which is that the function property e has a larger purpose. There is a menu of actions that the user can choose to perform on the current selection and/or its content. I thought it would be more efficient to store the reference in the function property rather than traversing the DOM to search for it by one of its unique attributes. Is that a reasonable method?
The purpose is simply to keep track of the currently selected HTML element and not perform the function code triggered by an event if the user clicks again upon the currently selected element.
Rather than doing what you're asking (uniquely identifying an element), I'd flag that element in some way. One way to do that is to add something to its dataset. I'm guessing though that you'll want to change the styling of this selected element at some point though anyway so that users see it's already selected. In that case, we'll add a class.
// Add an event listener on the container for these elements.
// It's more efficient to have just one event listener, rather than thousands.
document.querySelector('.parent').addEventListener('click', (e) => {
// Ensure what's actually clicked meets the filter
if (!e.currentTarget.matches('.selectable')) {
return;
}
// If it's already selected, don't do anything else! (You can combine this with above.)
if (e.currentTarget.matches('.selected')) {
return;
}
e.currentTarget.classlist.add('selected');
// Perform your other actions here
});
so I have this basic bootstrap form and I have a button called add another location which will dynamically create another 4 inputs to add more location. This is achieved via jquery and jquery UI. So I made 3 copies of this form and put them in a list because eventually, they are going to come from a server and loop the form depends on however many sets of information available. The problem I am having is that, only my first add another location button works and it's creating additional inputs on the second and third one as well. I can give different id/class to the buttons where the new form goes but that wouldn't do me any good since more or fewer forms can be displayed via the server. My question is how can each button act independently without giving different id/class to it. so if I click add another location button on the second set of form, it only creates additional inputs on the second set not first or 3rd, same for 1st set and 3rd set.
this is the jquery code that clones and appends the new inputs
$("#pm-do-clone1").click(function () {
$(".pm-clone-this3 .pm-clone4").clone().appendTo(".pm-clone-here1");
});
here's my jsfiddle : https://jsfiddle.net/jaisilchacko/yqvd4Lvv/4/
ps: the fiddle the first add location is not creating new inputs, but it works on my local.Probably an external resource issue
alright, as I understand You gotta grab the clicked button by referancing it with;
$("#pm-do-clone1").click(function () {
$(this).//rest of the code
and at the rest of the code as we captured the clicked one, we now have to find its parent where we gonna add the new inputs. For example,
var y = document.createElement('input');
var x =$(this).parents('.form');
$(x).append(y);
Edit: Btw, you are clicking an ID, ID is not the best model to catch one from multiple elemets because it sometimes make mistakes, use class instead.
Edit2: Check this snippet too. I belive this will help you. View DEMO
Edit3: Why do you wrapping each inputs into divs? It seems not necessary no create too much elements as you could achive the same result with only inputs.
I want to make a very simple mix and match system, where the user chooses items from a select drop down menu which triggers things. I have buttons that are appended to the document in a rather off the cuff manner, that is to say, whenever the user chooses something from the select some text will appear as well as a button to remove that text (and corresponding button). I'm using D3 to manipulate selections, add classes and append things. I use classes to tell the button which text to remove. All that being said, I believe this still could simply be a native javascript problem I'm running into. The problem is as follows:
After you choose some things from the select drop down menu, and then proceed to click the x buttons in the order bottom to top, the behavior is as desired. However, if you click a button at the top or in the middle, the button will not remove the right text. I believe that is because the button is simply removing whatever the latest string value of the dynamic class I'm using. That makes me doubt that the button actually retains the initial properties of its .on('click', function() {}) (hence the post title).
If that's the case, I'm not really sure how to circumvent such an issue, as the buttons are dynamic in nature.
Very short and simple example here.
No need to retain memory kind of thing just make sure your element is accessible one such scenario would be to save the id reference of element as class of another element like this
d3.select('body').append('button')
.text('X')
.attr('id','b'+(intCount+1))
.attr('class',choice+'1') //class is the id of the text element
.on('click', function(d,i) {
var t = d3.select(this).attr('id')
var c = d3.select(this).attr('class')
var thisChoice = choice;
d3.selectAll('.' + t).remove(); //remove this element
d3.selectAll('.'+ c).remove(); //remove text element
intCount -= 1;
count -= .7;
});
working FIDDLE
Hoping for some advice here, I'm quite new to javascript and coding in general so I'm sure there are better ways to do what I need, however any help much appreciated ....
I have a piece of javascript that creates a table, the amount of rows being dynamic.
When I call the javascript I'm passing a few bits of info over, and one of these is an array. The array contains in each element a long string of text.
So I create the table with X rows showing some identifying data. I also create a radio button for each row with an on click event. The idea being that when the user clicks on the radio button, then the long string from the array element will be displayed in a separate text box.
I have managed to get to the point that the table is created and that when the radio button is selected the onclick event fires and loads a piece of data into the txt box. However that piece of data is hardcoded (txtbox.value=array[1])
What I'm now trying to do is load the relevant string from the array, depending on what radio button is clicked.
If i change my onclick event to onclick=function(ID) and my function to function(ID) I'm getting an error 'Not implented'
It appears to be generated from the onclick event rather than the function ...
The following works :
R1.onclick=clicktest;
function clicktest()
{
txtbox.value=array[1]
}
The following generates the error
R1.onclick=clicktest(1);
function clicktest(id)
{
txtbox.value=array[id]
}
Apologies if this isn't so clear.
Using this code
R1.onclick=clicktest(1);
You're executing clicktest(1) and assigning the result as event handler.
You could change it by this in to make it work
R1.onclick = function() { clicktest(1) };