Edited for clarity. (thanks)
On my page, there are dynamically created divs that contain input elements(they clone the original). Each div refers to a unique form, but the ID of the input elements are not unique in each div(this may be a problem).
The code below successfully searches my doc for all of the divs that have been created(Their ID is medical-report(random number), gathers their input elements and then outputs each string in the array separated by a comma.
var $inputs= $("div[id^='medical-report']").find("input").clone();
$("#multi").append(($inputs).map(function() {
return $(this).val();
})
.get()
.join(", "));
}
What I want to do instead, is traverse the array (not sure if I have truly created one), and then looks at the ID of each input element and append unique paragraph text for each to an area in my page. It would basically summarize the contents of each div.
(search for inputs, and clone them)
var $inputs= $("div[id^='medical-report']").find("input").clone();
Then
pseudo code:
for each div=
If the ID is "nameofdoc" add paragraph The name of the doctor is "nameofdoc.val"
If the ID is "datereceived" add paragraph the document was received on "datereceived.val"
and so on.
Just to restate, a problem here may be that "nameofdoc" and "datereceived" are not unique ID's. The container divs however are unique.
var $inputs= $("div[id^='medical-report']").find("input").clone();
$("#multi").append(($inputs).map(function(index) {
return $(this).val();
.get();
if ($(this).is("#MEDRIN")) {
$("p").text("The medical was received on" +index);
}
})
I have read up on .each and.contents in the jquery API but I am really unsure of what direction to go in. Fiddle is below.
http://jsfiddle.net/gdoax9q2/7/
There are a number of issues here. I will list the steps that I would take to solve this problem.
Rename the function from "sayHi" to a name that describes what this function does. "generateReportSummaries" seems appropriate.
I removed all of the innerHTML stuff because I had no idea what it was doing.
Use jQuery to grab a collection of all the forms we want to create summaries for (I gave the forms each a "report-form" class to make this easier.
Create a function that will take a a form element and return a formatted element that we can append to the document. I called my function "getReportElement".
For each form element, call getReportElement and append the result to #mutli.
Implement getReportFormat to map the values for all the form's inputs - include a conditional for when input's name attribute is 'MEDRIN'. Join the values array and append it to the new element that the function returns.
function generateReportSummaries () {
/* Get a jQuery wrapped collection of all .report-form elements. */
var $forms = $('.report-form');
/* Call getReportElement for each .report-from. */
$forms.each(function () {
$('#multi').append(getReportElement($(this)));
});
}
function getReportElement ($form) {
/* Create a new paragraph element to contain our text. */
var $paragraph = $('<p></p>');
/* Get an array of the form's input values. */
/* If input is [name="MEDRIN"], add prefix text to array value. */
var mapped_values = $form.find('input').map(function () {
if ($(this).is('[name="MEDRIN"]')) {
return 'The medical was received on ' + $(this).val();
} else {
return $(this).val();
}
}).get();
/* Join our values array and set it as our paragraph element's text. */
$paragraph.text(mapped_values.join(', '));
/* Return our (jQuery-wrapped) paragraph element. */
return $paragraph;
}
I removed the input ids and replaced them with name attributes because ids should not be duplicated. Also, the datepicker was causing issues for the cloned forms, so I changed things a little to make everything work. You can see my result at: http://jsfiddle.net/76484/qLeg5wm9/
Related
I am using this Wordpress plugin
https://smashballoon.com/custom-twitter-feeds/demo
I would like to trim the Tweets to 120 characters.
I have no JS skills and very little php - I tried this which I found but I don't know if it's relevant at all.
$twitter_feed = (strlen($twitter_feed) > 120) ? substr($twitter_feed,0,10).'...' : $twitter_feed;
enter code here
I also attempted to edit my working code for trimming my post titles to suit which did not work.
function custom_trim_my_tweet( $twitter_feed ) {
global $uncode_vc_index;
if ( is_singular() && !$uncode_vc_index )
return $twitter_feed;
$twitter_feed = wp_trim_words( $twitter_feed, 9 );
return $twitter_feed;
}
add_filter( 'ctf-tweet-text', 'custom_trim_my_tweet' );
To trim the text using JavaScript:
First you have to select the element using a css selector. It's easiest if you can select the elements using an element id, like so:
var tweet = document.getElementById("my_tweet_id");
Then you can grab the text content of the element with element.innerText
var tweetText = tweet.innerText;
Then you can simple cut the length of the text inside the element using string.substring()
tweet.innerText = tweetText.substring(0, 120);
I honestly think you should try to fix this at the plugin/wordpress/php level rather than cutting text in JavaScript. But if that's what you want to do, then the above methos would work.
EDIT:
In case the tweet elements do not have unique ID's you will have to select all of them and then loop through each and perform the text-cutting. I'll give you an example of how to do that:
You might have to be a bit creative with your css selectors depending on how the tweets are displayed.
In my example I will assume that you have a div with the ID 'tweets' that then holds five separate div elements, one for each tweet, that all have the same class of 'single-tweet'.
First we get all the 'single-tweet' elements:
var tweets = document.querySelectorAll('#tweets .single-tweet');
tweets now contain a node list of the five 'single-tweet' divs.
Then we loop through them with .forEach() and do the text-cutting on each element.
tweets.forEach( (tweet) => {
tweet.innerText = tweet.innerText.substring(0, 120);
})
Now all of the 'single-tweet' elements will contain what's left after you cut the text down to 120 characters.
I have an array of delete button elements:
const DELETE_BUTTONS = document.getElementsByClassName('delete-button');
These delete buttons are in a table, and each of them are inside a table row in its own td. I add an event listener to it in three different ways.
To already rendered delete buttons:
for (let x = 0; x < DELETE_BUTTONS.length; x++) {
DELETE_BUTTONS[x].onclick = function () {
deleteProperty(DELETE_BUTTONS[x]);
};
}
To a new row in the table, which is an inline-form that I add with another onclick:
...
CLONED.classList.add('cloned', 'properties__row');
const DELETE_BUTTON = CLONED.lastElementChild.lastElementChild;
DELETE_BUTTON.onclick = function () {
deleteProperty(DELETE_BUTTON);
};
When the user has submitted the inline form, I get the data back with Ajax, and create a new tr and append it to the table body. (To create this element easily I use another JS function. Note that I did not include the bit where I create the tr itself, it is irrelevant.)
MAKE_ELEMENT('a', {onclick: 'deleteProperty(this)', class: ['btn-flat', 'waves-effect', 'btn-floating']},
MAKE_ELEMENT('i', ['material-icons', 'red-text'],
'delete_forever'
)
)
This is the function that is added with the onclick:
function deleteProperty(element) {
element.parentElement.parentElement.remove();
}
This works perfectly, right up until I delete a second element. Every time I delete an element, it also removes it from the array. Meaning that deleteProperty(DELETE_BUTTONS[19]) will delete/remove a different element than it did at first. How can I prevent the array from changing length?
I tried to make a copy of the array, but it behaved exactly like the original. I could also just insert an empty place holder in the array when I remove an element so it stays the same length, but this doesn't seem like good practice. Any pointers would be welcome, thanks.
Someone knows how can I get all the radiobuttons inside a div? The div has a id as follows
<div id="quest{{ $groups }}" class="quest">
I'm using Laravel, therefore my idea is to get the values inside a div, and put in jQuery something like
var radios = $("input[type='radio'][id^='quest'"+groups+"]");
But this doesn´t work, so I want to know how to get all the radiobuttons inside a div an do a loop inside using .each I think.
I need to duplicate one group of questions and then be able to do a validation, but only works for the first group, the second group is not validated and I´ve checked the id value for each radiobutton and change to previousid_2, and the questionnaire is cloned. Also I want to know how can I reset the values when I clone the questionnaire, because if you have select YES NO YES NO, in the second group when you clone it, those results are selected and the disabled fields too.
You're actually asking for several things. Your code implies you have access to the current group in a variable called groups. so...
1) select all radio inputs within a div:
var div = $("div#quest"+groups);
var radiosBtns = div.find("input[type='radio']");
2) Loop over them, and do some work on each element:
var doSomeWork = function(i,radiobtn){
console.log('the value of radio button #' + i ' is ' + radiobtn.value);
};
$.each(radioBtns,doSomeWork);
3) Duplicate a group of radio buttons:
var fromgroup = $("div#quest"+groups);
var togroup = fromgroup.clone();
var insertionPoint = $('body');
var toGroupId = 'questXXX';
// set the ID so it can be targetted
togroup.prop('id',toGroupId);
// reset radio button values
togroup.find('input[type="radio"]').each(function(){
this.prop('checked',false);
});
togroup.appendTo(insertionPoint);
4) Run validation on a specific group
var validateGroup = function(elements){
// your validation logic goes here
var isValid = false;
$.each(function(){
console.log( this.name, this.value );
});
return isValid;
};
// run the validation on the newly inserted group
var targetElements = $("#"+toGroupId).find("input[type='radio']");
var groupIsValid = validateGroup( targetElements );
You can get all radio buttons and iterate on them like following
$("input[type='radio'][id^='quest']").each(function(){
// add your logic here
});
it's very simple using Id's
To get all the elements starting with "quest" you should use:
$("[id^=quest]")
To get those that end with "jander"
$("[id$=quest]")
and the complete answer is
var radios = $("input[type='radio'][id^='quest']");
the point is what if you want to wildcard class :( :(
$("[class^=quest]")
on a dom like
<pre>
<a class="btn quest primary">link</a>
<pre>
it won't work , thus you will need a more complex wildcard that you have to till me when you find it :D
the fact is you will not need it , whenever you need to get a list of element using classes just use a common class :D
hope i helped u well
I have a table in an html form containing a table that a row is added to every time a button is clicked. When each row is added, I want the name and id of each field in the new row (there are four) to be updated from "Id.0" in the first row to "Id.1" in the second row and then "Id.2" in the third, etc. I can accomplish this with the id no problem using
var next=$("#QualificationRequirements tr:last").clone();
fixIds(next,nexdex);
nexdex++;
$("#QualificationRequirements").append(next);
function fixIds(element, counter) {
$(element).find("[id]").add(element).each(function() {
this.id = this.id.replace(/\d+$/, "")+counter;
}
}
However I have found that the same logic does not apply to the name attribute, and
$(element).find("[name]").add(element).each(function() {
this.name = this.name.replace(/\d+$/, "")+counter;
});
causes an error that says I can't call "replace" on a null object, so it appears the name attribute is not being found.
Can anyone see what I'm doing wrong? Thanks!
The issue comes from this part of your statement: add(element)
See, element refers to the complete row, and rows don't have a name attribute. You just want to act upon the inputs inside the row that have the name attribute so you should remove that part from your code:
$(element).find("[name]").each(function() {
this.name = this.name.replace(/\d+$/, "")+counter;
});
There is no name property on an HTML element. Instead you'll need to access it as an attribute:
this.setAttribute('name', this.getAttribute('name').replace(/\d+$/, "")+counter);
Working Demo
use $(this).attr('name'); to get and set the name attribute.
The full line:
$(this).attr('name',$( this).attr('name').replace(/\d+$/, "")+counter);
Try this
$(element).find("[name]").add(element).each(function() {
this.attr("name",this.attr('name').replace(/\d+$/, "")+counter) ;
});
I have been trying to find a solution on Google so I thought I would post it to the community. I need to use JavaScript to locate all the H2s on a page, get the innerHTML values and then loop them horizontally in a div (easy enough) to show a subheading anchor list at the top of the page. Can someone tell me or give me a hint on how I can use a JavaScript routine to locate all the H2s on a page? Thanks!
If you're using jQuery, you could run something like this
$('h2').each({
/* function */
});
Then to append to the .nav container you can run
$('h2').each(function() {
$('.nav').append($(this).text())
});
Use document.getElementsByTagName to select all the h2s:
var h2s = document.getElementsByTagName('h2');
for(var i = 0, length = h2s.length; i < length; i++){
// Do something with
h2s[i].innerHTML;
}
First of all, create an empty collection for the links you're going to create:
var $links = $();
Then, loop through each h2 using .each(), providing index and h2 as arguments — the first keep count, the second to get a reference of the current <h2> we're dealing with.
$('h2').each(function(index, h2){
// If there is no id (to link to), create one based on the index
if(!h2.id){
h2.id = 'header' + index;
}
// Get a jQuery object of the header
var $h2 = $(h2);
// Link will be an <a> with the same text as the heading, and will link to its id
var $link = $('<a>').text($h2.text()).attr('src', '#' + h2.id);
// Add this link to the collection
$links = $links.add($link);
});
So now $links contains your table of contents. Assuming you want to chuck these links in after the <h1>, you'd do the following:
$links.insertAfter('h1');
…but of course you can do whatever you want with them at this point.