Best html questions in April 2012

Cleaning HTML by removing extra/redundant formatting tags

18 votes

I have been using CKEditor wysiwyg editor for a website where users are allowed to use the HTML editor to add some comments. I ended up having some extremely redundant nested HTML code in my database that is slowing down the viewing/editing of these comments.

I have comments that look like this (this is a very small example. I have comments with over 100 nested tags):

<p>
 <strong>
  <span style="font-size: 14px">
   <span style="color: #006400">
     <span style="font-size: 14px">
      <span style="font-size: 16px">
       <span style="color: #006400">
        <span style="font-size: 14px">
         <span style="font-size: 16px">
          <span style="color: #006400">This is a </span>
         </span>
        </span>
       </span>
      </span>
     </span>
    </span>
    <span style="color: #006400">
     <span style="font-size: 16px">
      <span style="color: #b22222">Test</span>
     </span>
    </span>
   </span>
  </span>
 </strong>
</p>

My questions are:

  • Is there any library/code/software that can do a smart (i.e. format-aware) clean-up of the HTML code, removing all redundant tags that have no effect on the formatting (because they're overridden by inner tags) ? I've tried many existing online solutions (such as HTML Tidy). None of them do what I want.

  • If not, I'll need to write some code for HTML parsing and cleaning. I am planning to use PHP Simple HTML DOM to traverse the HTML tree and find all tags that have no effect. Do you suggest any other HTML parser that is more suitable for my purpose?

Thanks

.

Update:

I have written some code to analyze the HTML code that I have. All the HTML tags that I have are:

  • <span> with styles for font-size and/or color
  • <font> with attributes color and/or size
  • <a> for links (with href)
  • <strong>
  • <p> (single tag to wrap the whole comment)
  • <u>

I can easily write some code to convert the HTML code into bbcode (e.g. [b], [color=blue], [size=3], etc). So I above HTML will become something like:

[b][size=14][color=#006400][size=14][size=16][color=#006400]
[size=14][size=16][color=#006400]This is a [/color][/size]
[/size][/color][/size][/size][color=#006400][size=16]
[color=#b22222]Test[/color][/size][/color][/color][/size][/b]

The question now is: Is there an easy way (algorithm/library/etc) to clean-up the messy (as messy as that original HTML) bbcode that will be generated?

thanks again

Introduction

The best solution have seen so far is using HTML Tidy http://tidy.sourceforge.net/

Beyond converting the format of a document, Tidy is also able to convert deprecated HTML tags into their cascading style sheet (CSS) counterparts automatically through the use of the clean option. The generated output contains an inline style declaration.

It also ensures that the HTML document is xhtml compatible

Example

$code ='<p>
 <strong>
  <span style="font-size: 14px">
   <span style="color: #006400">
     <span style="font-size: 14px">
      <span style="font-size: 16px">
       <span style="color: #006400">
        <span style="font-size: 14px">
         <span style="font-size: 16px">
          <span style="color: #006400">This is a </span>
         </span>
        </span>
       </span>
      </span>
     </span>
    </span>
    <span style="color: #006400">
     <span style="font-size: 16px">
      <span style="color: #b22222">Test</span>
     </span>
    </span>
   </span>
  </span>
 </strong>
</p>';

If you RUN

$clean = cleaning($code);
print($clean['body']);

Output

<p>
    <strong>
        <span class="c3">
            <span class="c1">This is a</span> 
                <span class="c2">Test</span>
            </span>
        </strong>
</p>

You can get the CSS

$clean = cleaning($code);
print($clean['style']);

Output

<style type="text/css">
    span.c3 {
        font-size: 14px
    }

    span.c2 {
        color: #006400;
        font-size: 16px
    }

    span.c1 {
        color: #006400;
        font-size: 14px
    }
</style>

Our the FULL HTML

$clean = cleaning($code);
print($clean['full']);

Output

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title></title>
    <style type="text/css">
/*<![CDATA[*/
    span.c3 {font-size: 14px}
    span.c2 {color: #006400; font-size: 16px}
    span.c1 {color: #006400; font-size: 14px}
    /*]]>*/
    </style>
  </head>
  <body>
    <p>
      <strong><span class="c3"><span class="c1">This is a</span>
      <span class="c2">Test</span></span></strong>
    </p>
  </body>
</html>

Function Used

function cleaning($string, $tidyConfig = null) {
    $out = array ();
    $config = array (
            'indent' => true,
            'show-body-only' => false,
            'clean' => true,
            'output-xhtml' => true,
            'preserve-entities' => true 
    );
    if ($tidyConfig == null) {
        $tidyConfig = &$config;
    }
    $tidy = new tidy ();
    $out ['full'] = $tidy->repairString ( $string, $tidyConfig, 'UTF8' );
    unset ( $tidy );
    unset ( $tidyConfig );
    $out ['body'] = preg_replace ( "/.*<body[^>]*>|<\/body>.*/si", "", $out ['full'] );
    $out ['style'] = '<style type="text/css">' . preg_replace ( "/.*<style[^>]*>|<\/style>.*/si", "", $out ['full'] ) . '</style>';
    return ($out);
}

================================================

Edit 1 : Dirty Hack (Not Recommended)

================================================

Based on your last comment its like you want to retain the depreciate style .. HTML Tidy might not allow you to do that since its depreciated but you can do this

$out = cleaning ( $code );
$getStyle = new css2string ();
$getStyle->parseStr ( $out ['style'] );
$body = $out ['body'];
$search = array ();
$replace = array ();

foreach ( $getStyle->css as $key => $value ) {
    list ( $selector, $name ) = explode ( ".", $key );
    $search [] = "<$selector class=\"$name\">";
    $style = array ();
    foreach ( $value as $type => $att ) {
        $style [] = "$type:$att";
    }
    $replace [] = "<$selector style=\"" . implode ( ";", $style ) . ";\">";
}

Output

<p>
  <strong>
      <span style="font-size:14px;">
        <span style="color:#006400;font-size:14px;">This is a</span>
        <span style="color:#006400;font-size:16px;">Test</span>
        </span>
  </strong>
</p>

Class Used

//Credit : http://stackoverflow.com/a/8511837/1226894
class css2string {
var $css;

function parseStr($string) {
    preg_match_all ( '/(?ims)([a-z0-9, \s\.\:#_\-@]+)\{([^\}]*)\}/', $string, $arr );
    $this->css = array ();
    foreach ( $arr [0] as $i => $x ) {
        $selector = trim ( $arr [1] [$i] );
        $rules = explode ( ';', trim ( $arr [2] [$i] ) );
        $this->css [$selector] = array ();
        foreach ( $rules as $strRule ) {
            if (! empty ( $strRule )) {
                $rule = explode ( ":", $strRule );
                $this->css [$selector] [trim ( $rule [0] )] = trim ( $rule [1] );
            }
        }
    }
}

function arrayImplode($glue, $separator, $array) {
    if (! is_array ( $array ))
        return $array;
    $styleString = array ();
    foreach ( $array as $key => $val ) {
        if (is_array ( $val ))
            $val = implode ( ',', $val );
        $styleString [] = "{$key}{$glue}{$val}";

    }
    return implode ( $separator, $styleString );
}

function getSelector($selectorName) {
    return $this->arrayImplode ( ":", ";", $this->css [$selectorName] );
}

}

Different ways of accessing attribute values using javascript

15 votes
document.getElementById('myId').style;

is one way of accessing the style attribute.. Also we can do the same using document.getElementById('myId').getAttribute('style');

What is the difference between these two ways of getting attribute values..And which one is preferable?

In the first example you're not accessing to the style attribute, but to the style property. The property's value can be anything, in case of the style property is an object. In the second example you're accessing to the style attribute of the tag. The attribute's value can be only string.

In case of some attributes there is a mapping between them. So if you set an attribute style on a HTML node, your style property is updated and your style is applied. However, this is not always true: a well known bug in some versions of IE (at least till IE7) is that sort of mapping is broken, so set an attribute is not reflected to the property.

So, if you want set an attribute on a HTML node, you have to use the second one. But if you want to access to the property of your object that represent a HTML node, you have to use the first one.

In case of the style, the first one is strongly recommended.

To make it clear with an example (in modern browsers):

document.body.style.border = "1px solid red";
console.log(document.body.style); // [object CSSStyleDeclaration]
console.log(document.body.getAttribute("style")); // "border: 1px solid red;"

Div with slanted border using CSS3?

13 votes

I'm creating a javascript widget that resizes neighbouring divs, to reveal more of the div's background-image when the user hovers on it. This is simple enough, and working nicely with the divs having straight edges (obviously). However, the bordering edge 'needs' to be slanted.

Is there a simple way using css3 to make a slanted border between 2 DOM elements?

I have come across css3 transformations (namely, skew), and the diagonal border trick (using half colour, half transparency), but neither of these seem to be able to achieve what I need.

The effect I'm trying to achieve is like in this image: diaglonal border between dom elements

Any help appreciated.

You could technically embed your image in a rotated (see CSS3’s transform: rotate(<X>deg)) <div/>, and then rotate the embeded image with a reverse angle.

Alternatively, you could use SVG (with <clipPath>) to achieve this effect. Plus SVG embedded in <object/> tags can use JavaScript, so the responsive part can be part of the ride.

Both JSFiddle are on their way.

EDIT1: CSS Version: http://jsfiddle.net/kU3tu/
EDIT2: SVG Version: http://jsfiddle.net/b2JJK/

When a child element overflows horizontally, why is the right padding of the parent ignored?

12 votes

Given this simple structure:

<div id="parent">
    <div id="child">Lorem ipsum</div>
</div>

with this CSS:

#parent {
    width: 200px;
    height: 200px;
    padding: 20px;
    overflow-x: scroll;
}

#child {
    width: 500px;      
}

Live demo: http://jsfiddle.net/523me/5/

Notice that the parent has a 20px padding and that the child overflows horizontally (because it is wider). If you scroll the parent all the way to the right, you'll see that the child touches the right edge of the parent.

So, the parent should have a right padding, but it is ignored. It seems that when the child has a fixed width, the right padding of the parent does not apply. (Is this specified by a standard? I would love to know. Please let me know if you find anything!)

Is there a way to force the right padding to be applied in this scenario without having to remove any of the elements from the flow (by floating or positioning)?

enter image description here

Screenshot 1 - The right padding is ignored. This is how all current browsers behave.

Screenshot 2 - The right padding applies. This is what I'm trying to accomplish. (Btw, the screenshot is from IE7, which is the only browser which does not ignore the right padding.)

You're suffering from this problem.

I would solve it giving the margin to the child (and not the padding to the parent):

#parent {
    width: 200px;
    height: 200px;
    overflow-x: scroll;
    background: gray;
}

#child {
    width: 500px;
    background: yellow;  
    display: inline-block;
    margin: 20px; 
}

Demo: jsFiddle

How can I detect if a browser supports the blink tag?

12 votes

The HTML <blink> tag, in browsers that support it (i.e. Mozilla Firefox and Opera), makes its content blink on and off, resembling the effect of a slow strobe light.

I am writing a suite of polyfills for non-standard HTML, including the blink tag. The implementation of blinking behavior is pretty simple

(function blink(n) {
    var blinks = document.getElementsByTagName("blink"),
        visibility = n % 2 === 0 ? "visible" : "hidden";
    for (var i = 0; i < blinks.length; i++) {
        blinks[i].style.visibility = visibility;
    }
    setTimeout(function() {
        blink(n + 1);
    }, 500);
})(0);

(You can see this in action)

But this does not detect if the browser already supports the blink tag, and in browsers that already support it, there will be a double-blinking effect. I need some feature detection that determines if the browser supports blink, and if it doesn't then it falls back on my Javascript polyfill.

I do not want to do browser detection, because that solution is not scalable, and since people can disable blink behavior in their Firefox preferences, that solution is not effective.

Is there a way to detect support for the blink element?

I just did a little research on the matter and I think I may found an answer...

I'm sure you're aware of CSS property support detection? Well, there is a text-decoration: blink CSS property. So if the browser supports <blink> it must support the CSS property too!

This is normal CSS property detection i.e. to detect textDecoration is supported do this:

if (document.createElement("detect").style.textDecoration === "") {  
    // textDecoration supported
}  

Perhaps you could try something like this:

if (document.createElement("detect").style.textDecoration === "blink") {  
    // textDecoration: blink supported ?
}  

or along those lines...

Update

I have 4 browsers & so tested this with 4 browsers. Out of those 4 only FireFox supports the blink tag. <blink> is registered in the HTML document as a "Span" element in FF, but in the other 3 browsers it is registered as an unknown element.

<html>

<head>
<script type="text/javascript">
function investigate() {
    var blinker = document.getElementsByTagName("blink")[0];
    document.getElementById("monitor").innerHTML += blinker;
}
</script>
</head>

<body onload="investigate()">
<blink>Hello, blink!</blink>
<div id="monitor"> </div>
</body>

</html>

Output

Internet Explorer [7,8,9] not supported

Hello, blink!
[object]

Chrome [18] not supported

Hello, blink!
[object HTMLUnknownElement]

Safari [5] not supported

Hello, blink!
[object HTMLElement]

FireFox [3.6] supported

Hello, blink!
[object HTMLSpanElement]

A practical way of formatting explicit content

11 votes

As a blogger, I want to mark any content in my CMS based on how explicit it is (violent, erotic, spoiler, obscene and so on..). Is there a proper practical library and standard for this?

I have read about RTA, ICRA, PICS and W3C POWDER, but they mark entire page with meta or header. POWDER seems too complex - as far as I understood, it adds metadata outside of the page? Can you provide a simple useful example, if I use with HTML5 doctype.

What I want is a way to mark HTML elements based on their rating. I would also like it to be compliant with any parental filtering. It would also be nice to add EXIF data into images to have them filtered independent of the context.

Since there is no microformat, i've decided to make one. Named it xrate 1.0, wrote an article about it and added draft to microformats.org

Basically its about rating content from 0-100 based on danger with theses HTML attributes:

  • data-xrate-lang - Obscene language
  • data-xrate-sex - Romantic, erotic, pornographic
  • data-xrate-nude - Level of nudity
  • data-xrate-disgust - Might cause disgust (shit, larvae, decomposition)
  • data-xrate-violence - Violence and its results - weapons, wounds, dead bodies, blood
  • data-xrate-asocial - Smoking, alcohol, drugs, gambling, prostitution
  • data-xrate-blink - Blinking animation that might cause eplilepsy
  • data-xrate-spoiler - Story is retold
  • data-xrate-camera - If application (flash/applet?) gains access to videocamera
  • data-xrate-malware - If resource can cause infection (viruses, trojans etc.) on viewer's machine

Please notify if there is a better solution.

float next sibling left of previous sibling

11 votes

I don't know how to or if this can be done with internet explorer 6.

I am trying to float the next sibling to the left of the previous sibling

This is what im doing and it displays correctly with chrome 6 , opera 9 and firefox 1+.

What the issue with IE6 is that the previous (2) is floated to the far right (where it would be best to be beside to next (1) that is on the left side of the page.

 .wrap{float:left;}
 .prev {float:right;}
 .next {float:left;}


 <div class="wrap">
 <div class="prev">previous (2)</div><div class="next">next (1)</div>
 </div>

If it can be done and you know how to do it i will give a bounty of 250 points

Here you go: http://result.dabblet.com/gist/2489753

You can't use floats there, 'cause IE have a nasty bug, where it stretches the container that is floated to left (or is inline-block) if it contains the float: right;.

However, there is a rarely-used property direction, that can be used for such layouts: it's fully cross-browser and you can use it with inline-blocks for the best effect.

So, for your case the code would be this:

.wrap{
    display: inline-block;
    direction: rtl;
    }
.prev,
.next {
    display: inline-block;
    direction: ltr;
    }

But the display: inline-block don't work for IE from the box, so you need to hack it by making it inline but with hasLayout, so add those to IE only in conditional comments:

.wrap,
.prev,
.next {
    display: inline;
    zoom: 1;
    }

That's it!

Step by step:

  1. Make everything inline-blocks, so it would work in inline flow.
  2. Reverse the flow on the wrapper.
  3. Return the flow to the normal ltr mode in the children.
  4. It's done :)

Generate repeating hexagonal pattern with CSS3

9 votes

So, I need to make a repeating hexagonal pattern, using CSS. If images are needed, I can go there, but I'd prefer to just use CSS if possible.

Here's an idea of what I'm trying to create:

enter image description here

Basically, I just need a way to create the hexagonal shapes, and then overlay text/images on top of them. I don't have much code yet, because I'm not really sure where to start. The problem is, I could just use <div>s in the shape of a hexagon like shown in (http://css-tricks.com/examples/ShapesOfCSS/), but then they wouldn't be connecting. I could use a repeating hexagon pattern, but then I wouldn't be able to specify the exact location of the text or images I need in specific shapes. Thanks for any help in advance.

This was a truly amazing question. Thank you for asking it. The great thing is the fact that:

This Fiddle Proves You Can Do It!

The idea came to me almost instantly after reading your question, but took some time to implement. I originally tried getting a single "hex" with a single div and just pseudo elements, but as best I could tell, there was no way to just rotate the background-image (which I needed), so I had to add some extra div elements to get the right/left sides of the hex, so that I could then use the pseudo elements as a means of background-image rotation.

I tested in IE9, FF, and Chrome. Theoretically any browser supporting CSS3 transform it should work in.

Update (added explanation)

I have some time now to post some code explanation, so here goes:

First, hexagons are defined by 30/60 degree relationships and trigonometry, so those will be the key angles involved. Second, we start with a "row" for the hex grid to reside in. We are going to use inline-block for the hexagon display, but we don't want them to accidentally wrap to the next line and ruin the grid, so white-space: nowrap solves that issue. The margin on this row is going to depend on how much space you want between hex's, and some experimentation may be needed to get what you want.

.hexrow {
    white-space: nowrap;
    /*right/left margin set at (( width of child div x sin(30) ) / 2) 
    makes a fairly tight fit; 
    a 3px bottom seems to match*/
    margin: 0 25px 3px;
}

The immediate children of the .hexrow is going to just be div elements that become the basis for the hex shape. The width will drive the horizontal of the top of the hex, the height is derived from that number since all the sides are equal length on a regular hexagon. Again, margin is going to depend on spacing, but this is where the "overlap" of the individual hexagons is going to occur to make the grid look occur. The background-image is defined once, right here. The shift left on it is to accommodate at least the added width for the left side of the hex. Assuming you want centered text, the text-align handles the horizontal (of course) but the line-height that matches the height is going to allow for a vertical centering.

.hexrow > div {
    width: 100px;
    height: 173.2px; /* ( width x cos(30) ) x 2 */
    /* For margin:
    right/left = ( width x sin(30) ) makes no overlap
    right/left = (( width x sin(30) ) / 2) leaves a narrow separation
    */
    margin: 0 25px;
    position: relative;
    background-image: url(http://i.imgur.com/w5tV4.jpg);
    background-position: -50px 0; /* -left position -1 x width x sin(30) */
    background-repeat: no-repeat;
    color: #ffffff;
    text-align: center;
    line-height: 173.2px; /*equals height*/
    display: inline-block;
}

Each odd number hex we are going to shift down in relation to the "row" and each even shift up. The shift calculation ( width x cos(30) / 2 ) is also the same as (height / 4).

.hexrow > div:nth-child(odd) {
    top: 43.3px; /* ( width x cos(30) / 2 ) */
}

.hexrow > div:nth-child(even) {
    top: -44.8px; /* -1 x( ( width x cos(30) / 2) + (hexrow bottom margin / 2)) */
}

We are using 2 child div elements to create the "wings" of the hex. They are sized the same as the main hex rectangle, and then rotated, and pushed "below" the main hex. Background-image is inherited so that the image is the same (of course), because the image in the "wings" is going to be "lined up" to that in the main rectangle. The pseudo elements are used to generate the images, because they need to be "rerotated" back to horizontal (since we rotated the parent div of them to create the "wings").

The :before of the first will translate its background the width of the negative amount equal to the main portion of the hex plus the original background shift of the main hex. The :before of the second will change the origin point of the translation and will shift the main width on the x-axis, and half the height on the y-axis.

.hexrow > div > div:first-of-type {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: -1;
    overflow: hidden;
    background-image: inherit;

    -ms-transform:rotate(60deg); /* IE 9 */
    -moz-transform:rotate(60deg); /* Firefox */
    -webkit-transform:rotate(60deg); /* Safari and Chrome */
    -o-transform:rotate(60deg); /* Opera */
    transform:rotate(60deg);
}

.hexrow > div > div:first-of-type:before {
    content: '';
    position: absolute;
    width: 200px; /* width of main + margin sizing */
    height: 100%;
    background-image: inherit;
    background-position: top left;
    background-repeat: no-repeat;
    bottom: 0;
    left: 0;
    z-index: 1;

    -ms-transform:rotate(-60deg) translate(-150px, 0); /* IE 9 */
    -moz-transform:rotate(-60deg) translate(-150px, 0); /* Firefox */
    -webkit-transform:rotate(-60deg) translate(-150px, 0); /* Safari and Chrome */
    -o-transform:rotate(-60deg) translate(-150px, 0); /* Opera */
    transform:rotate(-60deg) translate(-150px, 0);

    -ms-transform-origin: 0 0; /* IE 9 */
    -webkit-transform-origin: 0 0; /* Safari and Chrome */
    -moz-transform-origin: 0 0; /* Firefox */
    -o-transform-origin: 0 0; /* Opera */
    transform-origin: 0 0;
}

.hexrow > div > div:last-of-type {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: -2;
    overflow: hidden;
    background-image: inherit;

    -ms-transform:rotate(-60deg); /* IE 9 */
    -moz-transform:rotate(-60deg); /* Firefox */
    -webkit-transform:rotate(-60deg); /* Safari and Chrome */
    -o-transform:rotate(-60deg); /* Opera */
    transform:rotate(-60deg);
}

.hexrow > div > div:last-of-type:before {
    content: '';
    position: absolute;
    width: 200px; /* starting width + margin sizing */
    height: 100%;
    background-image: inherit;
    background-position: top left;
    background-repeat: no-repeat;
    bottom: 0;
    left: 0;
    z-index: 1;

    /*translate properties are initial width (100px) and half height (173.2 / 2 = 86.6) */
    -ms-transform:rotate(60deg) translate(100px, 86.6px); /* IE 9 */
    -moz-transform:rotate(60deg) translate(100px, 86.6px); /* Firefox */
    -webkit-transform:rotate(60deg) translate(100px, 86.6px); /* Safari and Chrome */
    -o-transform:rotate(60deg) translate(100px, 86.6px); /* Opera */
    transform:rotate(60deg) translate(100px, 86.6px);

    -ms-transform-origin: 100% 0; /* IE 9 */
    -webkit-transform-origin: 100% 0; /* Safari and Chrome */
    -moz-transform-origin: 100% 0; /* Firefox */
    -o-transform-origin: 100% 0; /* Opera */
    transform-origin: 100% 0;
}

This span houses your text. The line-height is reset to make the lines of text normal, but the vertical-align: middle works since the line-height was larger on the parent. The white-space is reset so it allows wrapping again. The left/right margin can be set to negative to allow the text to go into the "wings" of the hex.

.hexrow > div > span {
    display: inline-block;
    margin: 0 -30px;
    line-height: 1.1;
    vertical-align: middle;
    white-space: normal;
}

You can individual target rows and cells in those rows to change images, or span text settings, or opacity, or accommodate a larger image (to shift it to the place you want), etc. That is what the following do for the second row.

.hexrow:nth-child(2) > div:nth-child(1) {
    background-image: url(http://i.imgur.com/7Un8Y.jpg);
}

.hexrow:nth-child(2) > div:nth-child(1) > span {
    /*change some other settings*/
    margin: 0 -20px;
    color: black;
    font-size: .8em;
    font-weight: bold;
}

.hexrow:nth-child(2) > div:nth-child(2) {
    background-image: url(http://i.imgur.com/jeSPg.jpg);
}

.hexrow:nth-child(2) > div:nth-child(3) {
    background-image: url(http://i.imgur.com/Jwmxm.jpg);
    /*you can shift a large background image, but it can get complicated
    best to keep the image as the total width (200px) and height (174px)
    that the hex would be.
    */
    background-position: -150px -120px;
    opacity: .3;
    color: black;
}

.hexrow:nth-child(2) > div:nth-child(3) > div:before {
    /*you can shift a large background image, but it can get complicated
    best to keep the image as the total width (200px) and height (174px)
    that the hex would be.
    */
    background-position: -100px -120px; /* the left shift is always less in the pseudo elements by the amount of the base shift */
}

.hexrow:nth-child(2) > div:nth-child(4) {
    background-image: url(http://i.imgur.com/90EkV.jpg);
    background-position: -350px -120px;
}

.hexrow:nth-child(2) > div:nth-child(4) > div:before {
    background-position: -300px -120px;
}

Textarea loses focus on mouse click?

9 votes

I'm having some strange issues with a textarea in Google Chrome.

The problem is, whenever I click on a textarea in Google Chrome, it will lose focus instantly, and go back to the previous input box. The problem doesn't happen if I press the tab key on my keyboard.

Here's a .gif showing my problem:

enter image description here

The code i'm using is valid html:

                <div class="inputborder rounded">
                    <label>Celebrity 1<label>
                    <div class="newline"></div>
                    <input type="text"/>
                    <div class="newline"></div>
                    <label>Tweet 1<label>
                    <div class="newline"></div>
                    <textarea>Y U NO WORK?!</textarea>
                    <div class="newline"></div>
                </div>

I'm not using any javascript on the page yet, apart from the jQuery library.

I'm pretty stunned as to why this is happening, as it's usually Internet Explorer that gives me problems like this.

Anyone have any idea what's wrong?

Try closing your label tags.

<div class="inputborder rounded">
        <label>Celebrity 1</label>
        <div class="newline"></div>
        <input type="text"/>
        <div class="newline"></div>
        <label>Tweet 1</label>
        <div class="newline"></div>
        <textarea>Y U NO WORK?!</textarea>
        <div class="newline"></div>
</div>

How to switch left and right in a css file?

9 votes

I have an HTML django template page that is both RTL and LTR (depends on user's locale).

The CSS of this page is stored in another file, and that file is currently static.

What is the best way to switch the attribute left and right according to the locale? Is there a built in attribute in CSS for this problem? (I don't want to use JS, it feels too messy)

I have:

.elem{
    left: 10px; 
    bottom: 10px;
    position: absolute;
}

I want something like this:

.elem{
    right-or-left-according-to-html-dir: 10px; 
    bottom: 10px;
    position: absolute;
}

Currently the only option I can think of is turning the file into a template also:

.elem{
    {{dir}}: 10px; 
    bottom: 10px;
    position: absolute;
}

Is there a better way that will let me keep my CSS file static?

You say you're making the document rtl or ltr depending on locale. In that case you can use the :lang() selector to make certain parts of your document have styling depending on the locale.

If you want a little more support (IE7+) you could use the attribute selector selector[lang='en'] though that will only test the attribute on the specified selector.

If you specify the language in the html element (which you should, with lang="en" for example) you can just put the html selector in front of the class you want to apply in certain locales:

.elem {
    margin: 0 10px 0 0;
    color: blue;
}

html[lang='en'] .elem {
    margin: 0 0 0 10px;
}

Even better, if you specified the dir attribute you can directly use that in css like so:

.elem[dir='rtl'] {
    margin: 0 10px 0 0;
}

Please note that with a class on the body element you will always depend on that class always being there. But the dir and lang attribute can be specified on a more specific scope, like a single div, and still be used in the css along with styles for the 'other' reading directions.

How does this site(allaboutrajni) work only when you go offline(disconnect from internet)

8 votes

The following site only works if you are offline. http://www.desimartini.com/allaboutrajni.htm

So how do they do this. I have even seen YouTube do something similar. just open YouTube and disconnect net and refresh. You will see the page below.

enter image description here

HTML5 allows webpages to work offline by;

  1. Providing storage in terms of localStorage and sessionStorage.
  2. Providing events to let the page know when it's online/ offline
  3. The navigation.onLine property is a boolean which lets you know whether you're online or not.
  4. Giving application caches.

So basically, both pages store the assets it needs to work offline in either of those storage mediums, and checks whether it's online or offline when the page loads.

For more info, you could see http://www.html5rocks.com/en/features/offline

EDIT: Meh, infact the site you linked to works by downloading the flash content, and then pinging http://images.desimartini.com/allaboutrajni/config.xml every second to detect whether it's still connected to the internet. This website won't load if you disconnect and then refresh the page.

However, a page which uses true offline functionality is one such as http://htmlfive.appspot.com/static/stickies.html

How i can display the output of a rss feed in HTML format in a TWebBrowser?

8 votes

I Want to show the output of a rss feed in a formatted HTML in a TWebBrowser component, if a load this feed http://code.google.com/feeds/p/v8/svnchanges/basic in a TWebbrowser, this shows the content as a XML file

enter image description here

but if I use IE to load the same page

enter image description here

I tried injecting a css to the loaded IHTMLDocument2 as is suggested in this question CSS and TWebbrowser delphi but i still getting the same result.

The question is, how i can load the rss feed in TWebbrowser but showing the output as HTML document like IE does?

Just a guess, but you might try applying the following XSL stylesheet (taken from http://snippets.dzone.com/posts/show/1162 and modified as suggested by cherdt in the comments below):

<xsl:stylesheet version="1.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:dc="http://purl.org/dc/elements/1.1/">
    <xsl:output method="html"/>
    <xsl:template match="/">
    <xsl:apply-templates select="/atom:feed/atom:head"/>
        <xsl:apply-templates select="/atom:feed"/>
    </xsl:template>
    <xsl:template match="atom:feed/atom:head">
        <h3><xsl:value-of select="atom:title"/></h3>
        <xsl:if test="atom:tagline"><p><xsl:value-of select="atom:tagline"/></p></xsl:if>
        <xsl:if test="atom:subtitle"><p><xsl:value-of select="atom:subtitle"/></p></xsl:if>
    </xsl:template>
    <xsl:template match="/atom:feed">
        <h3><xsl:value-of select="atom:title"/></h3>
        <xsl:if test="atom:tagline"><p><xsl:value-of select="atom:tagline"/></p></xsl:if>
        <xsl:if test="atom:subtitle"><p><xsl:value-of select="atom:subtitle"/></p></xsl:if>
        <ul>
            <xsl:apply-templates select="atom:entry"/>
        </ul>
    </xsl:template>
    <xsl:template match="atom:entry">
        <li>
            <a href="{atom:link[@rel='related']/@href}" title="{substring(atom:published, 0, 11)}"><xsl:value-of select="atom:title"/></a>
            <xsl:choose>
                <xsl:when test="atom:content != ''">
                    <p><xsl:value-of select="atom:content" disable-output-escaping="yes" /></p>
                </xsl:when>
                <xsl:otherwise>
                    <p><xsl:value-of select="atom:summary" disable-output-escaping="yes" /></p>
                </xsl:otherwise>
            </xsl:choose>
        </li>
    </xsl:template>
</xsl:stylesheet>

To the feed you are receiving. To transform the document, refer to this question's selected answer and then you could try to assign the resulting XML to the WebBrowser.

I am guessing that you are pointing your WebBrowser control to the feed, but using this approach you would need to download the feed using, for example, Indy (check out TIdHTTP and its Get() method), transform it, and then display in your control.

Please note that the above is just a guess, but I believe it is a good assumption. :)

Reloading page when user arrives from back button

7 votes

I have a generic error page, that any handled error will redirect to. I have an admin page that when the user invokes an error, and the user is brought to the error page, hitting the back button from the error page cause the admin page to load improperly.

So what I need, is a way to reload the admin page when I come from the error page. I have tried setting no cache and such on the admin page, and checking for a postback, but nothing works. Setting no cache seems to do nothing, and any javascript on the admin page's document.ready function does not get called either. Is there any other ways to get this to happen?

EDIT:

I should also mention that I have noticed that a table is missing 2 cells I recently added. This makes me believe that there is a old state of the page being cached somewhere, although clearing the browser cache and restarting my server do not help at all.

Edit2:

Also, setting window.onload() gets nuked when I come back to the admin page

So it turns out this is just an IE9 issue. My onload method was just never getting called. Works fine in the other browsers.

The fix I had to make in order get this to work in IE9 as well was to append a query string to the page, so that when I come back to the page, IE9 will go back to the browser incise the query string has changed or needs to be re-evaluated.

Thanks to both of you guys, or help helped me find the issue.

Javascript: Keydown Event: "Up" arrow key preventing further arrow-key Keydown events? (answered: keyboard ghosting)

7 votes

I've found a lot of related questions (here and elsewhere), but haven't found this one specifically.

I'm trying to listen for keydown events for the arrow keys (37-40), however when using the arrow keys in a certain order, subsequent arrow do not generate "keydown" events.

Example: http://blog.pothoven.net/2008/05/keydown-vs-keypress-in-javascript.html

  1. At that page, click in the "type here ->" box.
  2. Press and hold right arrow key: table updates to keycode 39
  3. While continuing to hold right arrow key, press and hold up arrow key: table updates to 38
  4. While continuing to hold right and up arrow keys, press and hold left arrow key: table does not update

However, if I do the same thing but using down arrow key instead of up arrow key then it works as expected.

Additionally, if I use the keypad instead of the arrow keys it works as expected.

I am preventing the normal operation of the keydown event (both by returning false in the event listener, and by calling preventDefault() ), but the behavior persists.

I thought it might be my keyboard, but it happens on a laptop as well as a friend's machine.

Does anyone have any insight as to what is going? Or some good ideas on workarounds?

[edit] Here's an example of what I mean. I realize this may not work on all browsers, but I just threw this together on my laptop to demonstrate what is happening for me (on chrome on w7 and also chrome & safari on mac os 10.6.8)

<html>
<body>
<script>

var keysDown = {};
addEventListener("keydown", function(e) {
    keysDown[e.keyCode] = true;
    document.getElementById('latestKeydown').value=e.keyCode;
}, false);

addEventListener("keyup",function(e){
    delete keysDown[e.keyCode];
}, false);

var loop = function(){
    document.getElementById('upinput').value=keysDown[38];
    document.getElementById('downinput').value=keysDown[40];
    document.getElementById('leftinput').value=keysDown[37];
    document.getElementById('rightinput').value=keysDown[39];
}

setInterval(loop,1);

</script>
Up: <input id="upinput" type=text size=10><br />
Down: <input id="downinput" type=text size=10><br />
Left: <input id="leftinput" type=text size=10><br />
Right: <input id="rightinput" type=text size=10><br />
Recent Keydown: <input id="latestKeydown" type=text size=10><br />

</body>
</html>

Again, the issue is: If I hold down A, then S, then D, then F, then G, you can see the "Recent Keydown" updating every single time I begin to hold a new key.

However, if I hold down right arrow, then up arrow, then left arrow, I do not see "Recent Keydown" updating for the left arrow key.

I can't speak on authority on this, but according to http://stackoverflow.com/a/4177260/562209 , unless you are working with simultaneous press of a modifier key(s) and a non-modifier key, regarding a multiple key press "the PC might not understand it due to the way keyboards are wired".

How do i fix :hover on iPhone if there is no <a> element?

6 votes

How do i fix :hover on iPhone if there is no <a> element?

I'm using a <li> element and the iPhone doesn't open my sub-menu when i tab it.

Example html:

<ul>
  <li>Menu item (no <a> element)
    <ul>
      <li><a href="#">Menu item</a><li>
    </ul>
  <li>
</ul>

I answered a JavaScript way to fix this, but i want to know if there are different ways to fix this (maybe a better one)

You can fix this by using JavaScript. The following script will add hover as class to the <li> element:

<script type="text/javascript">
$("li").hover(
  function () {
    $(this).addClass("hover");
  },
  function () {
    $(this).removeClass("hover");
  }
);  
</script>

Just add li.hover where you got li:hover in your CSS like this:

This:

ul li:hover ul{
    display:block;
}

Will be:

ul li:hover ul,
ul li.hover ul,{
    display:block;
}

jQuery Documentation:
http://api.jquery.com/hover/
http://api.jquery.com/addClass/

getting fixed height div to continue on next line

6 votes

Not at all sure that this is possible but on the off-chance, here is what I need:

  • 100px high div with top and bottom border.

  • an unknown number of items within the div that are displayed horizontally within the top and bottom borders of the parent div.

  • Importantly, if more items are contained within the div that can fit horizontally, the div should continue with a new row of items below. This second row should also have the items displayed horizontally between the top and bottom borders of the parent div. I do not want the div to simply grow in height and start a new line because this will not allow the top and bottom borders to appear above and below each row of items.

enter image description here

You can set the width of wrapper and put those blocks which are 100px high inside it.

Here is the example: http://jsfiddle.net/BVm5h/

Code:

<div class="wrapper">
 <div class="myClass">1</div>
 <div class="myClass">2</div>
 <div class="myClass">3</div>
 <div class="myClass">4</div>
 <div class="myClass">5</div>
 <div class="myClass">6</div>
 <div class="myClass">7</div>
 <div class="myClass">8</div>
 <div class="myClass">9</div>
 <div class="myClass">10</div>
</div>

CSS:

.wrapper {width: 600px;}

.myClass {
 border-top: 1px solid #FF0000;
 border-bottom: 1px solid #FF0000;
 width: 100px;
 height: 100px;
 float:left;
 margin-top: 5px;
}

div.myClass:last-child {
 width: 100%;
}​

JS:

var no = $('div.myClass').length;
var wlength = $('div.wrapper').width();
var length = $('div.myClass').width();
var tno = no*length;
while(wlength < tno)
 tno=tno-wlength;
var mw = wlength+length-tno;
$('div.myClass').last().css('max-width',mw);

​ ​ By changing the width of wrapper, you can set the number of div blocks you wish in each row.

Edit: Added JS if the last element is to be extended for entire row. ​

how to make unchecked check box return a value with jQuery serialize?

6 votes

I have an HTML form with some checkboxes. I use jQuery .serialize() function to make a query string to submit to the database. The problem I am having is that when a checkbox is unchecked, the .serialize() function does not register it in the query string.

My problem is illustrated in this jsfiddle: http://jsfiddle.net/cTKhH/.

This is a problem because i still need to save a value of the unchecked check box to the database. Right now the information is only saved when the check box is checked. When it is unchecked, and the information from .serialize() is submitted, no change is made since there is no information submitted.

Does anyone know how to make my .serialize() function return the unchecked value for all check boxes when they are unchecked?

Thanks!!

** EDIT **

Just a little more info, I know now why the unchecked check box is not submitted, because it is not a "successful" form control, see here: http://www.w3.org/TR/html401/interact/forms.html#successful-controls.

Hopefully I still modify the .serialize() function to submit unchecked values.

http://jsfiddle.net/cTKhH/16/

Editing and Saving user HTML with Javascript - how safe is it?

5 votes

For example I have a Javascript-powered form creation tool. You use links to add html blocks of elements (like input fields) and TinyMCE to edit the text. These are saved via an autosave function that does an AJAX call in the background on specific events.

The save function being called does the database protection, but I'm wondering if a user can manipulate the DOM to add anything he wants(like custom HTML, or an unwanted script).

How safe is this, if at all?

First thing that comes to mind is that I should probably search for, and remove any inline javascript from the received html code.

Using PHP, JQuery, Ajax.

Not safe at all. You can never trust the client. It's easy even for a novice to modify DOM on the client side (just install Firebug for Firefox, for example).

While it's fine to accept HTML from the client, make sure you validate and sanitize it properly with PHP on the server side.

jquery .get data manipulation

4 votes

I am using below code to get a page:

$.get('http://example.com/page1.html', function (data) {

});

Now lets imagine there is a #content div inside that page1.html and I need to read it's inner html as I already have #content div on page where Ajax call is occurring.

What is the right way to do this? I've tried with:

data = $(data).find('#content').html();
$("#content").empty().append(data);

But it seems that html() function is not the right one as it returns null, while contents() is returning data but I am not skillful enough to get only what I need from it.

Any help appreciated, thanks!!

Untested:

var content = $("#content", data).html(); // or var content = $("#content", $(data)).html();

$("#content").html(content);

EDIT: How about this?

$('#content').load("http://example.com/page1.html #content");

From: http://api.jquery.com/load/ - "loading page fragments".