Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #36822 > unrolled thread

Getting the index of a clicked element

Started byJames Harris <james.harris.1@gmail.com>
First post2019-06-07 17:35 +0100
Last post2019-06-11 03:22 -0700
Articles 20 on this page of 25 — 8 participants

Back to article view | Back to comp.lang.javascript


Contents

  Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-07 17:35 +0100
    Re: Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-07 17:59 +0100
      Re: Getting the index of a clicked element Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2019-06-07 20:33 +0200
        Re: Getting the index of a clicked element dr.j.r.stockton@gmail.com - 2019-06-08 01:43 -0700
    Re: Getting the index of a clicked element "R.Wieser" <address@not.available> - 2019-06-07 19:39 +0200
      Re: Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-08 18:52 +0100
    Re: Getting the index of a clicked element Julio Di Egidio <julio@diegidio.name> - 2019-06-07 10:45 -0700
      Re: Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-08 18:57 +0100
        Re: Getting the index of a clicked element Julio Di Egidio <julio@diegidio.name> - 2019-06-09 05:44 -0700
    Re: Getting the index of a clicked element Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2019-06-07 20:16 +0200
      Re: Getting the index of a clicked element Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2019-06-07 22:48 +0200
    Re: Getting the index of a clicked element Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2019-06-07 20:36 +0200
    Re: Getting the index of a clicked element JJ <jj4public@vfemail.net> - 2019-06-08 12:57 +0700
      Re: Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-08 10:30 +0100
        Re: Getting the index of a clicked element Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2019-06-08 12:13 +0200
          Re: Getting the index of a clicked element John G Harris <niam@jghnorth.org.uk.invalid> - 2019-06-08 13:35 +0100
          Re: Getting the index of a clicked element John G Harris <niam@jghnorth.org.uk.invalid> - 2019-06-08 13:45 +0100
          Re: Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-08 19:03 +0100
            Re: Getting the index of a clicked element Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2019-06-08 21:11 +0200
              Re: Getting the index of a clicked element dr.j.r.stockton@gmail.com - 2019-06-08 14:18 -0700
    Re: Getting the index of a clicked element dr.j.r.stockton@gmail.com - 2019-06-08 02:16 -0700
      Re: Getting the index of a clicked element James Harris <james.harris.1@gmail.com> - 2019-06-08 19:14 +0100
    Re: Getting the index of a clicked element dr.j.r.stockton@gmail.com - 2019-06-10 11:29 -0700
      Re: Getting the index of a clicked element "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2019-06-10 23:00 +0200
        Re: Getting the index of a clicked element dr.j.r.stockton@gmail.com - 2019-06-11 03:22 -0700

Page 1 of 2  [1] 2  Next page →


#36822 — Getting the index of a clicked element

FromJames Harris <james.harris.1@gmail.com>
Date2019-06-07 17:35 +0100
SubjectGetting the index of a clicked element
Message-ID<qde3ou$aqm$1@dont-email.me>
Almost a complete beginner at JavaScript so there may be a better way to 
do this but ... what I am trying to do is have a web page consisting of 
pairs of questions and answers as in

   Question
     Answer
   Question
     Answer
   Question
     Answer

where clicking on the question toggles whether the answer appears or 
not. Answers will initially be absent.

I've got that bit worked out in a way I like (will explain in a separate 
post). My problem is in identifying the corresponding answer when a 
question is clicked.

The web page has the form

<div class = "question">Why?</div>
<div class = "answer">Because</div>

<div class = "question">When?</div>
<div class = "answer">Soon</div>


On DOMContentLoaded I run the following function

function all_hide()
{
   var answers = document.getElementsByClassName("answer");
   for (var i = 0; i < answers.length; i++)
   {
     saved_answers[i] = answers[i].innerHTML;
     answers[i].innerHTML = "";
   }
}

All that stuff works but what I need to add is the toggling.

I guess that in the event handler I might be able to compare the clicked 
object against each element in getElementByClassName("question") until I 
find a match; then its index will be the same as that of the answer I 
have to toggle. But that could be inefficient when there are many 
questions and answers.

My question, therefore, is how best to identify the corresponding answer 
when the user clicks on a question.

Any suggestions?


-- 
James Harris

[toc] | [next] | [standalone]


#36823

FromJames Harris <james.harris.1@gmail.com>
Date2019-06-07 17:59 +0100
Message-ID<qde54s$j9q$1@dont-email.me>
In reply to#36822
On 07/06/2019 17:35, James Harris wrote:
> Almost a complete beginner at JavaScript so there may be a better way to
> do this but ... what I am trying to do is have a web page consisting of
> pairs of questions and answers as in
> 
>     Question
>       Answer
>     Question
>       Answer
>     Question
>       Answer
> 
> where clicking on the question toggles whether the answer appears or
> not. Answers will initially be absent.

So the above would initially appear as

   Question
   Question
   Question

and users would have to click on a question to reveal the subsequent 
answer.

> 
> I've got that bit worked out in a way I like (will explain in a separate
> post). 

To explain the rationale behind the choices:

First, I want, for convenience, to be able to type the answers in 
directly under the questions to which they correspond. Since the page is 
intended to begin with the answers hidden that meant having them present 
but hiding them on page load.

Second, I don't want the way to hide the text to be by making it 
invisible (e.g. by setting a CSS property) as I fear that could end up 
with the browser's 'find' function irritating the user by finding text 
the user cannot see. That's why I decided to move the InnerHTML of the 
answers to and from an array.

Third, I want this to be compatible with many browsers and generations 
of browser so didn't want to use the data- features which I've heard are 
part of the 'ultra modern' HTML5. :-)

Fourth, I want the web page to be usable even if the browser does not 
have JavaScript enabled. In that case, all answers would have to be 
visible all the time. Again, that meant the page having the answers 
there by default and using JavaScript, if enabled, to hide the answers 
on page load.

That's my rationale for the basic approach. As I say, next thing is how 
to know which answer to toggle when a certain question is clicked. I 
guess this is well-trodden ground but I was evidently using the wrong 
keywords for Google to magic up an answer. Hence this query.


-- 
James Harris

[toc] | [prev] | [next] | [standalone]


#36828

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2019-06-07 20:33 +0200
Message-ID<2485496.mvXUDI8C0e@PointedEars.de>
In reply to#36823
James Harris wrote:

> To explain the rationale behind the choices:

Your design choices appear to be driven mostly by ignorance and 
misconceptions about Web development and Web browsers.  A recipe for 
disaster.

> First, I want, for convenience, to be able to type the answers in
> directly under the questions to which they correspond. Since the page is
> intended to begin with the answers hidden that meant having them present
> but hiding them on page load.

It is not a good idea to manipulate the document tree on page load as that 
will slow down rendering.  Hiding elements is OK, changing their content in 
most cases (and certainly in this one) is not.
 
> Second, I don't want the way to hide the text to be by making it
> invisible (e.g. by setting a CSS property) as I fear that could end up
> with the browser's 'find' function irritating the user by finding text
> the user cannot see.

Working browsers will not let users “Find” content that have style “display: 
none” or HTML5’s “hidden” attribute set.

> Third, I want this to be compatible with many browsers and generations
> of browser so didn't want to use the data- features which I've heard are
> part of the 'ultra modern' HTML5. :-)

For suitable values for “ultra modern”.  HTML5 is best current practice 
since almost 5 years ago – an eternity on the Web.  The current W3C 
Recommendation is HTML 5.2 of 2017, work on HTML 5.3 is in progress.

Be aware that using scripting instead of plain HTML and CSS already 
sacrifices some compatibility.
 
> Fourth, I want the web page

“Where we are developing, there are no "web pages".”¹

_______
¹  apologies to Robert Zemeckis
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36833

Fromdr.j.r.stockton@gmail.com
Date2019-06-08 01:43 -0700
Message-ID<51b7addb-c6dd-4e04-96f5-1094af54684f@googlegroups.com>
In reply to#36828
On Friday, 7 June 2019 19:33:45 UTC+1, Thomas 'PointedEars' Lahn  wrote:
 
> It is not a good idea to manipulate the document tree on page load as that 
> will slow down rendering.  Hiding elements is OK, changing their content in 
> most cases (and certainly in this one) is not.

Rendering is so quick on modern computers hat, for pages of reasonable size, worrying about its speed is pointless (likely exception : pages with too many large images, or with complex looping calculation that must be re-done of re-rendering).

> -- 
> PointedEars
> FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
> <https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
> Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36824

From"R.Wieser" <address@not.available>
Date2019-06-07 19:39 +0200
Message-ID<qde7ho$1274$1@gioia.aioe.org>
In reply to#36822
James,

> I guess that in the event handler I might be able to compare the clicked 
> object against each element in getElementByClassName("question") until I 
> find a match;

A match with what ?    And which event handler might that be ?    And what 
is started with ?

Although you posted code that has nothing to do with your question 
(all_hide), you fully forgot(?) to post the code which you currently have 
got for the toggeling you're after.   So whe have NO way to know what you 
are babbeling about when you mention "compare with". :-(

That is ... if you already have (the first steps of) such code.   Do you ?

If not, you could do worse than to look here

https://www.w3schools.com/jsref/event_onclick.asp

and than especially the example starting with

<p onclick="myFunction(this, 'red')">

Yeah, "onclick" is the keyword.  I threw it into google together with 
"javascript" and got the above link as the very first result.    Why didn't 
you find that, or a comparable example yourself ?   Did you at all /look/ ?

Regards,
Rudy Wieser

[toc] | [prev] | [next] | [standalone]


#36844

FromJames Harris <james.harris.1@gmail.com>
Date2019-06-08 18:52 +0100
Message-ID<qdgsl6$js0$1@dont-email.me>
In reply to#36824
On 07/06/2019 18:39, R.Wieser wrote:
> James,
> 
>> I guess that in the event handler I might be able to compare the clicked
>> object against each element in getElementByClassName("question") until I
>> find a match;
> 
> A match with what ?    And which event handler might that be ?    And what
> is started with ?
> 
> Although you posted code that has nothing to do with your question
> (all_hide), you fully forgot(?) to post the code which you currently have
> got for the toggeling you're after.   So whe have NO way to know what you
> are babbeling about when you mention "compare with". :-(
> 
> That is ... if you already have (the first steps of) such code.   Do you ?

That's OK. I've got it working. Full initial code posted at 
https://groups.google.com/d/msg/comp.lang.javascript/yOMha0ZBCeg/HGbOPxkWBgAJ. 




-- 
James Harris

[toc] | [prev] | [next] | [standalone]


#36825

FromJulio Di Egidio <julio@diegidio.name>
Date2019-06-07 10:45 -0700
Message-ID<e1c1be71-2179-492d-934e-bb47d477ebce@googlegroups.com>
In reply to#36822
On Friday, 7 June 2019 18:35:49 UTC+2, James Harris  wrote:

> My problem is in identifying the corresponding answer when a 
> question is clicked.

The canonical way is the questions originally are numbered,
then you can use element id's to refer to specific elements,
plus you do not have the problem that any change in the structure
of your html breaks the whole thing (IOW, you do not tie the
functionality to the specific markup).

> <div class = "question" id="q_123">Why?</div>
> <div class = "answer" id="a_123">Because</div>

HTH,

Julio

[toc] | [prev] | [next] | [standalone]


#36845

FromJames Harris <james.harris.1@gmail.com>
Date2019-06-08 18:57 +0100
Message-ID<qdgstj$ltv$1@dont-email.me>
In reply to#36825
On 07/06/2019 18:45, Julio Di Egidio wrote:
> On Friday, 7 June 2019 18:35:49 UTC+2, James Harris  wrote:
> 
>> My problem is in identifying the corresponding answer when a
>> question is clicked.
> 
> The canonical way is the questions originally are numbered,
> then you can use element id's to refer to specific elements,
> plus you do not have the problem that any change in the structure
> of your html breaks the whole thing (IOW, you do not tie the
> functionality to the specific markup).
> 
>> <div class = "question" id="q_123">Why?</div>
>> <div class = "answer" id="a_123">Because</div>

I didn't want to put the user through the hassle of having to assign 
unique ids but I used your idea to generate the ids automatically with

   var questions = document.getElementsByClassName(QCLASS);

   // Go through each question
   for (question of questions)
   {
     // Find the following answer
     targ = next_sibling(question, Node.ELEMENT_NODE);
     if (targ && targ.className === ACLASS)
     {
       // Give the question a unique id
       question.id = QID + i;

Then the id is used as a key to save the answer text in an array with

       // Move the answer out of the div into the designated array
       saved_answers[question.id] = targ.innerHTML;
       targ.innerHTML = BLANK_ANSWER;

       // Next id number
       i++;
     }
   }



-- 
James Harris

[toc] | [prev] | [next] | [standalone]


#36857

FromJulio Di Egidio <julio@diegidio.name>
Date2019-06-09 05:44 -0700
Message-ID<492b8f9f-2018-4f8a-a79a-a7e846fe8507@googlegroups.com>
In reply to#36845
On Saturday, 8 June 2019 19:57:11 UTC+2, James Harris  wrote:
> On 07/06/2019 18:45, Julio Di Egidio wrote:
> > On Friday, 7 June 2019 18:35:49 UTC+2, James Harris  wrote:
> > 
> >> My problem is in identifying the corresponding answer when a
> >> question is clicked.
> > 
> > The canonical way is the questions originally are numbered,
> > then you can use element id's to refer to specific elements,
> > plus you do not have the problem that any change in the structure
> > of your html breaks the whole thing (IOW, you do not tie the
> > functionality to the specific markup).
> > 
> >> <div class = "question" id="q_123">Why?</div>
> >> <div class = "answer" id="a_123">Because</div>
> 
> I didn't want to put the user through the hassle of having to assign 
> unique ids but I used your idea to generate the ids automatically with
> 
>    var questions = document.getElementsByClassName(QCLASS);
> 
>    // Go through each question
>    for (question of questions)
>    {
>      // Find the following answer
>      targ = next_sibling(question, Node.ELEMENT_NODE);
>      if (targ && targ.className === ACLASS)
>      {
>        // Give the question a unique id
>        question.id = QID + i;
> 
> Then the id is used as a key to save the answer text in an array with
> 
>        // Move the answer out of the div into the designated array
>        saved_answers[question.id] = targ.innerHTML;
>        targ.innerHTML = BLANK_ANSWER;
> 
>        // Next id number
>        i++;
>      }
>    }

Of course you would not eventually write it by hand, the data usually comes
from a database or some other source and the page or parts of it are generated
or loaded dynamically: it just goes without saying, plus it's a separate
logical stage, i.e. you can start by mocking by hand and later go to
automatically generated.

You then do a completely pointless operation there, as once you have found the
elements, you just don't need *at that point* to set and keep id's, you already
have the references and would just keep those.

Overall, you and the whole band-wagon here just have no idea what you are
doing: indeed you keep missing the *one critical point* here, which is do not
tie your logic to the markup!

HTH,

Julio

[toc] | [prev] | [next] | [standalone]


#36826

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2019-06-07 20:16 +0200
Message-ID<1860328.oMNUckLgyt@PointedEars.de>
In reply to#36822
James Harris wrote:

> Almost a complete beginner at JavaScript so there may be a better way to
> do this but ... what I am trying to do is have a web page consisting of
> pairs of questions and answers as in
> 
>    Question
>      Answer
>    Question
>      Answer
>    Question
>      Answer
> 
> where clicking on the question toggles whether the answer appears or
> not. Answers will initially be absent.

You should probably read about “event bubbling”.  The event listener should 
have the following general form:

  var listener = function (event) {
    const classList = event.target.classList;

    if (classList.contains('js-question'))
    {
      if (classList.contains('shown'))
      {
        classList.remove('shown');
      }
      else
      {
        classList.add('shown');
      }
    }
  };

Then you do the showing and hiding with CSS rules based on those CSS 
classes.

But there is no scripting needed for this in modern graphical browsers (and 
text browser users want to see everything at a glance):

HTML:

  <div class="question">
    <label for="checkbox-foo">question</label>
    <input type="checkbox" class="checkbox" id="checkbox-foo">
    <div class="answer">
      answer
    </div>
  </div>

CSS:

  /* or whatever style you like */
  .question .checkbox { visibility: hidden; }
  
  .question .checkbox:not(:checked) ~ .answer { display: none; }
  .question .checkbox:checked .answer { display: block; }

Using the :not(:checked) pseudo-class explicitly prevents the answer from 
being hidden if the :checked pseudo-class is not supported.

This approach can be used for all kinds of interactive widgets, e. g. tree 
widgets too.

<https://developer.mozilla.org/en-US/docs/Web/CSS/Reference#Selectors>

If you can target HTML5 users only, then you can also use the “details” 
element, in which case CSS is optional:

<https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details>
  
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36831

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2019-06-07 22:48 +0200
Message-ID<5257802.DvuYhMxLoT@PointedEars.de>
In reply to#36826
Thomas 'PointedEars' Lahn wrote:

> But there is no scripting needed for this in modern graphical browsers
> (and text browser users want to see everything at a glance):
> 
> HTML:
> 
>   <div class="question">
>     <label for="checkbox-foo">question</label>
>     <input type="checkbox" class="checkbox" id="checkbox-foo">
>     <div class="answer">
>       answer
>     </div>
>   </div>
> 
> CSS:
> 
>   /* or whatever style you like */
>   .question .checkbox { visibility: hidden; }
>   
>   .question .checkbox:not(:checked) ~ .answer { display: none; }
>   .question .checkbox:checked .answer { display: block; }

Minor mistake: This line should be

    .question .checkbox:checked ~ .answer { display: block; }

to select elements whose “class” attribute contains the class name “answer” 
that are also siblings following the checkbox.
 
> Using the :not(:checked) pseudo-class explicitly prevents the answer from
> being hidden if the :checked pseudo-class is not supported.
> 
> This approach can be used for all kinds of interactive widgets, e. g. tree
> widgets too.
> 
> <https://developer.mozilla.org/en-US/docs/Web/CSS/Reference#Selectors>

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36829

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2019-06-07 20:36 +0200
Message-ID<11309336.O9o76ZdvQC@PointedEars.de>
In reply to#36822
Stefan Ram wrote:

>   Tested under a recent "Firefox":
> 
>   main.html
> 
> <!DOCTYPE html>
> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
> <head><meta charset="UTF-8" />
> <title>Q and A</title><style type="text/css">
> 
> hide { display: none }
> 
> </style></head><body>
> 
> <ul>
>     <dl class="question">
>         <dt>question</dt><dd>What is 1+1?</dd></dl>
>     <dl class="answer">
>         <dt>answer</dt><dd>2</dd></dl>
> </ul>
> <ul>
>     <dl class="question">
>         <dt>question</dt><dd>What is 4-1?</dd></dl>
>     <dl class="answer">
>         <dt>answer</dt><dd>3</dd></dl>
> </ul>
> 
> <pre><code><script>/*<![CDATA[*/
> 
> [].map.call
> ( document.getElementsByClassName( "answer" ),
>   answer => answer.classList.add( "hide" ));
> 
> [].map.call
> ( document.getElementsByClassName( "question" ),
>   question => question.addEventListener
>   ( "click",
>     event =>
>     event.currentTarget.parentNode.lastElementChild.classList.toggle
>     ( "hide" )))

JFTR (I know from experience that it is futile to tell Stefan Ram anything):

This is NOT remotely how proper code looks like.  If you would be employed
in the industry, you would probably get disciplined or fired for this.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36832

FromJJ <jj4public@vfemail.net>
Date2019-06-08 12:57 +0700
Message-ID<rzu6rgkcx0ct.be7zd8a6ci7q.dlg@40tude.net>
In reply to#36822
On Fri, 7 Jun 2019 17:35:40 +0100, James Harris wrote:

> Almost a complete beginner at JavaScript so there may be a better way to 
> do this but ... what I am trying to do is have a web page consisting of 
> pairs of questions and answers as in
> 
>    Question
>      Answer
>    Question
>      Answer
>    Question
>      Answer
> 
> where clicking on the question toggles whether the answer appears or 
> not. Answers will initially be absent.
> 
> I've got that bit worked out in a way I like (will explain in a separate 
> post). My problem is in identifying the corresponding answer when a 
> question is clicked.
> 
> The web page has the form
> 
> <div class = "question">Why?</div>
> <div class = "answer">Because</div>
> 
> <div class = "question">When?</div>
> <div class = "answer">Soon</div>
> 
> On DOMContentLoaded I run the following function
> 
> function all_hide()
> {
>    var answers = document.getElementsByClassName("answer");
>    for (var i = 0; i < answers.length; i++)
>    {
>      saved_answers[i] = answers[i].innerHTML;
>      answers[i].innerHTML = "";
>    }
> }
> 
> All that stuff works but what I need to add is the toggling.
> 
> I guess that in the event handler I might be able to compare the clicked 
> object against each element in getElementByClassName("question") until I 
> find a match; then its index will be the same as that of the answer I 
> have to toggle. But that could be inefficient when there are many 
> questions and answers.
> 
> My question, therefore, is how best to identify the corresponding answer 
> when the user clicks on a question.
> 
> Any suggestions?

With that HTML structure, you can setup the click event handler like below.

  addEventListener("click", e => {
    e = e.target;
    if (e.classList.contains("question")) {
      e = e.nextElementSibling.style;
      e.display = e.display ? "" : "block";
    }
  });

[toc] | [prev] | [next] | [standalone]


#36835

FromJames Harris <james.harris.1@gmail.com>
Date2019-06-08 10:30 +0100
Message-ID<qdfv79$dvn$1@dont-email.me>
In reply to#36832
On 08/06/2019 06:57, JJ wrote:
> On Fri, 7 Jun 2019 17:35:40 +0100, James Harris wrote:

...

>> <div class = "question">Why?</div>
>> <div class = "answer">Because</div>
>>
>> <div class = "question">When?</div>
>> <div class = "answer">Soon</div>

...

> With that HTML structure, you can setup the click event handler like below.
> 
>    addEventListener("click", e => {
>      e = e.target;
>      if (e.classList.contains("question")) {
>        e = e.nextElementSibling.style;
>        e.display = e.display ? "" : "block";
>      }
>    });
> 

Good answer.

Were there any browsers which supported JavaScript but not the .style 
property?

FWIW I got the system to work as I want it to. The complete code is 
below. Your answer may be better but I quite like what I came up with.

I am not familiar with JavaScript so folks reading the code may find 
things they don't like or which could be better. Feel free to criticise 
it. Note that I avoided nextElementSibling for compatibility.


<script type = "text/javascript">

/**********************************************************************
  *
  * Globals
  *
  **********************************************************************/

var saved_answers = [];   //Answers saved from the HTML
var BLANK_ANSWER = "";    //The inner HTML to use when answer missing
var QCLASS = "question";  //The element class to use for questions
var ACLASS = "answer";    //The element class to use for answers
var QID = "Q-";           //The prefix to set on question ids



/**********************************************************************
  *
  * Hide all the answers (if JavaScript is supported)
  *
  **********************************************************************/

function all_hide()
{
   var targ;
   var i = 0;
   var questions = document.getElementsByClassName(QCLASS);
   for (question of questions)
   {
     targ = next_sibling(question, Node.ELEMENT_NODE);
     if (targ && targ.className === ACLASS)
     {
       question.id = QID + i;
       saved_answers[question.id] = targ.innerHTML;
       targ.innerHTML = BLANK_ANSWER;
       i++;
     }
   }
}



/**********************************************************************
  *
  * Make each question clickable
  *
  **********************************************************************/

function questions_make_clickable()
{
   var questions = document.getElementsByClassName(QCLASS);
   for (question of questions)
   {
     question.addEventListener("click", qclick);
   }
}



/**********************************************************************
  *
  * Find the next sibling of a specified type. Use this in preference to
  * nextElementSibling if wanting compatibility with browsers which do
  * not support that function.
  *
  **********************************************************************/

function next_sibling(from, node_type)
{
   var targ = from;
   do
   {
     targ = targ.nextSibling;
   }
   while (targ && targ.nodeType !== node_type);
   return targ;
}



/**********************************************************************
  *
  * Respond to a click on a question
  *
  **********************************************************************/

function qclick(ev)
{
   var targ = next_sibling(ev.target, Node.ELEMENT_NODE);
   if (targ && targ.className === ACLASS)
   {
     // Toggle the answer
     if (targ.innerHTML === BLANK_ANSWER)
     {
       targ.innerHTML = saved_answers['' + ev.target.id];
     }
     else
     {
       targ.innerHTML = BLANK_ANSWER;
     }
   }
}



/**********************************************************************
  *
  * Code to run on page load
  *
  **********************************************************************/

window.addEventListener(
   'DOMContentLoaded', (event) =>
   {
     all_hide();
     questions_make_clickable();
   }
);

</script>


-- 
James Harris

[toc] | [prev] | [next] | [standalone]


#36839

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2019-06-08 12:13 +0200
Message-ID<5498390.lOV4Wx5bFT@PointedEars.de>
In reply to#36835
James Harris wrote:

> On 08/06/2019 06:57, JJ wrote:
>> On Fri, 7 Jun 2019 17:35:40 +0100, James Harris wrote:
>>> <div class = "question">Why?</div>
>>> <div class = "answer">Because</div>
>>>
>>> <div class = "question">When?</div>
>>> <div class = "answer">Soon</div>
>> 
>> With that HTML structure, you can setup the click event handler like
>> below.
>> 
>>    addEventListener("click", e => {

addEventListener must be called as method of the event target, not the 
global object.

>>      e = e.target;
>>      if (e.classList.contains("question")) {

This is actually insufficient, see below.

>>        e = e.nextElementSibling.style;
>>        e.display = e.display ? "" : "block";

Looking for siblings with script code and writing CSSOM code is unnecessary 
if you use the sibling *element* selector(s) of CSS with attached CSS rules.  
The latter is also much easier to maintain and less error-prone (a sibling 
*node* can be a text node, and text nodes do not have a “style” property; as 
a result, a TypeError exception is thrown on this line then).

In that regard, my code needs to be improved slightly so that it checks 
whether, if the object in question does not have a “classList” property (is 
not an element node), one of its ancestors has and its “class” attribute 
contains the pertinent class name.  There is this trade-off with event 
bubbling to find out the proper ancestor if a descendant was the event 
target; this problem does not exist if event listeners are being added to 
the proper ancestors directly, but then it has to be added to every single 
one of them.  Insofar using event bubbling this way might actually not 
always be the best strategy (speed tests pending; it is also situation-
dependent).

>>      }
>>    });
>> 
> 
> Good answer.

Rest assured that as a beginner you are not in any position to tell.

It is a striking feature of ECMAScript-based programming languages and their 
applications in particular that, because they seem comparably easy to learn, 
people very quickly become overconfident in their estimations of their own 
knowledge about them.  Some of them even take their hubris to writing more 
or less clueless books (Flanagan, Crockford, Resig).  There is a culture of 
cargo cult programming.  Blind leading the blind.

A quote (ignoring the wrong spelling, indication overgeneralization):

| > If you get a bunch of authors […] that state the same "best practices"
| > in any programming language, then you can bet who is wrong or right...
| Not with javascript. Nonsense propagates like wildfire in this field.
|   -- Richard Cornford, comp.lang.javascript, 2011-11-14
 
> Were there any browsers which supported JavaScript but not the .style
> property?

Yes.
 
> FWIW I got the system to work as I want it to. The complete code is
> below. Your answer may be better but I quite like what I came up with.

Whether *you* *like* it does NOT matter.  It must *work* for the 
*customer/user*.  That is the first rule of software development,
in particular of Web development where you have almost no idea
where and under which circumstances your code is going to run.

> I am not familiar with JavaScript so folks reading the code may find
> things they don't like or which could be better.

Again, it is not a matter of “like”.  There are valid *reasons* why it is 
being recommended to do some things one way and not the other ways.

> Feel free to criticise it.

Thanks, but no, thanks.  I have told you how to do this easily, efficiently, 
and in a backwards-compatible way. You decided to do it hopelessly 
complicated, inefficient, and in an incompatible way instead.  Now you have 
to live with the consequences.

> [convuluted mess]

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36841

FromJohn G Harris <niam@jghnorth.org.uk.invalid>
Date2019-06-08 13:35 +0100
Message-ID<isanfep7o9783ts03jk9cth7h8k224jbg5@4ax.com>
In reply to#36839
On Sat, 08 Jun 2019 12:13:02 +0200, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:

  <snip>
>It is a striking feature of ECMAScript-based programming languages and their 
>applications in particular that, because they seem comparably easy to learn, 
>people very quickly become overconfident in their estimations of their own 
>knowledge about them.  Some of them even take their hubris to writing more 
>or less clueless books (Flanagan, Crockford, Resig).
  <snip>

Hallelujah! Thomas agrees with me about Crockford. (See one of the few
book reviews in this news group).

  John

[toc] | [prev] | [next] | [standalone]


#36842

FromJohn G Harris <niam@jghnorth.org.uk.invalid>
Date2019-06-08 13:45 +0100
Message-ID<6dbnfe9sofn0brlec385a4b1k30q8b46i5@4ax.com>
In reply to#36839
On Sat, 08 Jun 2019 12:13:02 +0200, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:

  <snip>
>Whether *you* *like* it does NOT matter.  It must *work* for the 
>*customer/user*.  That is the first rule of software development,
>in particular of Web development where you have almost no idea
>where and under which circumstances your code is going to run.
  <snip>

An experienced programmer who mutated into quality control told me
about a particular product Release Candidate :

She :
"Look what happens when a User does *this*." 
Program goes SPLAT!

Programmer :
"Why would anyone do *that*?"
 
She :
"I don't know, but they do!"

  John

[toc] | [prev] | [next] | [standalone]


#36846

FromJames Harris <james.harris.1@gmail.com>
Date2019-06-08 19:03 +0100
Message-ID<qdgtag$odo$1@dont-email.me>
In reply to#36839
On 08/06/2019 11:13, Thomas 'PointedEars' Lahn wrote:
> James Harris wrote:

...

>> Were there any browsers which supported JavaScript but not the .style
>> property?
> 
> Yes.

In that case I am right to design the system as I have: To use 
JavaScript for processing (including the 'hiding' of answers), and to 
use CSS purely for appearance.

>   
>> FWIW I got the system to work as I want it to. The complete code is
>> below. Your answer may be better but I quite like what I came up with.
> 
> Whether *you* *like* it does NOT matter.  It must *work* for the
> *customer/user*.  That is the first rule of software development,
> in particular of Web development where you have almost no idea
> where and under which circumstances your code is going to run.

As the user of it, I like it.

> 
>> I am not familiar with JavaScript so folks reading the code may find
>> things they don't like or which could be better.
> 
> Again, it is not a matter of “like”.  There are valid *reasons* why it is
> being recommended to do some things one way and not the other ways.
> 
>> Feel free to criticise it.
> 
> Thanks, but no, thanks.  I have told you how to do this easily, efficiently,
> and in a backwards-compatible way. You decided to do it hopelessly
> complicated, inefficient, and in an incompatible way instead.  Now you have
> to live with the consequences.
> 
>> [convuluted mess]

It's clear, easy to read, separates concepts, is written to cope with 
multiple browsers and browser settings, and should be fast. That's far 
from a 'mess'. I'd call it a good solution.


-- 
James Harris

[toc] | [prev] | [next] | [standalone]


#36852

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2019-06-08 21:11 +0200
Message-ID<2994022.aeNJFYEL58@PointedEars.de>
In reply to#36846
James Harris wrote:

> On 08/06/2019 11:13, Thomas 'PointedEars' Lahn wrote:
>> James Harris wrote:
>>> Were there any browsers which supported JavaScript but not the .style
>>> property?
>> Yes.

Actually, “No”, because the existence of the “style” *property* more or less 
requires an ECMAScript-based runtime environment.  The correct answer is 
“Yes” for the “style” _element_ and style _attribute_.

Also note that the answer made no indication as to whether the question made 
sense.

> In that case I am right to design the system as I have:

No.

>>> FWIW I got the system to work as I want it to. The complete code is
>>> below. Your answer may be better but I quite like what I came up with.
>> 
>> Whether *you* *like* it does NOT matter.  It must *work* for the
>> *customer/user*.  That is the first rule of software development,
>> in particular of Web development where you have almost no idea
>> where and under which circumstances your code is going to run.
> 
> As the user of it, I like it.

Pardon?  If you are the only user, why did *you* talk about backwards 
compatibility?

>>> [[convoluted mess]]
> 
> It's clear, easy to read, separates concepts, is written to cope with
> multiple browsers and browser settings, and should be fast. That's far
> from a 'mess'. I'd call it a good solution.

You have no idea.  Globals?  Loops (even with for…of)?  innerHTML?

<https://github.com/airbnb/javascript>

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#36854

Fromdr.j.r.stockton@gmail.com
Date2019-06-08 14:18 -0700
Message-ID<bf819cec-05e8-4979-a407-f0ceffb4f504@googlegroups.com>
In reply to#36852
On Saturday, 8 June 2019 20:11:09 UTC+1, Thomas 'PointedEars' Lahn  wrote:
> James Harris wrote:
> 
> > On 08/06/2019 11:13, Thomas 'PointedEars' Lahn wrote:
> >> James Harris wrote:
> >>> Were there any browsers which supported JavaScript but not the .style
> >>> property?
> >> Yes.
> 
> Actually, “No”, because the existence of the “style” *property* more or less 
> requires an ECMAScript-based runtime environment.  

Nonsense.
(1.1) I have pages which use CSS styles which are set in the source HTML file and are never changed after loading.  I don't think I've ever set or changed the float property after loading, and I don't recall dynamically altering margins or padding either.
(1.2) Internet Explorer supports   <script type="text/vbscript">    and VBScript is not ECMAScript-based.  I expect that VBscript can manipulate CSS styles.
(1.3) Anyone who can write an HTML engine could, for example, support <script type="text/fortran">  and  <script type="text/algol68">.

(2) He was in essence asking "does script require style" but you have answered "does style require script".

For some while, I was using JScript without knowing of the existence of style.

-- 
  (c) John Stockton, near London, UK.  Using Google Groups.           |
 Mail: J.R.""""""""@physics.org - or as Reply-To, if any.             |

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.javascript


csiph-web