Adding more classes to a javascript function - javascript

I'm trying to make a function run several div's in a Q&A accordion, but I can't figure out the right syntax for it to happen. In line 6, the classname 'questionV1' does the job well, but I want the function to run classnames 'questionV2' and 'questionV3' as well. I have tried to add questionV2 + V3, in the same line like this (divs[no].classname=='questionV1, questionV2, questionV3') but it does not work. The javascript looks like this:
function initShowHideDivs()
{
var divs = document.getElementsByTagName('DIV');
var divCounter = 1;
for(var no=0;no<divs.length;no++){
if(divs[no].className=='questionV1'){
divs[no].onclick = showHideContent;
divs[no].id = 'dhtmlgoodies_q'+divCounter;
var answer = divs[no].nextSibling;
while(answer && answer.tagName!='DIV'){
answer = answer.nextSibling;
}
answer.id = 'dhtmlgoodies_a'+divCounter;
contentDiv = answer.getElementsByTagName('DIV')[0];
contentDiv.style.top = 0 - contentDiv.offsetHeight + 'px';
contentDiv.className='answer_content';
contentDiv.id = 'dhtmlgoodies_ac' + divCounter;
answer.style.display='none';
answer.style.height='1px';
divCounter++;
}
}
}
window.onload = initShowHideDivs;

Here are two solution for your problem. One with regex, the other with string comparison.
RegEx Solution:
for(var index in divs){
var div = divs[index];
if(/questionV[123]/.test(div.className)) {
// code here
}
}
String comparison:
for(var index in divs){
var div = divs[index];
if(div.className === 'questionV1'
|| div.className === 'questionV2'
|| div.className === 'questionV3') {
// code here
}
}
also a link to jsfiddle

Related

Updating value in for loop / Reseting a for loop?

I'm working on my first school project so I don't have much experience in doing such web applications, that's why I decided to ask here.
How can I update the value in the for loop syntax or reset it entirely, so it iterates again, like I just reloaded it? I have another function that I decided not to show, simply because it would be useless to. What it does in the end is increments the taskCount.length by one. This part technically works but problem is, the function I'm going to show you now, once iterated, will always keep the default taskCount.length value, once the page is loaded, it never changes there. Is there any way I can update it?
Here's an example: The function above makes taskCount.length = '5' but when the page started it was taskCount.length = 4, and when I do alert(taskCount.length) from the console, I get 5. But the for loop doesn't want to change.
for (var i = 0; i < taskCount.length; i++) {
document.getElementsByClassName('task')[i].addEventListener('click', ((j) => {
return function() {
var shadow = document.createElement('div');
// Styling
var changingWindow = document.createElement('div');
// Styling
var changingTitle = document.createElement('p');
// Styling
var changingText = document.createElement('p');
// Styling
var changingTitleNode = document.createTextNode('Промяна');
var changingTextNode = document.createTextNode('Моля, изберете действие.');
var deleteTask = document.createElement('button');
var goUp = document.createElement('button');
var goDown = document.createElement('button');
var unchange = document.createElement('button');
// Styling
var deleteElementNode = document.createTextNode('Премахни задачата');
var goUpNode = document.createTextNode('Премести нагоре');
var goDownNode = document.createTextNode('Премести надолу');
var unchangeNode = document.createTextNode('Отказ');
var justBreak = document.createElement('br');
var justBreakAgain = document.createElement('br');
var justBreakOneMoreTime = document.createElement('br');
body.appendChild(shadow);
shadow.appendChild(changingWindow);
changingWindow.appendChild(changingTitle);
changingTitle.appendChild(changingTitleNode);
changingWindow.appendChild(changingText);
changingText.appendChild(changingTextNode);
changingWindow.appendChild(deleteTask);
deleteTask.appendChild(deleteElementNode);
deleteTask.onclick = function() {
document.getElementsByClassName('task')[j].parentNode.removeChild(document.getElementsByClassName('task')[j]);
shadow.parentNode.removeChild(shadow);
localStorage.setItem("listContent", document.getElementById('list').innerHTML);
}
changingWindow.appendChild(justBreak);
changingWindow.appendChild(goUp);
goUp.appendChild(goUpNode);
goUp.onclick = function() {
if (j !== 0) {
var saveThisTaskValue = document.getElementsByClassName('task')[j].innerHTML;
var savePreviousTaskValue = document.getElementsByClassName('task')[j - 1].innerHTML;
document.getElementsByClassName('task')[j].innerHTML = savePreviousTaskValue;
document.getElementsByClassName('task')[j - 1].innerHTML = saveThisTaskValue;
}
shadow.parentNode.removeChild(shadow);
localStorage.setItem("listContent", document.getElementById('list').innerHTML);
}
changingWindow.appendChild(justBreakAgain);
changingWindow.appendChild(goDown);
goDown.appendChild(goDownNode);
goDown.onclick = function() {
if (j !== document.getElementsByClassName('task').length - 1) {
var saveThisTaskValue = document.getElementsByClassName('task')[j].innerHTML;
var saveNextTaskValue = document.getElementsByClassName('task')[j + 1].innerHTML;
document.getElementsByClassName('task')[j].innerHTML = saveNextTaskValue;
document.getElementsByClassName('task')[j + 1].innerHTML = saveThisTaskValue;
}
shadow.parentNode.removeChild(shadow);
localStorage.setItem("listContent", document.getElementById('list').innerHTML);
}
changingWindow.appendChild(justBreakOneMoreTime);
changingWindow.appendChild(unchange);
unchange.appendChild(unchangeNode);
unchange.onclick = function() {
shadow.parentNode.removeChild(shadow);
}
}
})(i))
}
As a matter of the page reloading, you can always save the value as a cookie and reuse it again and again. You can update it whenever you want.
I don't fully understand you question, but maybe some recursion is what you need. Something along the lines of:
loop(5);
function loop(xTimes) {
for (var i = 0; i < xTimes; i++) {
if (newXTimes !== xTimes) {
loop(newXtimes);
break;
}
}
}
Maybe set newxTimes as a global variable that can be accessed inside loop.
In case someone "from the future" reads this question and it doesn't have any answers, I came up with the solution to reload the page everytime you change the value. Still, I'd like to do it without reloading.

How can I get the text to which a Nested Style is applied in InDesign

I am trying to write a script that will convert all characters to lowercase if a particular nested style is applied. I can't seem to figure out the correct syntax to get the text.
I originally tried the following, which worked to an extend, but lowercased the entire paragraph rather than only the text that has the character style applied:
function lowerCaseNest(myPStyle, myCStyle){
var myDocument = app.documents.item(0);
//Clear the find/change preferences.
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
//Set the find options.
app.findChangeTextOptions.caseSensitive = false;
app.findChangeTextOptions.includeFootnotes = false;
app.findChangeTextOptions.includeHiddenLayers = false;
app.findChangeTextOptions.includeLockedLayersForFind = false;
app.findChangeTextOptions.includeLockedStoriesForFind = false;
app.findChangeTextOptions.includeMasterPages = false;
app.findChangeTextOptions.wholeWord = false;
app.findTextPreferences.appliedParagraphStyle = myPStyle;
var missingFind = app.activeDocument.findText();
var myDoc = app.documents[0];
for ( var listIndex = 0 ; listIndex < missingFind.length; listIndex++ ) {
for (i = missingFind[listIndex].nestedStyles.length-1;i>=0; i--) {
for (j = missingFind[listIndex].nestedStyles[i].parent.characters.length-1;j>=0; j--) {
if (missingFind[listIndex].nestedStyles[i].parent.characters[j].contents.appliedCharacterStyle(myCStyle)) {
var myString = missingFind[listIndex].nestedStyles[i].parent.characters[j].contents;
if (typeof(myString) == "string"){
var myNewString = myString.toLowerCase();
missingFind[listIndex].nestedStyles[i].parent.characters[j].contents = myNewString;
}
}
}
}
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
}
I then tried playing around with appliedNestedStyles, but can't seem to figure out how to retrieve the text that the nested style is applied to.
Could anyone help with this?
Thanks!
John
Unless I am wrong the appliedNestedStyle can be looked after in the F/C dialog by targeting the applied characterStyle:
GREP
Find : .+
Format : character style => myCharStyle
then
var found = doc.findGrep();
…
I actually took a different tack, and figured out something that works:
function lowerCaseNest(myPStyle, myCStyle){
for (var i = 0; i < app.activeDocument.stories.length; i++){
for (var j = 0; j < app.activeDocument.stories[i].paragraphs.length; j++){
var myP = app.activeDocument.stories[i].paragraphs[j];
if (myP.appliedParagraphStyle.name==myPStyle) {
for (k=0; k<myP.characters.length; k++) {
if(typeof(myP.characters[k].appliedNestedStyles[0]) != 'undefined'){
if(myP.characters[k].appliedNestedStyles[0].name == myCStyle) {
var myC = myP.characters[k].contents;
if (typeof(myC)=='string'){
var myNewString = myC.toLowerCase();
myP.characters[k].contents = myNewString;
}
}
}
}
}
}
}
}
Still would be interested in knowing if there's an easier way to handle this, as I'm afraid this may take longer to run on long documents, since it's dealing with every paragraph individually.

What is the plain Javascript equivalent of .each and $(this) when used together like in this example?

What is the plain Javascript equivalent of .each and $(this).find when used together in this example?
$(document).ready(function(){
$('.rows').each(function(){
var textfield = $(this).find(".textfield");
var colorbox = $(this).find(".box");
function colorchange() {
if (textfield.val() <100 || textfield.val() == null) {
colorbox.css("background-color","red");
colorbox.html("Too Low");
}
else if (textfield.val() >300) {
colorbox.css("background-color","red");
colorbox.html("Too High");
}
else {
colorbox.css("background-color","green");
colorbox.html("Just Right");
}
}
textfield.keyup(colorchange);
}
)});
Here's a fiddle with basically what I'm trying to accomplish, I know I need to use a loop I'm just not sure exactly how to set it up. I don't want to use jquery just for this simple functionality if I don't have to
http://jsfiddle.net/8u5dj/
I deleted the code I already tried because it changed every instance of the colorbox so I'm not sure what I did wrong.
This is how to do what you want in plain javascript:
http://jsfiddle.net/johnboker/6A5WS/4/
var rows = document.getElementsByClassName('rows');
for(var i = 0; i < rows.length; i++)
{
var textfield = rows[i].getElementsByClassName('textfield')[0];
var colorbox = rows[i].getElementsByClassName('box')[0];
var colorchange = function(tf, cb)
{
return function()
{
if (tf.value < 100 || tf.value == null)
{
cb.style.backgroundColor = 'red';
cb.innerText = "Too Low";
}
else if (tf.value > 300)
{
cb.style.backgroundColor = 'red';
cb.innerText = "Too High";
}
else
{
cb.style.backgroundColor = 'green';
cb.innerText = "Just Right";
}
};
}(textfield, colorbox);
textfield.onkeyup = colorchange;
}
var rows = document.querySelectorAll('.rows');
for (var i=0; i<rows.length; i++) {
var row = rows[i];
var textfield = row.querySelector('.textfield');
var colorbox = row.querySelector('.box');
// ...
}
Note that you must use a for loop to iterate the rows because querySelectorAll() does not return an array, despite appearances. In particular, that means that .forEach() isn't valid on the returned list.

Replace a space within a SPAN tag with a BR tag

I need to replace the space between the 2 words with a BR tag. I've tried quite a few things, this one I thought would work, but the original script only does it to the first item. :( I need it to replace it on all the menu items.
It's for menu text on a CMS, so I won't know what the text is going to be. All I know is that it will always be no more than 2 words.
I can use either JS or jQuery.
Demo here: JS Bin Link
HTML:
<span class="navtext">Lorem ipsum</span>
<br>
<span class="navtext">Lorem ipsum</span>
<br>
<span class="navtext">Lorem ipsum</span>
JavaScript:
// Doesnt work
// var span = document.getElementsByTagName(".navtext");
// Only works for the first one
var span = document.querySelector(".navtext");
// Doesnt work
// var span = document.querySelectorAll("navtext");
function space() {
var elem = document.createElement("br");
// elem.className = "space";
// elem.textContent = " ";
return elem;
}
function replace(elem) {
for(var i = 0; i < elem.childNodes.length; i++) {
var node = elem.childNodes[i];
if(node.nodeType === 1) {
replace(node);
} else {
var current = node;
var pos;
while(~(pos = current.nodeValue.indexOf(" "))) {
var next = current.splitText(pos + 1);
current.nodeValue = current.nodeValue.slice(0, -1);
current.parentNode.insertBefore(space(), next);
current = next;
i += 2;
}
}
}
}
replace(span);
I think, you dont want to use jQuery. Well, Here is quick solution:
var elms = document.querySelectorAll(".navtext");
for(var i=0; i<elms.length; i++){
elms[i].innerHTML = elms[i].innerHTML.replace(/\s/gi, "<br />");
}
Here is the jsfiddle: http://jsfiddle.net/ashishanexpert/NrTtg/
using jQuery you can do this:
$("span.navtext").each(function(){
$(this).html($(this).text().replace(/ /g,"<br />"));
})
If you install jQuery you can make it all more simple. Follow the installation instructions and then the code you'll need is something like:
jQuery(function($) {
// for each navtext run the described function
$(".navtext").each(function() {
// "this" represents the navtext
// replace all " " with "<br/>" from this's html
var code = $(this).text();
code = code.replace(" ", "<br/>");
// update this's html with the replacement
$(this).html(code);
});
});
Someone on twitter provided me with a fix, which was exactly like what Ashish answered.
var spans = document.getElementsByTagName("span");
for(var i = 0; i < spans.length; i++) {
spans[i].innerHTML = spans[i].innerHTML.replace(' ', '<br>');
}
But that would quite work for me, but it did give me my answer! So thanks to Pete Williams
This is the code I went with:
var spans = document.querySelectorAll('.navtext');
for(var i = 0; i < spans.length; i++) {
spans[i].innerHTML = spans[i].innerHTML.replace(' ', '<br>');
}

Why is my Javascript not valid?

I have a div with ID 'adpictureholder', to which I dynamically add (or remove) images.
On Form submit I want to get SRC values of all these images within that DIV and put them to the value of one hidden input with ID 'piclinkslisttosubmit'. The thing is that my current Javascript does not function as if there is some syntax typo there, but I don't see where. Can anyone please have a quick look at it?
function copyonsubmit(){
var strump1 = '';
var i=0;
var endi = document.getElementById('adpictureholder').childNodes[].length - 1;
var images = document.getElementById('adpictureholder').childNodes[];
for (i=0;i<=endi;i++)
{
strump1 = strump1 + '|' + images[i].src;
}
document.getElementById('piclinkslisttosubmit').value = strump1;
}
Change childNodes[] to simply childNodes.
You don't need to specify that a variable you're referencing is an array by adding brackets.
Your javascript isn't valid because you keep putting childNodes[] you can solve that by replacing childNodes[] with simply childNodes
function copyonsubmit(){
var strump1 = '';
var i=0;
var endi = document.getElementById('adpictureholder').childNodes.length - 1;
var images = document.getElementById('adpictureholder').childNodes;
for (i=0;i<=endi;i++)
{
strump1 = strump1 + '|' + images[i].src;
}
document.getElementById('piclinkslisttosubmit').value = strump1;
} ​
You shouldn't use [] when reading a property value:
var images = document.getElementById('adpictureholder').childNodes;
You can then get the length from the array, instead of reading the property again:
var endi = images.length - 1;
First off you don't need the [] after childNodes. that causes an error.
You also were forgetting that childNodes includes text nodes and would not work properly, because they did not all contain the src property. I've corrected that in the following example:
function copyonsubmit() {
var str = '';
var textbox = document.getElementById('piclinkslisttosubmit');
var i = 0;
var images = document.getElementById('adpictureholder').childNodes;
var numImages = images.length - 1;
var src = "";
for (i = 0; i < numImages; i++) {
if (images[i].tagName === "IMG") {
str += images[i].src + '|';
}
}
str = str.slice(0, -1); // cut off the final |
textbox.value = str;
}
http://jsfiddle.net/NWArL/2/
Secondly you could write this really simply with jQuery.
var str = "";
$("#apictureholder").children("img").each(function() {
str += $(this).attr("src") + "|";
})
$("#piclinkslisttosubmit").val(str);
Third off make sure to check your console for errors. It was very clear when I ran this code on JSFiddle that it had a problem.
Finally, what exactly are you trying to do?
Change childNodes[] to childNodes and rest looks fine to me,
Read about childNodes
Try,
function copyonsubmit(){
var strump1 = '';
var i=0;
var endi = document.getElementById('adpictureholder').childNodes.length - 1;
var images = document.getElementById('adpictureholder').childNodes;
for (i=0;i<=endi;i++)
{
strump1 = strump1 + '|' + images[i].src;
}
document.getElementById('piclinkslisttosubmit').value = strump1;
}
You said you were using jQuery, but you presented us with vanilla Javascript. I took the liberty of converting your code to jQuery and cleaning it up a bit. The others have already identified your problem, though.
function copyonsubmit() {
var strump1 = '';
var images = $("#adpictureholder")[0].childNodes;
for (var i = 0; i < images.length; i++) {
strump1 += '|' + images[i].src;
}
$('#piclinkslisttosubmit').val(strump1);
}​

Categories

Resources