Tag Archives: javascript

Optimize Youtube Embeds with Facades

Embedding Youtube videos on your website can be very easy, but the typical ways of doing it can slow down your page load time. If you want to ensure the best user experience, then you can improve your page speed performance by lazy loading Youtube videos with a facade. Here’s how to do it using lite-youtube.

1. Add the Script

First, add the following script to your web page footer:

<script type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@1.5.0/lite-youtube.js" async></script>

2. Replace YouTube Embeds

For each YouTube video on your page, replace the standard YouTube embed code with the following custom HTML:

<lite-youtube videoid="VIDEO_ID" videotitle="VIDEO_TITLE" width="WIDTH" height="HEIGHT">
<a class="lite-youtube-fallback" href="https://www.youtube.com/watch?v=VIDEO_ID">Watch "VIDEO_TITLE" on YouTube</a>
</lite-youtube>

The HTML link inside the lite-youtube element is a fallback, that will only be displayed when someone’s browser can’t run the lite-youtube script.

3. Customize for Each Video

Make sure to update the following attributes for each video:

  • videoid: The unique identifier of the YouTube video, a series of random letters & numbers in the embed link
  • videotitle: The title of the video
  • width: The width of the video player
  • height: The height of the video player
  • href: The full YouTube URL of the video
  • Fallback text: Update the text inside the <a> tag

4. Determine Video Size

To determine the correct width and height for each video:

  1. Open your browser’s developer tools
  2. Inspect the current YouTube embed
  3. Look for the computed style to find the exact dimensions

That’s it! Now when your page loads, the videos will initially be rendered as images. The embedded Youtube player won’t load until you click the image. This method eliminates a lot of javascript execution and load time, improving your page speed performance and SEO.

A Quick Simple Way to Download All the Images on a Page

You don’t need to write a web scraper to do this, just some simple code and standard linux/unix commands.

  1. Open the page in your web browser
  2. Open the Developer Tools
  3. Paste in the following Javascript
var images = document.getElementsByTagName('img'); 
var srcList = [];
for(var i = 0; i < images.length; i++) {
    srcList.push(images[i].src.split('?', 1)[0]);
}
srcList.join('\n');
  1. Create a folder to store the images
  2. Copy the text output from above into a file & save as images.txt in your folder
  3. Inspect images.txt to make sure it looks right
  4. Run the following commands in a terminal, from your folder
cat images.txt | sort | uniq > uniq_images.txt
wget -i uniq_images.txt

Now all the images from that page should be in the folder you created.

Python 3 Web Development Review

Python 3 Web DevelopmentThe problem with Python 3 Web Development Beginner’s Guide, by Michel Anders, is one of expectations (disclaimer: I received a free eBook from Packt for review). Let’s start with the title… First we have Python 3 Web Development. This immediately sets the wrong expectations because:

  1. There’s almost as much jQuery & Javascript as there is Python.
  2. Most of the Python code is not Python 3 specific, and the code that is could easily be translate to Python 2.
  3. Much of the Python code either uses CherryPy or is for generating HTML. This is not immediately obvious, but becomes apparent in Chapter 3 (which is available as a free PDF download: Chapter 3 – Tasklist I Persistence).

Second, this book is also supposed to be a Beginner’s Guide, but that is definitely not the case. To really grasp what’s going on, you need to already know the basics of HTML, jQuery interaction, and how HTTP works. Chapter 1 is an excellent introduction to HTTP and web application development, but the book as a whole is not beginner material. I think that anything that uses Python metaclasses automatically becomes at least intermediate level, if not expert, and the main thrust of Chapter 7 is refactoring all your straightforward database code to use complicated metaclasses.

However, if you mentally rewrite the title to be “Web Framework Development from scratch using CherryPy and jQuery”, then you’ve got the right idea. The book steps you through web app development with CherryPy, database models with sqlite3, and plenty of HTML and jQuery for interface generation and interaction. While creating example applications, you slowly build up a re-usable framework. It’s an interesting approach, but unfortunately it gets muddied up with inline HTML rendering. I never thought a language as simple and elegant as Python could be reduced to the ugliness of common PHP, but generating HTML with string interpolation inside the same functions that are accessing the database gets pretty close. I kept expecting the author to introduce template rendering, which is a major part of most modern web development frameworks, but it never happened, despite the plethora of excellent Python templating libraries.

While reading this book, I often had the recurring thought “I’m so glad I use Django“. If your aim is rapid application development, this is not the book for you. However, if you’re interested in creating your own web development framework, or would at least like to understand how a framework like Django could be created, then buy a copy Python 3 Web Development.

jQuery Validation with Django Forms

Django has everything you need to do server-side validation, but it’s also a good idea to do client-side validation. Here’s how you can integrate the jQuery Validation plugin with your Django Forms.

jQuery Validation Rules

jQuery validation works by assigning validation rules to each element in your form. These rules can be assigned a couple different ways:

  1. Class Rules
  2. Metadata Rules
  3. Rules Object

Django Form Class Rules

The simplest validation rules, such as required, can be assigned as classes on your form elements. To do this in Django, you can specify custom widget attributes.

[sourcecode language=”python”]
from django import forms
from django.forms import widgets

class MyForm(forms.Form):
title = forms.CharField(required=True, widget=widgets.TextInput(attrs={
‘class’: ‘required’
}))
[/sourcecode]

In Django 1.2, there’s support for a required css class, but you can still use the technique above to specify other validation rules.

Django Form Metadata Rules

For validation methods that require arguments, such minlength and maxlength, you can create metadata in the class attribute. You’ll have to include the jQuery metadata plugin for this style of rules.

[sourcecode language=”python”]
from django import forms
from django.forms import widgets

class MyForm(forms.Form):
title = forms.CharField(required=True, minlength=2, maxlength=100, widget=widgets.TextInput(attrs={
‘class’: ‘{required:true, minlength:2, maxlength:100}’
}))
[/sourcecode]

jQuery Validate Rules Object

If your validation requirements are more complex, or you don’t want to use the metadata plugin or class based rules, you can create a rules object to pass as an option to the validate method. This object can be generated in your template like so:

[sourcecode language=”html”]
<script type="text/javascript">
FORM_RULES = {
‘{{ form.title.name }}’: ‘required’
};

$(document).ready(function() {
$(‘form’).validate({
rules: FORM_RULES
});
});
</script>
[/sourcecode]

The reason I suggest generating the rules object in your template is to avoid hardcoding the field name in your javascript. A rules object can also be used in conjunction with class and metadata rules, so you could have some rules assigned in individual element classes or metadata, and other rules in your rules object.

Error Messages

If you want to keep the client-side validation error messages consistent with Django’s validation error messages, you’ll need to copy Django’s error messages and specify them in the metadata or in a messages object.

Metadata Messages

Messages must be specified per-field, and per-rule. Here’s an example where I specify the minlength message for the title field.

[sourcecode language=”python”]
from django import forms
from django.forms import widgets

class MyForm(forms.Form):
title = forms.CharField(minlength=2, widget=widgets.TextInput(attrs={
‘class’: ‘{minlength:2, messages:{minlength:"Ensure this value has at least 2 characters"}}’
}))
[/sourcecode]

Messages Object

Messages can also be specified in javascript object, like so:

[sourcecode language=”html”]
<script type="text/javascript">
FORM_RULES = {
‘{{ form.title.name }}’: ‘required’
};

FORM_MESSAGES = {
‘{{ form.title.name }}’: ‘This field is required’
};

$(document).ready(function() {
$(‘form’).validate({
rules: FORM_RULES,
messages: FORM_MESSAGES
});
});
</script>
[/sourcecode]

Just like with validation rules, messages in element metadata can be used in conjunction with a global messages object. Note: if an element has a title attribute, then the title will be used as the default error message, unless you specify ignoreTitle: false in the jQuery validate options.

Error Labels vs Errorlist

Django’s default error output is an error list, while the default for jQuery Validation errors is a label with class="error". So in order to unify your validation errors, there’s 2 options:

  1. make jQuery Validation output an error list
  2. output error labels instead of an error list in the template

Personally, I prefer the simple error labels produced by jQuery validation. To make Django generate those instead of an error list, you can do the following in your templates:

[sourcecode language=”html”]
{{ field }}
{% if field.errors %}
{# NOTE: must use id_NAME for jquery.validation to overwrite error label #}
<label class=’error’ for=’id_{{ field.name }}’ generated="true">{{ field.errors|join:". " }}</label>
{% endif %}
[/sourcecode]

You could also create your own error_class for outputting the error labels, but then you’d lose the ability to specify the for attribute.

If you want to try to make jQuery validation produce an error list, that’s a bit harder. You can specify a combination of jQuery validation options and get a list, but there’s not an obvious way to get the errorlist class on the ul.

[sourcecode language=”javascript”]
$(‘form’).validate({
errorElement: ‘li’,
wrapper: ‘ul’
});
[/sourcecode]

Other options you can look into are errorLabelContainer, errorContainer, and a highlight function.

Final Recommendations

I find it’s easiest to specify class and metadata rules in custom widget attributes 90% of the time, and use a rules object only when absolutely necessary. For example, if I want to require only the first elements in a formset, but not the rest, then I may use a rules object in addition to class and metadata rules. For error messages, I generally use a field template like the above example that I include for each field:

{% with form.title as field %}{% include "field.html" %}{% endwith %}

Or if the form is really simple, I do

{% for field in form %}{% include "field.html" %}{% endfor %}

Design Patterns in Javascript – Model-View-Controller

Model-View-Controller, or MVC for short, is an software architecture pattern for user interfaces that creates a distinction between the display (or view), the data (or model), and the interaction (or controller). In this article, I’m going to focus specifically on how MVC applies to the client side of web applications. What I mean is that MVC in a web based ui translates to

This separation of concerns means that as long as the model stays consistent, you can

  1. Create multiple views for the same model
  2. Develop the controller and views independently

For a great example of 1 checkout css Zen Garden. Here, the same HTML (the model) can be seen with many different views.

Now checkout the jquery ui demos for a clear example of both 1 and 2. Again, the same HTML has many different views with the various CSS themes, and you can also see jquery ui controller code in action. The Javascript manipulates the model, affecting what you see and how you see it, independently of which theme (or view) you choose.

What this all means is that you can create semantically correct HTML optimized for search engines, CSS so your page looks good for humans, and Javascript to make your page interactive. In other words, content can be separated from presentation, which can be separated from the interaction behavior. The CSS and Javascript can be developed (mostly) independently and only be loosely coupled to the HTML.

Taking this a step further, it’s possible to create generic views and controllers using CSS and Javascript that work on a small generic model. jquery ThickBox is an example of this, since it can be used on any page where you have <a class='thickbox' ...>...</a>. As long as your HTML supports the generic model, you can reuse the CSS and Javascript across multiple pages.