Putting functionality back into <blockquote />

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Toby A Inkster

    Putting functionality back into <blockquote />

    In "the other place" Jukka has pointed out that semantically <blockquote/>
    is useless in many browsers, so I'm experimenting with Javascript to put
    some functionality back into <blockquote/>.

    The basic idea is to use Javascript to pop up a small link to the
    blockquote's cite attribute on hover.

    You can see what I have so far here:



    There are two things that still need fixing though, and that is where all
    you lovely people come in, as I sadly don't have the JS knowledge to fix
    it on my own.

    1. When the "cite" text is hovered over, the link goes invisible. The link
    still works, but this is certainly not desirable behaviour. I believe it
    has to do with event bubbling. Any ideas?

    2. I need a way to attach the bqHover and bqHoverOut functions to the
    blockquote without using the onmouseover and onmouseout HTML attributes so
    that all the JS can go in one external script file. I think
    addEventListene r comes into play here, but I don't know very much about
    that and have never gotten such things to work in anything besides Gecko.
    Ideally I'd want a solution that works in IE6/Win, Gecko and Opera 7.
    Konqueror, Safari and IE5 for Windows and/or Mac would be a bonus. But
    I'll take what I can get.

    Thanks in advance for any light you can shed onto the matter.

    --
    Toby A Inkster BSc (Hons) ARCS
    Contact Me - http://www.goddamn.co.uk/tobyink/?page=132
  • Yann-Erwan Perio

    #2
    Re: Putting functionality back into &lt;blockquo te /&gt;

    Toby A Inkster wrote:
    [color=blue]
    > In "the other place" Jukka has pointed out that semantically <blockquote/>
    > is useless in many browsers, so I'm experimenting with Javascript to put
    > some functionality back into <blockquote/>.[/color]

    I'm not well-versed in HTML subtleties, but according to the HTML
    reference, BLOCKQUOTE elements only offer a "cite" attribute, aside of
    the ones defined by the %attrs; entity. Since you're likely to want to
    precise source, date, author etc, ISTM that blockquote cannot be
    particularly enhanced, you'd indeed use a larger structure most of the
    time (for instance a DIV as a container and other tags for other
    information).

    The enhancement you want to set up is probably the only logical one
    (apart from working with extended DTD), although I think that having the
    link already existing as part of an additional tag would probably be
    safer (for instance you position your link relatively to the top-left
    blockquote point, but what if the quotation needs scrolling?).
    [color=blue]
    > 1. When the "cite" text is hovered over, the link goes invisible. The link
    > still works, but this is certainly not desirable behaviour. I believe it
    > has to do with event bubbling.[/color]

    That's correct, moving into an inner element fires the mouseout event of
    the outer element, then the event mouseover event is fired from the
    inner element and bubbles to the outer element; each time the
    appropriate handlers being triggered.

    You can manage this issue by studying the origin/direction of the event
    and taking adapted decision (or using mouseenter-mouseleave non-standard
    events).
    [color=blue]
    > 2. I need a way to attach the bqHover and bqHoverOut functions to the
    > blockquote without using the onmouseover and onmouseout HTML attributes so
    > that all the JS can go in one external script file. I think
    > addEventListene r comes into play here,[/color]

    You can always define mouseover/mouseout handlers outside of the tag
    declaration, using a reference to the element, so that's not a problem.
    Alternatively, you could also set up some kind of mousemove conception,
    though this would be more complex to manage.

    "addEventListen er" is a way to define a handler, it is useful when you
    want to set up many listeners to the object (and for the sort of script
    you want to design it would indeed make sense to use addEventListene r
    and IE's attachEvent methods - I prefer using a specific function for
    that, though).

    Here's a simple example of what you're asking; tested IE6, Mozilla 1.5,
    Opera 7 - you might surprisingly experience flickering with IE if you
    include several block-level elements in the blockquote - I think that
    nothing can be done about that. All the script part can be safely
    inserted as a js include if needed.


    <script type="text/javascript">
    (function(){

    var CITE_VALUE="Jum p!";
    var CITE_CLASS="jsC ite";

    function _e(obj, evt, func) {
    if(obj[evt]) {
    obj[evt]=(function(orig inalHandler) {
    return function () {
    func.apply(obj, arguments);
    return originalHandler .apply(obj, arguments);
    }
    })(obj[evt]);
    } else
    obj[evt]=func;
    }

    function contains(contai ner, containee) {
    if(container.co ntains) {
    return container.conta ins(containee);
    } else {
    while(containee && containee!=cont ainer)
    containee=conta inee.parentNode ;
    return !!containee;
    }
    }

    function mover (evt) {
    evt=evt||window .event;
    var related=evt.fro mElement||evt.r elatedTarget;
    if(related) {
    if(!contains(th is, related)) {
    Cite.define(thi s.citeObject, this);
    Cite.setVisible (true);
    }
    }
    }

    function mout(evt){
    evt=evt||window .event;
    var related=evt.toE lement||evt.rel atedTarget;
    if(related) {
    if(!contains(th is, related)) {
    Cite.define(thi s.citeObject, this);
    Cite.setVisible (false);
    }
    }
    }

    var Cite = (function() {
    var $child, $parent;
    return {
    define:function (child, parent){
    if(!child) {
    var a, c, d=document;
    if((c=parent.ge tAttribute("cit e"))!="") {
    a=d.createEleme nt("a");
    a.href=c;
    a.appendChild(d .createTextNode (CITE_VALUE));
    parent.citeObje ct=d.createElem ent("span");
    parent.citeObje ct.className=CI TE_CLASS;
    parent.citeObje ct.appendChild( a);
    child=parent.ci teObject;
    }
    }
    $child=child;
    $parent=parent;
    },
    setVisible:func tion(bVisible){
    if($child && $parent)
    $parent[(bVisible?"appe nd":"remove")+" Child"]($child);
    }
    }
    })();

    if(typeof Function!="unde fined" &&
    Function.protot ype &&
    Function.protot ype.apply) {
    _e(window, "onload",
    function(evt){
    var d=document;
    if(d && d.body && d.createElement && d.body.appendCh ild &&
    typeof d.body.parentNo de!="undefined" &&
    d.getElementsBy TagName) {

    var bq=d.getElement sByTagName("blo ckquote");
    for(var ii=0; ii<bq.length; ii++) {
    _e(bq[ii], "onmouseove r", mover);
    _e(bq[ii], "onmouseout ", mout);
    }

    }
    }
    );
    }
    })();
    </script>

    <style type="text/css">
    blockquote {
    position: relative;
    margin-left:0; padding-left:4em;
    }
    blockquote .jsCite {
    font-size: 85%;
    position: absolute; top: 0; left: 0;
    padding: 1px;
    border: 1px dotted black;
    }
    </style>

    <blockquote cite="hello.htm l">
    <p>Hello</p>
    </blockquote>



    HTH
    Yep.

    Comment

    • Richard Cornford

      #3
      Re: Putting functionality back into &lt;blockquo te /&gt;

      "Yann-Erwan Perio" <y-e.perio@em-lyon.com> wrote in message
      news:402e9700$0 $28743$626a14ce @news.free.fr.. .
      <snip>[color=blue]
      > function contains(contai ner, containee) {
      > if(container.co ntains) {
      > return container.conta ins(containee);
      > } else {
      > while(containee && containee!=cont ainer)
      > containee=conta inee.parentNode ;
      > return !!containee;
      > }
      > }[/color]

      Knowing your interest in such things, you might like to know that I
      recently did a speed test of:-

      var boolValue = !!x;

      - against -

      var boolValue = Boolean(x);

      - (both executed in the context of a global function) and
      type-converting to boolean by calling the Boolean constructor as a
      function outperformed the double NOT operation by about a factor of 4
      (with the usual browser variations). Unfortunately they are not directly
      comparable operations, as the scope resolution of - Boolean - as an
      identifier would influence the results. With a long scope chain the
      extra work in the resolution of the identifier might swing the
      performance of the forced type-conversion back in favour of double NOT.

      <snip>[color=blue]
      > if(typeof Function!="unde fined" &&
      > Function.protot ype &&
      > Function.protot ype.apply) {
      > _e(window, "onload",
      > function(evt){
      > var d=document;
      > if(d && d.body && d.createElement && d.body.appendCh ild &&
      > typeof d.body.parentNo de!="undefined" &&
      > d.getElementsBy TagName) {[/color]
      <snip>

      I was a little surprised not to see an explicit test for
      d.body.removeCh ild among those. ;-)

      Richard.


      Comment

      • Yann-Erwan Perio

        #4
        Re: Putting functionality back into &lt;blockquo te /&gt;

        Richard Cornford wrote:

        [color=blue]
        > Knowing your interest in such things,[/color]

        Indeed:-)
        [color=blue]
        > you might like to know that I
        > recently did a speed test of:-
        >
        > var boolValue = !!x;
        >
        > - against -
        >
        > var boolValue = Boolean(x);
        >
        > - (both executed in the context of a global function) and
        > type-converting to boolean by calling the Boolean constructor as a
        > function outperformed the double NOT operation by about a factor of 4
        > (with the usual browser variations).[/color]

        I believe that according to Ecma, this would make sense, although the
        implementation of Boolean isn't described (it is just said it should
        call toBoolean).

        Ah! but now I'm quite confused with the following simple test case here,
        which gives opposite results on my WinXP/PIII450:

        IE6 Mozilla1.5 Opera7.23
        Using Boolean 3265 650 1372
        using !! 2584 271 1062



        <textarea id="results" rows="10" cols="60"></textarea>
        <script type="text/javascript">
        function test(){
        var d1, d2, d3, b;

        d1=new Date();
        for(var ii=0; ii<100000; ii++)
        b=Boolean(docum ent);
        d2=new Date();
        for(var k=0; k<100000; k++)
        b=!!document;
        d3=new Date();

        document.getEle mentById("resul ts").value+=
        "Boolean:"+ (d2-d1)+" !!:"+(d3-d2)+"\n";
        }

        test();
        </script>


        What do I miss?
        [color=blue][color=green]
        >> if(d && d.body && d.createElement && d.body.appendCh ild &&
        >> typeof d.body.parentNo de!="undefined" &&
        >> d.getElementsBy TagName) {[/color][/color]
        [color=blue]
        > I was a little surprised not to see an explicit test for
        > d.body.removeCh ild among those. ;-)[/color]

        Argh! You're right of course, this test is absolutely required here - it
        seems I tend to be dreaming too much when finishing writing scripts:-)


        Cheers,
        Yep.

        Comment

        • Richard Cornford

          #5
          Re: Putting functionality back into &lt;blockquo te /&gt;

          "Yann-Erwan Perio" <y-e.perio@em-lyon.com> wrote in message
          news:403125ce$0 $22520$626a14ce @news.free.fr.. .
          <snip>[color=blue]
          >Ah! but now I'm quite confused with the following simple test
          >case here, which gives opposite results on my WinXP/PIII450:
          >
          >IE6 Mozilla1.5 Opera7.23
          >Using Boolean 3265 650 1372
          >using !! 2584 271 1062[/color]
          <snip>[color=blue]
          > What do I miss?[/color]

          Probably a mistake in my test script. I cannot find it now, which is odd
          because I keep all my seed test scripts together (I also cannot find a
          similar test comparing concatenation with the String constructor when
          forcing type-conversion to a string). But I recreated the script and got
          opposite results, specifically double NOT outperformed the Boolean
          constructor (by a factor of 10 this time). Sorry for being misleading.
          <snip>

          Richard.


          Comment

          Working...