Building web applications with Javascript - I Using JavaScript

Sep 16, 2006 - Docs kind of skimpy, therefore slightly steep learning curve. • Not as well-thought as ... Use the dojo->widget< class ... Google and Yahoo! Maps.
357KB taille 0 téléchargements 338 vues
New Delhi, 16th September 2006

Building web applications with Javascript - I Building Web Applications

Using JavaScript, MochiKit and Dojo Part I - Introduction to JavaScript Anant Narayanan Malaviya National Institute of Technology, Jaipur

Overview - Part I • • •

Web Applications - Why not a desktop app? JavaScript - An introduction AJAX - What's all the hype about?

What are web applications? • • • • •

Applications that run on a web browser Relies entirely on HTML and JavaScript for User Interface Local Server Browser (or) Internet Browser Usually consists of only a few web pages Examples include: YouOS, GMail, phpmyadmin

Why web applications? • • • • •

Very lean pre-requisites - Browser + Plugins Reaches a vast majority of people No Installation, easy updating and maintenance No cross platform quirks Needs lesser effort to guarantee consistent output

Why NOT web applications? • • • • •

Highly customised UI's not possible Not very reliable Inherent delays (Internet) Not very secure No system software is possible

1

Traditional web applications • • • • •

J2EE extremely popular Synchronous action - response model Relies on Java Applets or Flash for richer widgets All processing is done on the server, client is "dumb" Still useful in many cases

Enter JavaScript! • • • • • •

Plays two major roles: • Allows for a more richer and dynamic UI Makes the client a bit more intelligent Client is now able to handle data and respond to the user User is now more involved instead of "Click and Wait" Most browsers come with JavaScript enabled, no other pre-requisites! Supports object-oriented programming, powerful and easy to learn

So how does it work? • • • • • • •

Scripting language embedded in HTML Executed as an interpreted language by the browser (client) Open specification, driven by Mozilla Can be used for simple tasks like: • Creating customised popup windows Creating cookies Detect user's browser More powerful applications are possible through the AJAX concept!

How do we interact with HTML? • • • • • • • • •

Document Object Model Specified by the W3C as a standard Representation of an XML document as a tree Defines specific methods of accessing XML elements • Nodes Elements Attributes Text Defines events that can be attached to HTML nodes Four levels of specification: 0, 1, 2, 3 - implemented by most modern browsers

What can we do with DOM? • • • •

Dynamically add, remove and modify HTML React to events triggered by user immediately Validate forms on the client-side Play around with XML files!

2

Need more interactivity with the server? • • •

Enter AJAX! Asynchronous Javascript And Xml Can make requests (usually GET or POST) to server without page reload

What's different?

User feels less bored!

How do I do this AJAX stuff? •

Makes use of the XMLHttpRequest() object (JavaScript), ActiveXObject(Microsoft.XMLHTTP) (JScript) 3

• •

Yeah, different browsers implement JavaScript (and DOM!) in different ways :-( You'll have to detect the browser and use an appropriate object

There MUST be an easier way! • • • •

Sure, that's what MochiKit and Dojo are for! Toolkits come to the rescue Give you a neat, unified way of doing things in JavaScript Lots of reusable code, hardly anyone writes "raw" JavaScript nowadays

Any questions so far?

4

New Delhi, 16th September 2006

Building web applications with Javascript - II Building Web Applications

Using JavaScript, MochiKit and Dojo Part II - MochiKit Anant Narayanan Malaviya National Institute of Technology, Jaipur

Overview - Part II • • • • •

Introduction to MochiKit Making AJAX work Functional programming DOM Manipulation JavaScript Interpreter

Introduction

MochiKit makes JavaScript suck less! • • • •

Bob Ippolito's brainchild Programmer's Paradise! Extremely well thought out and heavily documented "Borrows" lots of ideas from Python and Twisted

Using MochiKit • • • •

Does not interfere with other JavaScript Code Possible to prevent functions from being exported to global namespace Available as "Packed"' and "Split" versions Split into 14 categories: Asyc, Base, DOM, DragAndDrop, Color, DateTime, Format, Iter, Logging, LoggingPane, Signal, Style, Sortable, Visual

5

Program, don't design with this! • • • •

More of a programming aid than a visual widget/animation set DragAndDrop, Visual picked from script.aculo.us Added only recently, buggy... Other 12 categories rock!

Let's take a look at them...

AJAX with MochitKit.Async • • • • • •

Uses Deferred object, much like in Twisted Represents a value that you don't have with you yet Attach callbacks to the object, they are called when value is ready (or error is encountered) Or use the doSimpleXMLHttpRequest to send a quick GET request to a URL (returns a Deferred object) Use the getXMLHttpRequest method to obtain a XMLHttpRequest object transparently Quick and Painless, abstracts all browser incompatibilities!

Functional programming with MochiKit.Base • • • • •

Excellent methods to make programming easier Use compare to sensibly match two objects: Arrays, Dates, Strings and Numbers You can add your own custom comparator with registerComparator Provides programmer representation, just like repr in Python Evaluate JSON strings (evalJSON) and create serialized JSON from objects (serializeJSON)

MochiKit.Base (continued) • • • • • •

Want to copy over key:value pairs to an existing object? update it! What to use an exclusively mutable object? clone is your friend! Want to iterate over a tree of objects? Check out nodeWalk! Want to apply the same function on all objects of an array? Just map it! Want to supply only partial arguments to a function? partial lets you do just that! Lots and Lots of more nifty stuff... Python programmers feel at home :)

DOM it with MochiKit.DOM • • • • • • •

Easily the best DOM creation and manipulation API Creating Nodes is a piece of Cake with createDOM Commonly used tags are available as aliases to make things even more easier! (A, BUTTON, DIV, TABLE etc.) Get DOM nodes based on their class with getElementsByTagAndClassName Convert your own objects into DOM Nodes using registerDOMConverter scrapeText out of any DOM Node of your choice All the standard DOM functions have wrappers with added functionality...

MochiKit.Color and MochiKit.DateTime • •

CSS3 based Color abstraction Interconvert Strings, RGB, Hex, HSV and HSL values 6

• •

Control brightness, intensity and alpha values Convert between ISO and JavaScript Date objects

MochiKit.Format and MochiKit.Iter • • • • • •

Do all kinds of string formatting Inspired by the Number format pattern Syntax of Java Iteration in JavaScript made easy, again, inspired by Python's iteration and itertools modules Add iteration capabilities to your custom objects with registerIterator forEach is most useful when you need to iterate over an iterable Standard stuff like count, next, range available

Debug with MochitKit.Logging • • • • •

Stop peppering your code with alert! JavaScript logs viewabale in FireFox Otherwise use the LoggingPane Opens up a popup window, very useful for debugging Use the log method, different levels such as DEBUG, INFO, WARN possible

Handle events with MochiKit.Signal • • • • • • •

More amazing than MochiKit.DOM! Connect DOM events, Browser events, Object events freely through unified API! Mother of all event API's - single connect function All DOM events converted to lower case: onClick becomes `onclick' Synthesized events like onmouseenter Based on Qt's signal-slot system Use signal to trigger your own signal

Spice up with MochiKit.Style and MochiKit.Visual • • • • •

CSS and Visual Effects Mostly adapted from script.aculo.us Modify CSS characteristics, hide and show elements Some good transition effects No layout and widgets though...

Dojo and script.aculo.us better at this kind of stuff :)

MochiKit.DragAndDrop and MochiKit.Sortable • • • •

Easy to use, smooth drag and drop Not very powerful though! Nice if your app doesn't need very snazzy stuff And it's quite light...

The MochiKit JavaScript Interpreter •

It's the icing on the cake! 7

• • •

Enables efficient debugging and rapid prototyping Quickly try out MochiKit (and other) JavaScript methods Yeah, it's like the Python Interpreter... Again!

Okay that's enough of programming... How do I make websites with amazing looks? Dojo will take care of your appearance... Any questions so far?

8

New Delhi, 16th September 2006

Building web applications with Javascript - III Building Web Applications

Using JavaScript, MochiKit and Dojo Part III - Dojo Anant Narayanan Malaviya National Institute of Technology, Jaipur

Overview - Part III • • • • • •

The Dojo Way Widgets Layout Animation Offline Storage AJAX and Programming

Introduction

• • • •

Lots of functionality rolled into one Nice packaging and build system Plenty of useful widgets and layout options Revolutionary offline storage system available

Using Dojo • • • • •

Allows you to import external code or create your own packages MochiKit can be imported as a Dojo package! Specialised packed versions available: eg) dojp-widgets or dojo-ajax Docs kind of skimpy, therefore slightly steep learning curve Not as well-thought as Mochikit, yet extremely powerful and popular

9

What is Dojo made up of?

Dojo's layered architecture

Dojo Widgets • • • •

A set of predefined widgets that can replace their HTML equivalents Make better-looking buttons, checkboxes and combo boxes More sophisticated widgets like DatePicker, TimePicker and ColorChooser Extensible architecture, you can define your own widgets!

Creating and modifying widgets • • • • •

Can be defined as HTML div tags with the dojoType parameter Need W3C compliant HTML? Use the dojo->widget< class Dojo parses HTML before it is loaded and replaces all such HTML with a battery of HTML and JavaScript that represents your widget Two-State approach, actual HTML differs from your Widget object, which can be modified For dynamic widgets, you can use the createWidget method to create and show widgets programmatically

Some more useful widgets • • • • • • • •

Trees Menus Fisheye (Apple Dock style!) inlineEditBox (Think flickr!) Tooltips Charts Slideshows Google and Yahoo! Maps

Widget principles • • •

Work cross browser Gracefully degrades Accessible 10

• •

Supports i18n Extensible Let's take a look at the Dojo General Widget Demo...

Form Validation • • • •

Great validation features Integrate all your widgets into the form Results in a form that looks good AND validates! Autocompletion and regex supported

Defining Layout • • • • • • • • •

Those familiar with GUI programming will like this! HPanes and VPanes Tabs Containers • Really great concept Acts and feel like iFrames But are part of current Document! Can load external content! Windows Wizards

Drag And Drop & Effects • • • • • • •

Readily sortable lists Define DragSources and DragDestinations DragMove allows widgets to be moved anywhere, eg: Windows Drag handles can be specified Visual effects have all the usual suspects: • Fade Wipe Slide

Animation • • • • •

Real good library Combined with effects, who needs Flash?! Complex stuff like Bezier curve based animation possible Lots of predefined animations like Highlight and Explode Slightly buggy, not entirely cross-browser, but great future!

Rich text editor • • • •

Great replacement for the bland textarea Can edit Rich Text (HTML Output) Based on the Moxie Editor RichText widget available to just display

11

• •

Editor2 Framework under development (GSoCTM), plugin system Enhances RTE's features, we are working on XML editing too

Offline Storage • • • • •

RTE capable of storing text offline! No server required! Uses the Flash engine for persistence, but other drivers like Cookies are possible The "New" web! Enables some really creative applications

Dojo and script.aculo.us better at this kind of stuff :)

You can do AJAX too! • • • •

Dojo has powerful I/O system and Language Utilities Not well documented, buggy and doesn't make it as easy as MochiKit Can send data over alternate transports (other than XMLHttp) Has an RPC interface to manage multiple calls

Customising Dojo • • •

Nice modular architecture Define and customise widgets Create custom packages and builds (Uses Ant build system)

Summary Great stand alone package Although using MochiKit will make your programming life easier! Picks the best of all JavaScript tookits, you usually don't need anything else Any questions so far?

12

New Delhi, 16th September 2006

Building web applications with Javascript - IV Building Web Applications

Using JavaScript, MochiKit and Dojo Part IV - Case Studies Anant Narayanan Malaviya National Institute of Technology, Jaipur

Pure JavaScript S5: HTML Presentation • • • •

This presentation was made in S5! Great example of how you can use JavaScript to interact with user S5 is very useful for online presentations Completely standards Compliant

MochiKit Integrated into TurboGears PlotKit: Charting Library • • •

Uses MochiKit's language facilities Supports SVG creation Clean and Fast, thanks to MochiKit

Dojo YouOS: The web operating system! • • • •

MIT Product: Very Interesting - MUST SEE! Complete OS environment Dojo's extensibility allows you to write applications for YouOS! Applications like Browser, Notes and Terminal already available

MochiKit And Dojo Beacon: The GuideXML editor • •

Uses MochiKit for language and AJAX Uses Dojo to create layout and widgets 13

• • •

MochiKit dynamically creates Dojo widgets using swapDOM Will drive development of Dojo's inlineEditBox and Editor2 Example of where web applications can replace traditional apps

Think about your next Killer App! http://www.kix.in/webapps/ [email protected] KillerX @ irc.freenode.net Thank you!

14

ChiPy, 11 November 2004

SQLObject and Database Programming in Python The Ongoing Example

Address book: • • • • •

person: • first_name last_name email (many emails for one person) email: • type address

The DB API Database programming in Python is based on the DB-API. Some supported databases: • • • • • •

MySQL PostgreSQL (multiple drivers) SQLite Firebird (Interbase) MAXDB (SAP DB) Oracle, Sybase, MS SQL Server

DB API Example Example: import MySQLdb conn = MySQLdb.connect( db='test', username='ianb') cur = conn.cursor() cur.execute( "SELECT id, first_name, last_name FROM person") result = cur.fetchall() for id, first_name, last_name in result: print "%2i %s, %s" % (id, last_name, first_name)

DB API • • • • •

Import the database module (MySQLdb, psycopg, sqlite, etc) Use module.connect(...) to create a connection. Use connection.cursor() to get a cursor. Cursors do all the work. Use cursor.execute(sql_query) to run something. Use cursor.fetchall() to get results.

15

DB API problems 1. 2. 3. 4. 5.

Connections and cursors are tedious. The databases don't all work the same; multiple SQL dialects. Lots of time spent writing SQL. Database updates can effect all the SQL you've written. Unless you make abstractions...

Abstractions • •

Every significant database application has a database abstraction layer. You write one whether you mean to or not.

Object-Relational Mappers The table: person id first_name last_name 1 John

Doe

2 Tom

Jones ...

ORMs: Classes The class: person id first_name last_name 1 John

Doe

2 Tom

Jones

class Person(SQLObject): # id is implicit first_name = StringCol() last_name = StringCol()

...

ORMs: Instances An instance: person id first_name last_name 1 John

Doe

2 Tom

Jones

>>> john = Person.get(1) >>> john.first_name 'John'

...

ORM: summary • •

Every table is a class Every row is an instance 16



Columns become attributes

Usage __connection__ = 'postgres://pgsql@localhost/test' class Person(SQLObject): first_name = StringCol() last_name = StringCol() emails = MultipleJoin('Email')

Usage (classes) class Email(SQLObject): person = ForeignKey('Person') type = EnumCol(['home', 'work']) address = StringCol()

Usage (creating tables) def createTables(): for table in (Person, Email): table.createTable(ifNotExists=True)

Usage (instances) Using your classes: >>> john = Person(first_name='John', last_name='Doe') >>> email = Email(person=john, type='home', ... address='[email protected]') >>> john.emails []

Usage (instances) >>> tom = Person(first_name='Tom', last_name='Jones') >>> tom is Person.get(tom.id) True >>> list(Person.selectBy(first_name='John')) []

Defining Classes • • •

The class name matches the table name The attributes match the column names (kind of...)

Defining Classes... You can add extra methods: class Person(SQLObject):

17

... def _get_name(self): return self.first_name + ' ' + self.last_name >>> tom.name 'Tom Jones'

Automatic properties • • •

_get_attr() methods are called whenever the obj.attr attribute is called _set_attr() methods are called whenever the obj.attr = value statement is run _set_attr() is optional

Defining classes... You can override columns: class Person(SQLObject): ... last_name_searchable = StringCol() def _set_last_name(self, value): self._SO_set_last_name(self, value) self.last_name_lower = re.sub(r'[^a-zA-Z]', '', value).lower()

Defining classes... You can fiddle with the naming: class Person(SQLObject): _table = "people" first_name = StringCol(dbName="fname") ...

Connecting classes Foreign Keys: class Email(SQLObject): person = ForeignKey('Person') ...

Note we use a string for 'Person'.

Backreferences The other side of one-to-many: class Person(SQLObject): ... emails = MultipleJoin('Email')

Many-to-many Many to many relationships imply a "hidden" table: 18

class Address(SQLObject): people = RelatedJoin('Person') ... class Person(SQLObject): addresses = RelatedJoin('Address')

Many-to-many... The intermediate table created: CREATE TABLE address_person ( address_id INT NOT NULL, person_id INT NOT NULL );

Lazy classes SQLObject can use reflection to figure out what columns your table has: class Person(SQLObject): _fromDatabase = True

You can start with _fromDatabase = True and add in explicit columns, overriding defaults.

Instances • • •

Use Person.get(id) to retrieve a row Use Person(first_name=...) to insert a row (the new object is returned) Use aPerson.destroySelf() to delete a row

Updating • •

aPerson.first_name = "new_name" UPDATE is executed immediately Update multiple columns at once: aPerson.set(first_name="new_fname", last_name="new_lname")

Selecting You can use Python expressions (kind of): query = Person.q.first_name == "Joe" Person.select(query)

Selecting... • • •

Class.q.column_name creates a magical object that creates queries. sqlrepr() turns these query objects into SQL (mostly hidden) sqlrepr(Person.q.first_name == "Joe", 'mysql') creates the SQL person.first_name = 'Joe'

19

Selecting... Complicated joins are possible: Person.select((Person.q.id == Email.q.personID) & (Email.q.address.startswith('joe')))

Becomes: SELECT person.id, person.first_name, person.last_name FROM person, email WHERE person.id = email.person_id AND email.address LIKE 'joe%'

SelectResult Select results are more than just lists: • • • •

You can slice them, and LIMIT and OFFSET statements are added to your query You can iterate through them, and avoid loading all objects into memory You can do things like select_result.count() to run aggregate functions To get a real list, you must do list(select_result)

Caching • • • • •

SQLObject caches everything Maybe too much (bad if you have multiple updaters) Needs to because there's no joins Has potential to be faster than ad hoc queries Thread safety or thread confusion?

Performance • • •

Not good if you are dealing with lots and lots of rows Inserts and selects substantially slower But for many applications you'll pay that price sooner or later anyway

The problem with ORMs ORMs live in the world between Object Oriented programmers (and programs) and Relational programmers (and programs). Neither will be happy.

ORM Mismatch • •

Python classes aren't tables Python instances aren't rows

ORM Mismatch: Classes • • •

Databases don't have inheritance Even when they do, no one uses it Some tables are too boring (e.g., intermediate tables for many-to-many relationships), or don't warrant 20

the overhead

ORM Mismatch: Instances • • • •

Instances get garbage collected, rows are forever Rows exist even when instances don't Instances may still exist when the row is gone In the relational calculus, rows don't have real identity

ORM Mismatch: Relations • • •

Things like joins don't make sense for objects, but are central to relations Views and stored procedures also don't make sense Aggregate functions and set operations aren't natural in Python (the for loop is natural)

Solving the question by avoidance • • • •

SQLObject doesn't let you forget SQL You still have to think relationally But many relational concepts don't work either Advantage: it's easy

Solving the Mismatch SQLObject's answer: don't try too hard. • • • •

There exist database restrictions; not every database schema maps well. (But most are fine) Sometimes you have to do things more slowly or more imperatively, compared to a purely relational technique There exist object restrictions; not every object-oriented concept maps well; e.g., no inheritance Inheritance isn't planned; this isn't transparent persistence

Some other alternatives Several Python ORMs exist; contrasts: • • • •

SQLObject doesn't try to be too OO, so it works well with normal database schemas SQLObject doesn't have a compile step SQLObject isn't just a SQL wrapper SQLObject is reasonably complete

Other alternatives... See the Python Wiki at: python.org/moin The page is HigherLevelDatabaseProgramming.

21