91

Resize iframe by its content – cross-domain

We all had this problem once: Including an iframe into a website and then – there were scroll bars which mess up everything. But have you ever heard of the JavaScript method Window.postMessage? We can use this method to communicate between the iframe and its parent and it is also widely supported.

At first, we need to register the message event to the listener on the parent:

<script type="text/javascript">
    // browser compatibility: get method for event 
    // addEventListener(FF, Webkit, Opera, IE9+) and attachEvent(IE5-8)
    var myEventMethod = 
        window.addEventListener ? "addEventListener" : "attachEvent";
    // create event listener
    var myEventListener = window[myEventMethod];
    // browser compatibility: attach event uses onmessage
    var myEventMessage = 
        myEventMethod == "attachEvent" ? "onmessage" : "message";
    // register callback function on incoming message
    myEventListener(myEventMessage, function (e) {
        // we will get a string (better browser support) and validate
        // if it is an int - set the height of the iframe #my-iframe-id
        if (e.data === parseInt(e.data)) 
            document.getElementById('my-iframe-id').height = e.data + "px";
    }, false);
</script>

Note: You can limit the source of the message for security by asking the event for its origin (e.origin).

Now we need to post the message, the height of its content, by the iframe:

<script type="text/javascript">
    // all content including images has been loaded
    window.onload = function() {
        // post our message to the parent
        window.parent.postMessage(
            // get height of the content
            document.body.scrollHeight
            // set target domain
            ,"*"
        )
    };
</script>

Thats it. Thats all.

0

Quickly preview web fonts on a website

If you are a web designer, you you probably should know that your typography helps to create an experience for users before they’ve even read a word or clicked a button.

With web services like Google Web Fonts and the Font Face Generator, including new fonts into your website is very easy nowdays.

But takes some time to change and preview different fonts on your page if you do it manually.

Thankfully there are some services which make your life easier and enables you to quickly preview your whole website with different available webfonts:

Font Swapper by webtype.com

TypeWonder by Fonts.com

 

Web Fonts Preview of michilehr.de

Webtype Font Swapper Preview of michilehr.de

Enjoy using them!
2

Think before using “return false;”

One of the first things jQuery coders learn is how they can stop the browser from calling the default action of an event.

$('a').click(function(){
    alert('You have clicked the link!');
    return false; //stop browser from opening the link - DONT USE! SEE BELOW
})

“return false;” will stop the browser calling the default behaviour: opening the clicked link. But using “return false;” in that way is very bad.

What “return false” is really doing

“return false;” does not only stop the browser from calling the default behaviour, it also stops events from propagating so they can’t be handled somewhere else!

jQuery event.js Line 393+: Handle return false; :

if ( ret !== undefined ) {
    if ( (event.result = ret) === false ) {
        event.preventDefault();
        event.stopPropagation();
    }
}

The correct method

“stop the browser from calling the default action” – thats what we want to achieve. Like you can see in the above jQuery code, “return false;” calls preventDefault() and stopPropagation().

stopPropagation(): Stop events from propagate
preventDefault(): Stop default behaviour of browser

So in most cases, especially when working with jQuery Plugins you will only need to apply preventDefault to an event because the event must propagate.

$('a').click(function(e){
    alert('You have clicked the link!');
    e.preventDefault(); // correct method
    return true;
})
1

Resize images and save with new name recursively with bash

When we prepared the relaunch of diginights.com with our new and awesome responsive layout, we needed to resize a bunch of flyer, location and avatar images (~1.000.000). One of our requirements was that we save the images with a new tag so we won’t affect the running application. The following bash one-liner will find all images recursively in a directory and resizes them to a specific size and replaces a given string in the filename.

In the example, we search for files which match the pattern ‘preview_image*-default-*’ and resize them to a width of 238 pixel. The new image will be saved in the same path, but in the filename, we replace the string ‘-default-‘ with ‘-resp-‘.

find . -name 'preview_image*-default-*' -print0 | xargs -0 -L 1 -I {} bash -c 'f="{}"; convert -compress JPEG -resize 238 "$f" "${f/-default-/-resp-}"'
0

Responsive emails and the capabilities by clients

Android 4 nativeEverybody is talking about responsive web design these days – but what about the emails? Lots of people are checking their email via their smartphones or tablets. Most of those newsletter or notification emails which I receive have a static layout and are almost unreadable on mobile devices.

The solution will be a responsive email design.

In contrast to a responsive web design you will have to pay attention to lots of different email clients and web applications and their capablities concerning css and their media query support.

List with css capabilities by clients
List with media query support by clients

Now you will have to choose the clients you want to reach – and I think thats almost all 🙂

We at Filmfrage.net have decided to use a minimal newsletter design so we support almost 100% of the common used email clients and web applications.

 

0

JimFlow – my bachelor thesis

To complete my bachelor degree course “Software Engineering” at Heilbronn University, i have written my bachelor thesis with the title Develop a system for monitoring, recording and processing of state changes on a work plan.

Fridel, David J. Anderson and I

The goal was to create a proof of concept for a full automated system to track the state changes on a work plan. After i have completed the thesis and also received my bachelor degree, i have started to create JimFlow with my workmate Robin.

Should we use a physical board or an electronic tool?

In the agile world, this question is the center of many heated debates. Both solutions have their advantages and both have their flaws.

Physical Kanban boards have visibility and presence. They encourage face-to-face communication, enhance stand-up experiences and serve as a constant reminder of team goals and achievements.

image

Digital boards are accessible from anywhere, making remote collaboration a breeze. Digital boards are great for distributed teams and maintenance of charts, and they link directly to the associated tickets.

 

JimFlow is a hybrid tool that combines advantages of both worlds: A physical board linking all tickets to its digital counterpart. Through the use of corresponding QR Codes, a camera monitors the physical board, automatically detecting any QR code movement.Then, using JimFlow software, an electronic image of the board is generated, viewable in any web browser.

image

Robin has created the component JimFlowPrint which enables you to print your tickets out of your ticket system with just one click while i have created the other components to track those printed tickets on the physical board.

JimFlow is now free for use and also open source.

0

Memory and Doctrine 1.2

When dealing with doctrine 1.2 and medium data, you will probably see something like this:

Fatal error: Allowed memory size of X bytes exhausted (tried to allocate X bytes)

To avoid this you should care about the following points:

1. If you only want to read data fetch it as an array. Nobody needs an overloaded active record while read only.

$q->setHydrationMode(Doctrine_Core::HYDRATE_ARRAY)

2. Select only the data you need – especially when using multiple inner joins.

$q->select('u.id, u.email, u.slug')
$q->from('User u')

3. Use pagination while using active records

4. Use free on objects you dont need any longer when using php <= 5.2.5

0

Speed up Swiftmailer while using an external smtp

Do you send lots of emails with one task via swiftmailer and an external smtp? Here are some tips for you:


1. One mailer object only!

Create the mailer object once and use this object for all the emails. Every time you create and use a new mailer object, a new smtp connection will be established. This would cost lots of time.

 

2. Use the anti flood plugin

We dont want to send all 9999999 emails via one smtp connection. If there is an error in the connection, it will be very bad for the emails followed. Instead of this, we will close the connection after x emails and create a new one. Thanks to Fabien Potencier, there is already a plugin thats doing this job called Swift_Plugins_AntiFloodPlugin. The following code will register theplugin which reestablishes connection after 200 mails:

$mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(200));


3. Use caching in memory

Especially when you use the decorator plugin you should use the memory to cache the body.

For example:

Swift_Preferences::getInstance()
      ->setCacheType('disk')
      ->setTempDir('/run/shm')
;


4. Update swiftmailer

There was an error in the qp encoding of swiftmailer. Upgrade to the newest version will fix this. If you cannot upgrade for example with symfony 1.4, you can try to set the encoding to 8 bit.

$message->setEncoder(Swift_Encoding::get8BitEncoding());
0

Full page caching with Symfony2 and the Symfony2 reverse proxy

Activate the cache in web/app.php

require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
require_once __DIR__.'/../app/AppCache.php';

use Symfony\Component\HttpFoundation\Request;

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$kernel = new AppCache($kernel);
$kernel->handle(Request::createFromGlobals())->send();

After that, go to your controller action. At first, you will need to create a new Response object. After that set it as public so the cached response is used by all visitors. Then you will need an unique identifier, the etag, for the cache – an id and a modified date of the resource for example. If the resource is not modified the cached response will be responded. If the resource was modified since the last cache got created, a new cached response will be created with the new eTag. See the example:

public function detailAction($id) {

        $response = new Response();
        $response->setPublic();

        $em = $this->get('doctrine')->getEntityManager();
 
        $article = //get article by id from repository
  
        $identifier = md5(
                        $article->getId().
                        $article->getUpdatedAt()->format('Y-m-d H:i:s')
                      )

        $response->setETag($identifier );

        if ($response->isNotModified($this->get('request'))) {
            return $response;
        }

        //do the heavy work 

        return $this->render(
            'MyAwesomeBundle:Board:detail.html.twig',
            array('awesomeObject' => $awesomeObject),
            $response
        );
    }
?>

Important: The Symfony2 reverse proxy is cool – but not that fast as reverse proxies written in c. If you want to build a website with a very high load, please consider using Varnish with Symfony2 for example.