Hướng dẫn dùng 子meaning JavaScript

The problem with the above solution is that it can be removed using a simple:

if( top != self )
    delete top.onbeforeunload;

Once that has been called, then the prevent_bust will never be incremented, and that means that the website will be freely re-directed without your consent or knowledge. Bad deal.

If you wanted a consistently functional version of that solution, I would recommend doing this instead:

// Create a random seed value, making it almost impossible to 
// determine what is being tested for.
var prevent_bust = Math.random() * 3000; 

// enclose everything in a function, so that it cannot be addressed
function iniFunc ( init ) { 
    // The function is no longer in scope of the main window.
    function onbeforeunload() { prevent_bust++ }
    window.onbeforeunload = onbeforeunload;
    setInterval( function() {
        // make sure the function was not deleted.
        if( window.onbeforeunload != onbeforeunload )
        {
            prevent_bust = init + 1;
            window.onbeforeunload = onbeforeunload;
        }
        if (prevent_bust > init ) {  // All comparison is to the random seed.
            prevent_bust -= 2
            window.top.location = 'http://server-which-responds-with-204.com/' 
            // Unfortunately, you have absolutely no idea which website caused
            // the incrementation, so you cannot replace it with a link!
            //
            // You might try to simply ignore it and just use the iframe as is -- 
            // theoretically, they are no longer able to bust this frame. 
            // (this theory will be disproved below).
       }
   }, 1 );
};
iniFunc( prevent_bust );

Unfortunately, this does cause leave one problem -- it is a trivial thing to retrieve the interval which has been set, unset it, and then re-direct the page:

// setTimeout will return the highest timeout which is not "in use", in this case,
// it will be the original setInterval (from the above function) + 1.
// Event if there are 1,000 intervals already set, it will be rather trivial to 
// clear them all.
var currentInterval = 10000;
// window.setTimeout( gotoHREF, 100 );

// clearInterval will not interfere with setTimeout, so we can clear all
// of the Intervals already set.
for( var i = 0; i < currentInterval; i++ ) top.clearInterval( i );

function gotoHREF(){
    top.location.href = "http://";
}

Your best bet is actually to solve this issue server side (if you can). If you have access to the server for the website which will hold iframes, create an interim, proxy location where you pull in the website's data and then strip the script tags:

// In php
$dd = new DOMDocument();
// file_get_contents will simply convert the entire web address into a String
$dd->loadXML( file_get_contents( "http://" . $_GET[ 'loadedURL' ] ) );
$scripts = $dd->getElementsByTagName( "script" );

// iterate through the website and remove all script tags.
for( $i = 0; $i < $scripts->length; $i++ )
{
    $current = $scripts->item( $i );
    $current->parentNode->removeChild( $current );
}

// output it to the dummy page.
echo $dd->saveXML();

You would then use the tag:


Unfortunately, this will mean that your iframe will be running without JavaScript which might cripple, if not completely lobotomize the website in question. You'll also need to make sure that all of the src attributes are correctly modified for descendant nodes in the foreign site's HTML.

On the other hand, you could have your server check the framed site and all of its JS pages to see if the RegExp top(.|[\s*("|'))location (this will match top.location, top["location, and top[ 'location) exists (or if there are any references to top at all), and then use a link if it does exist and the site proper if it does not. The detriment here is that then you are forcing the user to wait for the secondary site to load twice -- once on the server and once in their browser. (unless everything is done through JS, but that is generally more annoying, in my opinion).

Personally, I'm of the opinion that the "don't frame my site" crowd can generally win most battles which involves the iframe directly. On the other hand, if code is used to process the HTML before it is appended to a web page, then the other side stands more than a fighting chance.

As a side note, all of these can be accomplished through JavaScript and AJAX, but that will generally be a bit slower. Use the server, if you can.

Someone on JSPerf dropped an amazingly fast implementation for checking leap years of the ISO calendar (link: Odd bit manipulations):

function isLeapYear(year) {
  return !(year & 3 || year & 15 && !(year % 25));
}

Using Node.js, I quickly checked it against two other one-liner implementations I know.

function isLeapClassic(y) { return (y % 4 == 0) && !(y % 100 == 0) || (y % 400 == 0); }
function isLeapXOR(y) { return (y % 4 == 0) ^ (y % 100 == 0) ^ (y % 400 == 0); }
function isLeapBitwise(y) { return !(y & 3 || y & 15 && !(y % 25)); }

//quick'n'dirty test on a small range!
//works with negative integers too
for (var i = 1900; i <= 2100; i++) {
    console.log(
        "year = %d,\t%d%d%d",
        i,
        isLeapClassic(i),
        isLeapXOR(i),
        isLeapBitwise(i)
    );
}

It works as expected, but my problem is I can't figure how. I know ((a % b) == (a & (b-1)) when b is power of two so (year % 4) == (year & 3), but year & 15 && !(year % 25) is quite hard to figure out. Can someone explain me how it works? Any reference about this implementation?

Hướng dẫn dùng 子meaning JavaScript

River

8,18013 gold badges53 silver badges65 bronze badges

asked Mar 24, 2012 at 15:18

Hướng dẫn dùng 子meaning JavaScript

7

year & 3 is the same as year % 4. Not so tricky there, it just represents the usual 4-year cycle.

year & 15 is the same as year % 16.

So, it's not a leap year if the year doesn't divide evenly by 4, or if it doesn't divide evenly by 16 but does divide evenly by 25. This means that every multiple of 25 is not a leap year unless it's also a multiple of 16. Since 16 and 25 don't have any common factors, the only time both conditions are met is when the year is a multiple of 16*25, or 400 years. The multiples of 4*25 will be considered not leap years, accounting for the 100 year cycle.

1900 wasn't a leap year because it was divisible by 100, 2000 was a leap year because it was divisible by 400, and 2100 won't be a leap year.

answered Mar 24, 2012 at 15:40

Mark RansomMark Ransom

289k40 gold badges382 silver badges606 bronze badges

1

If a number is divisible by 16 and divisible by 25, it's divisible by four times 25 (100) as well as 16 times 25 (400).

answered Mar 24, 2012 at 15:21

PointyPointy

393k59 gold badges573 silver badges608 bronze badges

1

Not the answer you're looking for? Browse other questions tagged javascript node.js leap-year or ask your own question.