Seo For Joomla Website

SEO professional or a team with deep knowledge in optimizing Joomla website. Our website was already optimized long time ago, and now needs further optmization.

Our requirements
• Optimize our website for 10 keywords
• Optimize our website for all london post codes and area names
• Optimize our website for All the most important cities in UK

Please, provide:
Proposal and inform what exactly is included in your price
How long it would take for you to perform the SEO
Other SEO Packages you offer

We are willing to carry on with this project on a yearlly base, if we see good results.

It is important to have skype account for our communication.

WE ARE GOING TO HIRE ONLY THE PROFESSIONAL THAT CAN SHOW PROVEN RESULTS.

Page Editor & Admin2

OK re posting project / coder vanishes after doing nothing somewhere in India.

But it is a NEW day and client still wants work done, so;

Client is adding a very simple feature to his website. He currently has two pages (news & specials) that he is always adding to. He likes the format of listing a thumbnail, title and small description in row view linked to its own page for further expanded details.

An admin control is needed to add/edit/delete or paginate the row view of thumbnails, titles and descriptions for both the new page and the specials page.

Then

Within that admin offer a HTML editor so any person he chooses to update his site can easily “drag and drop” , change fonts, add photos, preview before publishing and/or just be creative to edit the area of the page that will contain the expanded new or special.


Each expanded page will be generated from the script and will have editable meta tags and hot links.

All controls including pagination, tags and content need to be in one easy admin area.

here is what is needed:
one Admin control
2 pages (news and specials) adminable creating the row view as described above.
Generated pages for each title linked from the row view page.

This is simply a drag and drop or cut and paste page editor with an admin.

The Design of the project is complete and the css will remain the same, we only need the script for php installed to update the row view of news page, update specials page and have independent pages generated for each news / special for the purpose of SEO.

((( Bidding criteria / Winning Bidder / Deadline: )))

This project has a 30 day deadline.

Auto Bids or bids with statement such as “Can be done” will be banned forever.

Please look at the attachments carefully before bidding.

Must be available M-F business hours U.S. east coast time.

Must be available during business hours (see above) for daily on MSN during the project (((NO EXCEPTIONS)))

All work will be done on our server – no exceptions

Do not cut and past ANY previous example of links that do not relate to this type of project.

Payment – No exceptions

1/3 at 50% point and balance upon completion

½ of initial payment will be escrowed immediately.

Please read our reviews, We don’t play games and we pay very well. However payment are our on our terms and will NOT Alter.

Most important – Please read Carefully:
This project has a 30 day deadline if this is not something you can focus on and WORK ON PERSONALLY then do not place a bid.

5 Ways You Can Go Wrong with Social Media at Work

Social media is the greatest thing for the working class since the water cooler.

In a 10-minute break we can update our Facebook status, comment on our cousin’s photos and share links to new Muppet videos. But there are professional uses too. You can research solutions to problems, make new connections in your field and keep up with industry developments. There is a case to be made for using social media at work.

Hopefully you won’t have to make such a case at work. It’s tempting for management to restrict and prohibit you from accessing social networking sites. They don’t want you wasting time. But Brad Lawwill, general counsel of Pierce Promotions in Portland, Maine, advocates reasonable social media policies that don’t interfere with employees’ lives.

For example, don’t dictate that you can’t ever talk about your job or check your networks from the office. Lawwill says management is going to create more work for itself than it’s worth. Instead, managers should apply existing policies to social media use.

You probably already have a policy covering breaks and using company resources such as e-mail and the phone for personal use. Those can be applied nicely to your time spent on Facebook or Twitter.

If your boss says social media is fine as long as it doesn’t interfere with work, you’re in luck. Enjoy the freedom and the Mafia Wars. But that doesn’t mean you can’t get in trouble. This is a minefield you can navigate safely but be aware of a few mines you don’t want to trigger.

NSFW – Not Safe For Work

Do I really need to explain why you can’t use the work computers to collect porn? It’s a hostile workplace lawsuit waiting to happen. So you’re not going to watch porn at work.

But what about dirty jokes and sexy pictures? It’s not exactly porn. And it’s shared between consenting adults. But you don’t know who in the office is going to object. Just like telling off-color jokes in a meeting, something a little spicy could be enough reason for someone to file a complaint.

This is where your friends can get you into trouble. Even if you swear off surfing for bikini-model photo collections, you may be connected to someone who wants to share the art form with you. Make sure you avoid those kinds of updates at work.

Your Real Boss is Not a Foreman in Farmville

Even if your updates are totally safe for work, you can’t spend too much time on Twitter or Facebook. This probably is your manager’s biggest concern. Every supervisor looks for the time sucks that can waste productivity. And Facebook is built to distract you from getting any work done.

This is easy for management to track and see how you spend your time. Track your time before your boss does, and cut yourself off.

Discretion is Appreciated

Not everything you do at work is safe to share with your networks. There may be confidentiality expectations – especially when clients are involved. They may not appreciate your updates about what they’re doing when they expect discretion. And your employer may expect the same.

Be careful when talking about your job. Don’t share client’s names unless it already is acknowledged by your company publicly. Make sure you’re not about to share trade secrets. And it’s not a bad idea to become familiar with the contracts with clients. They often are specific about publicity.

Don’t Out Your Boss as a Jerk

In addition to being perfect for providing distractions, social media is built for distributing snarkiness. Your feeds and lists are full of friends rushing to prove how clever they are one snarky and sarcastic phrase at a time. So you’re forgiven if you fire off a zinger or two.

Just don’t make it about work. You don’t want to keep apologizing and explaining yourself to your coworkers and your boss. I know making fun of your boss is a national past time. So do it at happy hour or in a break room when you know he is out of earshot. Don’t write it on a wall that everyone and their human resource department can read.

Not only does it fail to impress current management, but it won’t look good to hiring managers when you re-enter the job market. Clients won’t be impressed either when they see employees trashing the company they’re expected to pay.

Speaking of clients, you don’t want to say anything negative about them either. I don’t care if you do it at home on your personal account. They can’t restrict your freedom of speech but they don’t have to pay someone who is going to criticize them publicly. Would you?

Don’t Make Yourself Look Like a Jerk Either

Did you read Mark Garrison’s column on getting promoted? It’s good advice that can get you far. But all that effort can be erased by the pictures of you from reggae night at your favorite bar. What you do in your personal time should be kept personal. Hard to argue that when unprofessional photos are published on social networks.

And it doesn’t take a photo to make you look like a knucklehead. Off-color remarks or stories about the weekend partying can create negative impressions also.

Some of this really isn’t new. The standards of decorum and manners still apply. Don’t write something on a wall that you wouldn’t say to your boss or a local reporter. It’s easy these days to become an unofficial spokesperson for your employer. Maybe it’s not fair but it’s what is happening.

Design & Slice With Html Css

Hi,
I have a draft of a design that needs to be finished up in a more creative look & then slice with CSS & XHTML.This template will be further implemented by my team on oscommerce.The HTML page will be compatible to all browsers like internet 7,mozilla & chrome

Its a template for a tshirts company engaged in screenprinting & embroidery.Please send me 2-3 links of your webpage designed not the whole bunch of links .

How to Make a Retro RC Airplane Poster

This is an exercise in digital drawing using Adobe Illustrator. In this tutorial, we’ll predominantly be using the Pen, Pencil and Gradient tools to create a fun retro remote-control airplane illustration. It takes quite a bit of work with the Pen, so make sure you’re familiar with the Pen Tool before beginning. Don’t worry if you’re a beginner, this tut is not too difficult, so let’s get on with it!


Step 1

OK, let’s begin by creating a new Illustrator document with an artboard size of 800×950 pixels, or 11×13 inches. In the centre of the canvas, draw a rectangle that is about 450×300 pixels. This is our guide for the airplane’s fuselage, or body. Grab your pen tool and begin drawing the fuselage (body) of the airplane, using the rectangle we just drew as a guide for the size and angle of the shape. It should be pretty thick at the nose. When it’s finished, fill it black with no stroke. Here’s what mine looks like, before it’s black, so you can see the path more easily:


Step 2

Now we draw another shape for the fuselage that’s very similar to the first one. This one is slightly smaller than the first shape and fits inside it. The other shape serves as a thick outline to the body, but doing them as separate shapes gives it a much more natural look than simply adding a stroke to a single shape because there is some variation in the thickness of the black layer. We’ll continue to use this technique for the major shapes in this illustration. You can go ahead and delete the guide rectangle.


Step 3

This shape needs a gradient. So, open up your gradients panel. Pick a gradient with two color stops, and proceed to modify it. Put the stops at opposite ends of the track and put the midpoint slider to about 40%. Double-click the first stop, on the left, choose the Swatches option, and choose the Red swatch. Set the second color stop to Mars Red. In the gradients menu in the upper left of the panel, hit the Save button. We’ll be using this gradient throughout the airplane’s body. Now, apply the gradient as shown to the shape you drew in Step 2.


Step 4

Now, we can begin the wings. Draw a wing shape on the near side of the airplane. Make the tip squareish, like the one shown.


Step 5

As we did for the fuselage, the wing will be composed of an outer shape and an inner shape. Draw the inner shape, leaving a very thin line of the outer shape showing along the front edge. Then, grab the red gradient that we saved in Step 3 and apply it to the wing as demonstrated.


Step 6

For the second wing, we go through the same process. Draw a black outer wing shape with the pen tool and then an inner wing. Apply the Red/Mars Red gradient to the wing so that it gets darker near the body of the airplane. Begin the gradient off the end of the wing and drag left, ending the gradient about two-thirds down the wing. Move these two objects behind the fuselage.


Step 7

The mouth of the plane comes next. This part is quite simple, but it has three parts to it. The first two are easy, we’ve been doing them for every part of the plane so far: an outer shape and an inner shape. Draw the outer shape and fill it black. Next, the inner shape. This time, fill it #333, or another very dark gray. This is how they should look. You can see that I left a part flat, because this is where the propeller is going to go. You can make it curved or leave it flat as you choose.


Step 8

We get to add a fun detail to the mouth now, another style of shadow. Draw a shape that is just a little larger than the black outer shape, so that it overlays the shape on the top and right, and just slightly on the left. Fill it Mars Red and move it backward twice to put it behind the other mouth layers.


Step 9

Let’s begin the tail now. Pan over to the tail by holding the spacebar and dragging. Grab the pen tool once again and draw the shape for the part of the tail nearest you. Then, draw the inner shape as well. Leave a thick outline on this one. Apply the Red/Mars Red gradient to the tail.


Step 10

Repeat the process for the upright tail fin and the little that you can see of the second tail fin. Since the second horizontal fin is barely peeking out from behind the plane, make it very stubby. Apply the gradient to the upright fin and fill the stubby fin with Mars Red. Move these four objects behind the fuselage.


Step 11

Pan over to the nose again. With the Pen Tool, draw a sort of blob here for the propeller. Make it blunt and rounded on the end. Fill it black, then make an inner shape. Open the gradients panel once again, and this time we get to use a different gradient! Select the White to Black gradient and set it to radial rather than linear. Apply it to the propeller head as shown.


Step 12

Now we get to add some interest to the body of the airplane with a shadow. Select the inner layer of the fuselage, copy it and go to Edit > Paste In Front to put it directly on top of the first one. Grab your Pencil Tool and start reshaping the top of it so it follows the contour of the plane the way a shadow would. It can take a while to get it just right. Use mine as a reference. When you’re done shaping the shadow, apply the Red to Mars Red gradient so the bottom is significantly darker.


Step 13

Select everything on your Artboard and group it. Then open up your layers panel and lock this group. Now, zoom out and take a look at your airplane. We’ve made some progress, and it’s looking good! Save your file before continuing. Unfortunately, we have quite a few details yet to go, and the details take quite some time! So, let’s get started with the accessories.


Step 14

One of the most necessary accoutrements to an airplane is its landing gear. We wouldn’t want anything to happen to this plane of ours, so let’s give it wheels. Start by taking the pencil tool and setting it to a 5pt, black basic stroke. Make two strokes just in front of the wings for our wheels to hang onto. Since there’s a thick outline on the fuselage we can start the stroke for the further wheel in the outline so it looks as though it’s behind the airplane. Also, note that the stroke on the left is very short.


Step 15

Now we get to start the wheels. This is a bit of a process, but it’s actually quite easy. Grab your EllipseTool. Make an Ellipse that is 45×90px and give it a 1 point black stroke. Grab the gradient tool and apply the White to Black radial gradient that we used for the propeller head. Using the gradient tool, squish the gradient into an ellipse so it fits the shape. Rotate the ellipse about -3 degrees.


Step 16

Holding down the Option key, hit the left arrow key to copy the shape and move it 1 point left. Then release the Option key and hit the left arrow key again so the second ellipse is 2 points away from the first one. Repeat this process with the second ellipse, copying it and moving it so the next shape is 2 points from the previous one. As you go, move every third ellipse up 1 point. Keep going until you have about 8 to 10 total ellipses. Select these ellipses and group them.


Step 17

The second wheel is similar, but it has a few differences. First of all, we start with an ellipse that is 50px wide and 83px tall. Then, rotate it about -18 degrees. Apply the White to Black radial gradient so it fits the shape and add a 1 point black stroke.


Step 18

Repeat step 16, but apply it to this wheel instead. Select this set of ellipses, group them, and move them so the centre of the top ellipse is at the point of the leg. You have now created your airplane’s tires!


Step 19

Go back to the first set of ellipses that you made. Copy the ellipse on the top of the stack using the method that we used for making the stack: hold down Option and hit the left arrow key. Keeping the proportions steady, resize this ellipse to about 80% of its original size. This is going to be the wheel, so centre it inside the next ellipse in the stack of tires. Do the same for the second wheel. This is what it should look like:


Step 20

Now we get to have some more fun with gradients. Open up your gradient panel and select the White to Black radial gradient. Put a white color stop at 55% and 85%. Leave the color stop on the far right black, and make the color stop on the far left Graphite. Hit the Save button in the gradient menu in the upper left corner of the panel. Select both of the ellipses you made in the previous step and select your new gradient from the gradient menu to apply it at the correct angles to these ellipses. Now your wheels are made, and we just need the hubs.


Step 21

With the pencil or pen tool, draw a blob-like shape to be the hub of the wheel. Fill it with Red. Hold down Option and hit the left arrow key to make a copy of this shape, release the Option key and hit the right arrow key to move it back on top of the first shape. With the Pencil Tool, reshape this hub to be a shadow for the first hub shape, similar to what we did with the airplane body. Make this shape Mars Red.


Step 22

For the other hub, simply make a small ellipse with a 1 point black stroke and rotate it about -18 degrees. Apply the White to Black radial gradient and put it behind the airplane’s leg. In your layers panel, select all the parts having to do with the wheels, hubs, tires and legs. Group the items.


Step 23

Now we need to make the antenna. Pan up to the top of the airplane. Grab your rounded rectangle tool and make a rectangle that is about 10 pixels wide and 80 pixels tall. Find a good corner radius by hitting the up and down arrow keys while holding the shape. Make the ends round like the one in the picture below. Apply the White to Black linear gradient to it.

Make a circle to sit on top of the antenna. It should be about 25 pixels in diameter. Give it a 1 point stroke and apply the same gradient to the circle.


Step 24

Make the engine comes next. With the pencil tool, draw a shape like the edge of a thick disk. Give it a 1.5 point black stroke and apply the White to Black linear gradient. Copy this shape twice by holding down the Option key and hitting the up arrow key. Align the shapes vertically, leaving a pixel or two of space in between the shapes. Select the three shapes and move them behind the fuselage so they look natural, as shown.


Step 25

To complete the engine, we need to cap it off with a larger shape. For this one, we’ll do an outer and inner shape, as we’ve done with all the major shapes. Start by making the outer shape with the pen tool and filling it black. Then, make the inner shape, also with the pen tool, and apply the White to Black linear gradient to it. As you can see, mine looks a little wobbly. That’s OK, because it fits in with the uneven style of the illustration. Select all the parts of the engine and antenna and group them.


Step 26

Zoom out and grab your brush tool. We’re going to put a couple highlights on the fuselage. Set the stroke color to white, the stroke opacity to 30%, and the stroke size to 0.5 pt. In the Artistic Ink brush library, choose the Tapered Stroke that’s tapered on both ends. Put a quick stroke near the nose and the tail as shown. Add these strokes to the wheels group in your Layers panel.


Step 27

In your Layers panel, unlock the airplane group. Select everything that’s on the canvas, group it, and lock the group. Name the groups as you like. Save your illustration before going on to the final section. We’re getting close to the finish!


Step 28

Now we can finally start the background! Grab your Rounded Rectangle tool and make a rectangle that’s 670px wide, 770 px tall and with a corner radius of 50px. Fill it with #6699CC and no stroke. Then, take the Shear tool and shear it to -170 degrees. Be sure to hold down the Shift key as you shear it so it only shears vertically.


Step 29

Select the large blue shape and move it to the back. Now, make a normal rectangle (no rounded corners) that’s about 750px wide and 50px tall and fill it #FDF6F2. Shear this one -25 degrees. Again, hold the Shift key while shearing. Move it behind the airplane but in front of the blue background shape.


Step 30

Make a large rectangle of the same color (#FDF6F2) that fills the canvas and move it to the back. Select the three shapes. In the Pathfinder panel, select Divide. Go into the group that this creates and fill the lower of the two blue shapes #336633. Exit the group.


Step 31

Open up the layers panel and unlock the airplane group. Copy the group, and lock the original, leaving the copy unlocked.

With the copy of the group selected, open the Pathfinder panel again. Hit Unite to make it a single shape. Set it to default color (black basic outline, white fill). Set the stroke to the same color as the background (#FDF2F6) and set it to 20 points. Move it behind the first airplane group.


Step 32

Now we get to have some fun. With the Pencil Tool, draw a little bolt of lightning like this. Copy the bolt of electricity twice and arrange them around the antenna like so.


Step 33

Make a text box in the lower right corner. Type Radio Control in all caps and set the font to Haettenschweiler. Make the font size 145 point and set the line height in the Type panel to 115. Make the text color #FDF2F6 and align it as shown.


Step 34

OK, you’re almost done. For the final effect, we have to take this over to Photoshop. Save your project. Now, save it as an Adobe PDF file and open it in Photoshop.

Once you’re in Photoshop, go to your Layers panel > Adjustments Menu and create a new pattern fill. In the pattern fill dialog box, open the Rock Patterns pattern library and choose the Rock Wall pattern. Set the Scale to 400% and hit OK. Looks great, right? Now you notice that this doesn’t look like an airplane; it just looks like an ugly texture. Let’s fix that. In your Layers panel, set the Blend Mode (Layer Mode) of the pattern to Overlay. This has a pretty shocking result, so fix that in turn by putting the layer opacity down to 10%. Now it looks much better.


Step 35

It still looks like something is missing. However, we can add a lot of impact with just a small step. In the Layers panel, right-click the pattern layer and duplicate it to this document. Then set the Blend Mode (Layer Mode) for this pattern layer copy back to Normal. This adds the texture in the light-colored parts and enhances the texture in the darker colors.


Conclusion

Save your file as a PDF. Believe it or not, we’re finally done! Congratulations! You have here a quality vector Retro RC Airplane poster with raster textures. Now that you’ve completed the tut using the set colors, why not try and make the poster sepia tone or black and white. Have fun!


Mysql Database Help

I am open to suggestions on how to do this. I want to add products/items into a database system. I want to use excel to manage a file like a CSV file add the additional items and re-upload the file using phpmyadmin.

Like I said, I’m open to suggestions on how to do this. I have looked at programs that will convert Excel to MySQL and all of that but I think those are way to hard to deal with because I don’t have all the info needed to connect to the server/database.

I’m not apposed to some kind of program/script to make this easy for me. I’m dealing with one single table from the database not the entire database.

Don’t tell me you’re ready to start this project, tell me what you’ll do for me and how easy this will be for me in the future. I don’t expect you to tell me how to do it or do anything without getting paid for the help or the info. Telling me you’re ready to go without some explanation on your part isn’t going to get you the job.

Create Site Backend Admin

I am looking for experienced persons or company in developing MYSQL Databases and admin sections for sites.

My site will be a whitelabel site and I require an admin section for:-

Whitelabel Network MAIN SITE
Freelancers where they can administer there account
Affiliates where they can edit their account
Webmasters where they can edit their account.

Basically the requirement is creating forms and interacting with MYSQL database.

Ideally programmed using OOP method but I am open to suggestions.

I would also like the Freelancers/ Webmasters/ Affiliates to also be able to use their login details to login to a forum (yet to be decided) which will be located at whitelabelfreelance.org.

I will provide more details to people that I feel are genuinely interested in the project.

I also create websites and am busy creating work for clients which is why i am outsourcing this which is my own project.

Please bid realistically!

Please ONLY provide examples of admin backend exampels ONLY any other kind of examples will be deleted.

Ilford Rugby Club

We are looking to create a website for www.ilfordrfu.co.uk
we are using http://www.pitchero.com/clubs/ilfordwanderersrfu/
and we want exactly the same level of admin as this on our own domain ilfordrfu.co.uk
as in the managers of the team have access and they can give a player access to some parts ie: uploading pictures.

its a complex site so i would urge you to create a login and see the site admin before quoting.
timescales are very important to us as we need it running asap
we have a windows based server running mysql at present
any questions then please do ask

Online Hotel Booking Engine

Online hotel booking component for a city/country destination travel portal.
Hotel managers have a complete property management interface including
– hotel/rooms/facilities description
– hotel/rooms/facilities photos
– hotel/rooms/facilities amenities
– maps
– setup unlimited room types
– rooms rates/availability
– rooms stay restrictions – minimum stay, close to arrival, close to departure
– special offers create

– on-line credit card processing, Paypal
– commission module
– booking reports, commission reports
– invoicing (verification/approval)

– guest reviews
– rating

As an example check http://www.joomloc.fr.nf/administrator/
– demo
– test

Please contact me for a more detailed description of the project.

Many thanks,
Valerie

Loading Data with Commands

It’s very common to load external data (such as SWF files) during runtime, but only when the data is completely loaded can we read or manipulate its content. Usually we have to listen to the complete event dispatched by a Loader or URLLoader object that loads the data for completion handling. Oftentimes, we write code that loads the data in one function, and write code that handles the completion of the loading in another function, but this can be improved by grouping the whole loading process together..

This tutorial demonstrates how to create a loading extension to the command framework in my previous tutorial, Thinking in Commands part 1 of 2, to pack the loading the completion handling into one place. This loading extension can also be combined with the scene management framework covered in Thinking in Commands part 2 of 2. Many classes used in this tutorial are covered in the previous tutorial, so I highly recommend that you read the previous tutorials before going on.

Additionally, this tutorial introduces the concept of data manager, a central “bank” that stores references to data objects. You can register data to the data manger with a unique key string, and later access the data by providing the corresponding key string. This spares you the trouble of keeping references of data objects and some variable scope issues.

By the way, you’ll need the GreenSock Tweening Platform in order to complete these examples.


Why Load Data with Commands?

Normally, we handle the loaded data inside the complete event listener function. This breaks apart two chunks of code that are logically connected. And by looking at the code, your flow of thought might be interrupted as your sight jumps from the loading function to the complete event listener.

Let’s look at the logic flow of a naive SWF loading approach.

The loader loads a SWF from a URL, and the onComplete() function is invoked by the dispatchEvent() method that dispatches a complete event, where the dispatchEvent() method is invoked internally by the loader. Well, actually, it’s invoked by the LoaderInfo object that belongs to the Loader object, but for simplicity, let’s just say the dispatchEvent() method is invoked by the Loader.

Next, within the onComplete() function, the doMoreStuff() function is invoked after the loading completion handling is done and, as the function’s name suggests, does more stuff.

The high-level logic flow is very linear: invoke the Loader.load() method first, onComplete() second, and doMoreStuff() third. However, as you’ll notice from the diagram, each function’s invocation is embedded within the function body of the previous one, resulting in a “nested” code. In my own opinion, if the logic flow of a certain functionality is linear, the associated code should be written in a linear manner, not nested. Otherwise, the code could sometimes become confusing if the invocation nest level is too high.

This is when the Command approach comes into play. From the diagram below, we can see that the code is pretty linear using commands, in that all the commands are linearly chained together by a serial command. Although the program “diverts” into the setProperties(), addChildLoader(), and doMoreStuff() functions; their invocation is linear.


Data Manager

Alright, before we get down to anything further about loading, let’s first take a look at the DataManager class. A data manager lets you associate a key string with a data object, and you can obtain a reference to this data object everywhere in your code. With the data manager, you don’t have to worry about keeping data references and variable scopes. All you have to do is register a piece of data to the manager with a key string.

The coding is pretty straightforward, as shown below:

package data {
	import flash.utils.Dictionary;

	public class DataManager {

		//a dictionary that maintains the string-data relations
		private static var _data:Dictionary = new Dictionary();

		//returns the data object associated with a key string
		public static function getData(key:String):* {
			return _data[key];
		}

		//registers a data object with a key string
		public static function registerData(key:String, data:*):void {
			_data[key] = data;
		}

		//unregisters a key string
		public static function unregisterData(key:String):void {
			delete _data[key];
		}

		//unregisters all key strings
		public static function clearData():void {
			for (var key:String in _data) {
				delete _data[key];
			}
		}
	}
}

So when we want to register a key string “myData” with a data object – say, a sprite – we could write the code as follows:

var sprite:Sprite = new Sprite();
DataManager.registerData("myData", sprite);

Later, anywhere in the code, we could write the following code to obtain a reference of the sprite and add it to a display list. It’s that simple, no more issues about maintaining object references and variable scopes.

var sprite:Sprite = DataManager.registerData("myData") as Sprite;
container.addChild(sprite);

Naive Loading Approach

Now let’s take a look at how the naive loading approach loads an external image. The loading code lies in one function and the completion handling code lies in another. We are going to load three images and add them to the stage when the loading is complete. Also, we’ll monitor the loading progress by listening to the progress events.


Step 1: Create a Flash Document

Open Flash and create a new Flash Document.

Step 2: Create a Progress Bar

Draw a progress bar on the stage; this is for representing the loading progress. Convert the entire progress bar into a symbol and give it an instance name of “progressBar_mc”. Within the progress bar symbol, convert the inner progress bar into another symbol, and give it an instance name of “innerBar_mc”.


Step 3: Prepare the Images

Place three images in the same folder as the FLA file, named “image1.jpg”, “image2.jpg”, and “image3.jpg”. Here’s what the three images look like.


Step 4: Create the Document Class

Create a new AS file for the document class for the FLA file. The code is pretty straightforward, and all the details are explained in the comments. First, three loaders are created and the loading begins. On each progress event, the progress bar is updated. When the loading is complete, the progress bar fades out and the three images fade in one-by-one.

package {
	import com.greensock.TweenMax;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;

	public class NaiveLoading extends MovieClip {

		private var loader1:Loader;
		private var loader2:Loader;
		private var loader3:Loader;

		public function NaiveLoading() {

			//shrink progress bar to zero scale
			progressBar_mc.innerBar_mc.scaleX = 0;

			//create loaders
			loader1 = new Loader();
			loader2 = new Loader();
			loader3 = new Loader();

			//add progress listeners
			loader1.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
			loader2.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
			loader3.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);

			//add completion listeners
			loader1.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			loader2.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			loader3.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);

			//start loading
			loader1.load(new URLRequest("image1.jpg"));
			loader2.load(new URLRequest("image2.jpg"));
			loader3.load(new URLRequest("image3.jpg"));
		}

		private function onProgress(e:ProgressEvent):void {

			//calculate total bits to load
			var bytesTotal:uint = 0;
			bytesTotal += loader1.contentLoaderInfo.bytesTotal;
			bytesTotal += loader2.contentLoaderInfo.bytesTotal;
			bytesTotal += loader3.contentLoaderInfo.bytesTotal;

			//calculate total bits loaded
			var bytesLoaded:uint = 0;
			bytesLoaded += loader1.contentLoaderInfo.bytesLoaded;
			bytesLoaded += loader2.contentLoaderInfo.bytesLoaded;
			bytesLoaded += loader3.contentLoaderInfo.bytesLoaded;

			//update progress bar scale
			progressBar_mc.innerBar_mc.scaleX = bytesLoaded / bytesTotal;
		}

		private var _completeCount:int = 0;
		private function onComplete(e:Event):void {
			_completeCount++;
			if (_completeCount < 3) return;

			//remove progress listeners
			loader1.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
			loader2.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
			loader3.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);

			//remove completion listeners
			loader1.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
			loader2.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
			loader3.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);

			var image1:DisplayObject = loader1.content;
			var image2:DisplayObject = loader2.content;
			var image3:DisplayObject = loader3.content;

			//adjust loaded image positions
			image1.x = 30, image1.y = 30;
			image2.x = 230, image2.y = 30;
			image3.x = 430, image3.y = 30;

			//add loaded images to display list
			addChild(image1);
			addChild(image2);
			addChild(image3);

			//fade out progress bar
			TweenMax.to(progressBar_mc, 0.5, {autoAlpha:0, blurFilter:{blurX:20, blurY:20}});

			//fade in loaded images
			TweenMax.from(image1, 0.5, {delay:0.5, alpha:0, blurFilter:{blurX:20, blurY:20}});
			TweenMax.from(image2, 0.5, {delay:0.7, alpha:0, blurFilter:{blurX:20, blurY:20}});
			TweenMax.from(image3, 0.5, {delay:0.9, alpha:0, blurFilter:{blurX:20, blurY:20}});
		}
	}
}

Step 5: Test the Movie

Press CTRL+ENTER to test the movie. You’ll see that the progress bar immediately fades out and the three images fade in. That is because the images are local files, meaning they can be loaded almost immediately. To simulate online download speed, first select the View > Download Settings > DSL as the simulated download speed, and then press CTRL+ENTER again without closing the test window to start simulating online downloading. This time you shall see the progress grow progressively wider before it fades out.

Okay, it’s time to load the images with the command framework.


Utility Commands

Before we proceed, let’s create some utility commands that will be used later in the example. Again, these command classes are based on the command framework presented in my previous tutorial (Part 1), and I highly recommend that you go through them before going on. If you’ve read the tutorial before, you can always head back if you need your memory refreshed.

Data Managers Commands

Here we are going to create two commands for registering and unregistering data for the data manager class. The RegisterData command registers data to the manager, while the UnregisterData command unregisters data.

package commands.data {
	import commands.Command;
	import data.DataManager;

	//this command registers data to the data manager
	public class RegisterData extends Command {

		public var key:String;
		public var data:*;

		public function RegisterData(key:String, data:*) {
			this.key = key;
			this.data = data;
		}

		override protected function execute():void {
			DataManager.registerData(key, data);
			complete();
		}
	}
}
package commands.data {
	import commands.Command;
	import data.DataManager;

	//this command unregisters data from the data manager
	public class UnregisterData extends Command {

		public var key:String;

		public function UnregisterData(key:String) {
			this.key = key;
		}

		override protected function execute():void {
			DataManager.unregisterData(key);
			complete();
		}
	}
}

The LoaderLoad Command

This command encapsulates a Loader instance’s load() method. You may provide an onProgress command that is executed upon each progress event and an onComplete executed when the loading is complete. Note that the complete() method is invoked when the loading is complete. This line of code is extremely crucial. If you do not invoke the method, the command will never be regarded as complete, jamming your entire application in the worst case scenario.

package commands.loading {
	import commands.Command;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;

	public class LoaderLoad extends Command {

		public var loader:Loader;
		public var url:URLRequest;
		public var context:LoaderContext;

		public var onProgress:Command;
		public var onComplete:Command;

		public function LoaderLoad(loader:Loader, url:URLRequest, context:LoaderContext = null, onProgress:Command = null, onComplete:Command = null) {
			this.loader = loader;
			this.url = url;
			this.context = context;
			this.onProgress = onProgress;
			this.onComplete = onComplete;
		}

		override protected function execute():void {

			//add listeners
			loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressListener);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeListener);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadingComplete);

			//start loading
			loader.load(url, context);
		}

		private function loadingComplete(e:Event):void {

			//remove listeners
			loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, progressListener);
			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, completeListener);
			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadingComplete);

			complete();
		}

		private function progressListener(e:ProgressEvent):void {

			//execute the onProgress command
			if (onProgress) onProgress.start();
		}

		private function completeListener(e:Event):void {

			//execute the onComplete command
			if (onComplete) onComplete.start();
		}
	}
}

The InvokeFunction Command

This command encapsulates the invocation of another function. It is designed to allow you to provide an extra parameter array for the function to be invoked.

package commands.utils {
	import commands.Command;

	//this command invokes a function
	public class InvokeFunction extends Command{

		public var func:Function;
		public var args:Array;

		public function InvokeFunction(func:Function, args:Array = null) {
			this.func = func;
			this.args = args;
		}

		override protected function execute():void {
			func.apply(null, args);
			complete();
		}
	}
}

That’s it. Time for the example.


Step 1: Copy the Flash Document File

Copy the FLA file from the previous example to a new folder and copy the image files along with it.


Step 2: Create the Document Class

Create a new AS file for the document class of the copied FLA file, named “LoadingDataWithCommands”. Remember to change the document class name in the FLA file to this new one.

The code for the document class is pretty clean. It simply sets the current scene to a LoadingScene with a scene manager. We are using the scene framework presented in my previous tutorial (Part 2). You can check it out if you’ve forgotten how to use it.

package  {
	import flash.display.MovieClip;
	import scenes.SceneManager;

	public class LoadingDataWithCommands extends MovieClip {

		public function LoadingDataWithCommands() {

			var sceneManager:SceneManager = new SceneManager();
			sceneManager.setScene(new LoadingScene(this));
		}
	}
}

There are two scenes in total. The LoadingScene loads the images and updates the progress bar. After the loading is complete, the scene transits to the MainScene, which fades in the loaded images.


Step 3: The Loading Scene

Extend the Scene class to create a new class named LoadingScene. The container property holds a reference to the main sprite. This allows us to access the progress bar later.

package {
	import scenes.Scene;

	public class LoadingScene extends Scene {

		private var container:LoadingDataWithCommands;

		public function LoadingScene(container:LoadingDataWithCommands) {
			this.container = container;
		}
	}
}

Now, create the intro command for the loading scene. The intro will create three loaders and begin the loading process. This is done by overriding the createIntroCommand() method. The following code goes into the class body, same as the constructor.

//the intro command begins the loading of the three images
override public function createIntroCommand():Command {
	var loader1:Loader = new Loader();
	var loader2:Loader = new Loader();
	var loader3:Loader = new Loader();

	var command:Command =
		new ParallelCommand(0,

			//shrink the progress bar to zero scale
			new SetProperties(container.progressBar_mc.innerBar_mc, {scaleX:0}),

			//loading-related commands executed in series
			new SerialCommand(0,

				//registers the three loaders to the data manager
				new ParallelCommand(0,
					new RegisterData("loader1", loader1),
					new RegisterData("loader2", loader2),
					new RegisterData("loader3", loader3)
				),

				//start three loading commands in parallel
				new ParallelCommand(0,
					new LoaderLoad(
						loader1, new URLRequest("image1.jpg"), null,
						new InvokeFunction(onProgress) //onProgress command
					),
					new LoaderLoad(
						loader2, new URLRequest("image2.jpg"), null,
						new InvokeFunction(onProgress) //onProgress command
					),
					new LoaderLoad(
						loader3, new URLRequest("image3.jpg"), null,
						new InvokeFunction(onProgress) //onProgress command
					)
				)
			)
		);

	return command;
}

Next, override the onSceneSet() method. This method is invoked when the intro command is complete, indicating that the loading is complete. Within this method, we tell the scene manager to transit to the main scene. Before the scene transition, the outro command is executed first.

override public function onSceneSet():void {
	sceneManager.setScene(new MainScene(container));
}

And then override the createOutroCommand. This command shall fade out the progress bar.

//the outro command fades out the progress bar
override public function createOutroCommand():Command {
	var command:Command =
		new SerialCommand(0,

			//fade out progress bar
			new TweenMaxTo(container.progressBar_mc, 0.5, {autoAlpha:0, blurFilter:{blurX:20, blurY:20}}),

			//remove progress bar from display list
			new RemoveChild(container, container.progressBar_mc)
		);

	return command;
}

Finally, create the onProgress method invoked by the InvokeFunction commands.

private function onProgress():void {

	//retrieve loader references from the data manager
	var loader1:Loader = DataManager.getData("loader1") as Loader;
	var loader2:Loader = DataManager.getData("loader2") as Loader;
	var loader3:Loader = DataManager.getData("loader3") as Loader;

	//calculate total bits to load
	var bytesTotal:uint = 0;
	bytesTotal += loader1.contentLoaderInfo.bytesTotal;
	bytesTotal += loader2.contentLoaderInfo.bytesTotal;
	bytesTotal += loader3.contentLoaderInfo.bytesTotal;

	//calculate total bits loaded
	var bytesLoaded:uint = 0;
	bytesLoaded += loader1.contentLoaderInfo.bytesLoaded;
	bytesLoaded += loader2.contentLoaderInfo.bytesLoaded;
	bytesLoaded += loader3.contentLoaderInfo.bytesLoaded;

	//update progress bar scale
	container.progressBar_mc.innerBar_mc.scaleX = bytesLoaded / bytesTotal;
}

Step 4: The Main Scene

Now create a new class for the main scene, extending the Scene class.

package {
	import scenes.Scene;

	public class MainScene extends Scene {

		private var container:LoadingDataWithCommands;

		public function MainScene(container:LoadingDataWithCommands) {
			this.container = container;
		}
	}
}

Override the createIntroCommand() method. This method will add the loaders to the display list, and fade them in one-by-one. In addition, the data key strings are unregistered from the data manager.

override public function createIntroCommand():Command {

	//retrieve loader references from the data manager
	var loader1:Loader = DataManager.getData("loader1") as Loader;
	var loader2:Loader = DataManager.getData("loader2") as Loader;
	var loader3:Loader = DataManager.getData("loader3") as Loader;

	var command:Command =
		new ParallelCommand(0,

			//loaded-image-handling commands
			new SerialCommand(0,

				//adjust loaded image positions
				new ParallelCommand(0,
					new SetProperties(loader1, {x:30, y:30}),
					new SetProperties(loader2, {x:230, y:30}),
					new SetProperties(loader3, {x:430, y:30})
				),

				//add loaded images to display list
				new ParallelCommand(0,
					new AddChild(container, loader1),
					new AddChild(container, loader2),
					new AddChild(container, loader3)
				),

				//fade in loaded images
				new ParallelCommand(0,
					new TweenMaxFrom(loader1, 0.5, {alpha:0, blurFilter:{blurX:20, blurY:20}}),
					new TweenMaxFrom(loader2, 0.5, {delay:0.2, alpha:0, blurFilter:{blurX:20, blurY:20}}),
					new TweenMaxFrom(loader3, 0.5, {delay:0.4, alpha:0, blurFilter:{blurX:20, blurY:20}})
				)
			),

			//unregsiter data from the data manager
			new ParallelCommand(0,
				new UnregisterData("loader1"),
				new UnregisterData("loader2"),
				new UnregisterData("loader3")
			)
		);

	return command;
}

Step 5: Test the Movie

Alright. We’re done! Test the movie and simulate online downloading. You will see the exact same result as in the previous example, but this time it’s all done with the command framework and the scene framework.


Summary

In this tutorial, I’ve shown you how to load external images with the command framework. The LoaderLoad command can be used to load external SWF files, too. Moreover, you can create your own commands to load external data other than images and SWF files, by encapsulating the URLLoader class into your commands.

We’ve written more code in the second example than the first one. Remember, the purpose of using the command framework and the scene framework is not to achieve the same result with less code, but to manage the code in a systematic and modular approach, making your life easier when it comes to future maintenance and modification.

The first example squeezes all the code into one single class, making it difficult for future maintenance if the code amount should grow extremely large. The second example, on the other hand, separates logically independent code into different scenes, making it easier for future modification. Also, by integrating with the command framework and the scene framework, we’ve made room for future extension, where we can add more scenes and intro/outro commands without disrupting irrelevant code.

This is the end of this tutorial. I hope you enjoyed it. Thanks for reading!

Clegg ‘disappointed’ at results

Nick Clegg

Nick Clegg has acknowledged the Liberal Democrats have had a "disappointing night", despite his pre-election poll surge in the wake of the TV debates.

Mr Clegg, who said during the campaign it had turned into a "two-horse race" between his party and the Tories, may end up with fewer seats than 2005.

As he was returned as MP for Sheffield Hallam, Mr Clegg said: "We simply haven’t achieved what we had hoped."

He urged no rushed decisions if, as expected, there is a hung parliament.

Mr Clegg, who retained his seat with an increased majority, but high profile Lib Dem MPs Lembit Opik and Evan Harris lost their seats.

‘Positive campaign’

With most results in, the Lib Dem vote is up 0.9% on 2005, Labour down 6.5% and the Conservatives up 4%.

Mr Clegg said: "This has obviously been a disappointing night for the Liberal Democrats. We simply haven’t achieved what we had hoped. I’m nonetheless proud of the way we conducted the campaign.

"I think we conducted a positive campaign, full of hope, full of optimism, which I think did engage a lot of people in the election campaign, even if they didn’t then go on to vote for the Liberal Democrats."

The Conservatives look set to be the biggest party but short of an overall majority – and Britain’s first hung parliament in Britain for more than three decades is predicted.

Downing Street sources have indicated Gordon Brown will seek to open coalition talks with the Lib Dems. But Mr Clegg said everyone should "take a little time so that people get the good government that they deserve in these very difficult and uncertain times".

"Clearly the final election result is still a little unpredictable, people have voted but no one appears to have won emphatically," said Mr Clegg.

"I don’t think anyone should rush into making claims or taking decisions which don’t stand the test of time. I think it would be best if everybody were just to take a little time, so that people get the good government that they deserve in these very difficult and uncertain times."

But he said his party would be "guided by the values and the principles on which we fought this election" – fairness, responsibility in providing stability and growth to an economy and "real change to the way we do politics".

He also expressed dismay at voters who were turned away from polling stations which could not cope with increased turnout: "That should never, ever happen again in our democracy."

This article is from the BBC News website. © British Broadcasting Corporation, The BBC is not responsible for the content of external internet sites.

First hung parliament for decades

David Cameron

The Conservatives have won the most MPs in the UK general election but fallen short of a majority, leading to the first hung parliament since 1974.

As counting continues the Tories have gained 92 seats, Labour have lost 86 and the Lib Dems six, despite hopes of a breakthrough for the third party.

The battle is now under way to see which leader can form a government.

Lib Dem leader Nick Clegg said the situation was "fluid" but the Tories had the first right to seek to govern.

Arriving back at Lib Dem headquarters in London, he said: "It is vital that all parties, all political leaders, act in the national interest and not out of narrow party political advantage."

He said he "stuck by" his view that the party with the biggest mandate – in terms of votes and seats – should have the right to seek to govern first. "It seems this morning, that it’s the Conservative Party that has more votes and more seats though not an absolute majority.

"I think it’s now for the Conservative Party to prove that it’s capable of seeking to govern in the national interest."

David Cameron has said Gordon Brown had "lost his mandate". Mr Brown said "stable, strong" government was needed.

The Tories have won 290 seats so far but it is now not possible for them to reach the 326 seats needed to win an overall majority.

Civil service

Mr Brown, whose party has 247 seats so far, has returned to Downing Street with aides and may turn to Nick Clegg’s Lib Dems, who have so far won 51 seats, to try to form a coalition government.

Downing Street has authorised the civil service to support other parties in hung parliament negotiations – essentially giving the go-ahead for talks to begin.

It means the Conservatives and the Lib Dems will be able to call on support from the civil service on policy or logistics.

The BBC projection suggests David Cameron’s Conservatives will have 306 seats. If there are 10 Unionists elected in Northern Ireland then Mr Cameron might be able to command 316 – probably still slightly too few for him to be sure of winning a Queen’s Speech.

But Labour and the Lib Dems together would have 317 seats, according to the BBC figures, which even with three SDLP MPs would still leave them at 320 – again a few votes short of a majority

In other election night news:

Northern Ireland’s first minister and DUP leaderinEast Belfastby the Alliance party TheGreens gained their first MPat Westminster – party leader Caroline Lucas inBrighton PavillionEducation secretary Ed Balls hung on inMorley and Outwoodby just over 100 votes but former Home Secretary Charles Clarke narrowly lost to the Lib Dem candidate inNorwich SouthJacqui Smith, who stood down as home secretary over her expenses,lost her Redditch seat to the Conservativebut Hazel Blears retained her seat in Salford Labour’s Margaret Hodge beat the BNP’s Nick GriffinMargaret Hodge beat the BNP’s Nick GriffininBarking and Dagenham,with a 5% increase in her vote Esther Rantzen came fourth in Luton South, which went to the Labour candidate Lib Dem frontbencher Lembit Opik has lost his Montgomeryshire seat after suffering a 13.2% swing to the Conservatives There were angry scenes and calls for an inquiry after people wereturned away from polling stationsas long queues formed ahead of the 2200 BST voting deadline.

Senior Labour figures have said that under the rules of Britain’s constitution, the sitting prime minister in a hung parliament makes the first attempt at forming a ruling coalition.

Business Secretary Lord Mandelson said Mr Brown had returned to Number 10, and was going to rest and "catch his breath" adding: "We have to be patient for some time more."

"It’s not possible to make definite claims or reach final conclusions about the outcome of the election because there are results still to come in," he said.

"You could say the electorate have voted for change but what they haven’t done is voted decisively in favour of the Conservatives."

Asked if it would be "inconceivable" to have a Labour minority or coalition government which did not have Gordon Brown as prime minister, Lord Mandelson said: "Frankly there are quite a number of permutations."

But he added it was "premature" to "start getting into hypotheses".

Shadow schools secretary Michael Gove said voters would not be "entirely happy" if Mr Brown "after a defeat like this, were to try to cling on and try to form some sort of coalition of the defeated, some sort of alliance of the dispossessed".

He said: "David Cameron has secure a larger number of votes and a larger share of the votes than Tony Blair secured in 2005 when he became prime minister. The logical next step is for David Cameron to form a Conservative-led government."

Gordon Brown

Mr Clegg – whose party have not performed as well as expected after a poll surge for the Lib Dems after the first live TV debate – cautioned other leaders against "rushing into making claims or taking decisions" which did not stand the test of time.

He urged everyone involved to "take a little time" to ensure people got the government they deserved during these "difficult times".

But he admitted it had been a "disappointing night" for the Lib Dems.

The Conservatives are predicted to take 297 seats in England, with Labour on 194 and the Lib Dems on 41. The Tories have also made significant gains in Wales – where Labour also regained their former stronghold Blaenau Gwent – but the Lib Dems and Plaid Cymru failed to gain target seats.

But in Scotland the Tories failed to make a significant breakthrough, while the Labour vote held up, with the party re-taking two seats it lost in by-elections – Glasgow East and Dunfermline and West Fife. The SNP and Lib Dems fell short of their targets.

Northern Ireland’s First Minister, DUP leader Peter Robinson lost his seat in the first shock result of the night. The other main unionist leader – the UUP’s Sir Reg Empey, was also defeated in South Antrim.

With 17 of 18 Westminster seats declared – the DUP have eight, Sinn Fein have four, the SDLP have three, the Alliance Party has one and one has gone to an independent.

This article is from the BBC News website. © British Broadcasting Corporation, The BBC is not responsible for the content of external internet sites.

BA cabin crew reject ‘new offer’

BA planes at Heathrow

British Airways will learn later whether it faces a renewed threat of industrial action by cabin crew as fresh ballot results are announced.

Thousands of Unite union members have voted on a new offer aimed at ending a long-running row over pay and conditions, which BA says is "fair".

But Unite has "strongly recommended" its members reject the offer, raising the possibility of more strikes.

Cabin crew strikes in March led to widespread disruption for passengers.

Costly delays

The airline said the seven days of industrial action had cost it up to £45m.

Further disruption to flights caused by ash from the Icelandic volcano in April cost it an additional £180m.

Tony Woodley, joint leader of Unite, said in a letter to cabin crew that BA was treating staff like second-class citizens who had been "branded" for going on strike.

He said the union was urging rejection of the new offer because BA had failed to restore travel perks taken away from those who went on strike and disciplinary action was being taken against more than 50 union members.

"The charges in the great majority of cases are entirely trivial and barely worthy of a slap on the wrist, let alone the sack," he said.

He added that he had made it clear to members that rejecting the offer could mean them having to "take a stand" against BA again.

Mr Woodley also said Unite had lost trust in BA’s commitment to finding a solution to the dispute.

"By their actions and behaviour throughout the dispute, and continuing to this day, it is impossible to take BA management’s words at their face value," he said.

‘Gross misconduct’

BA said it had put a "fair offer" to Unite that addressed all the concerns raised during the past 14 months of negotiations.

"It offers our cabin crew the assurances they have been asking for, and so we are asking them to accept the proposal and put this dispute behind us," its spokesman said.

The ballot result comes a day after Duncan Holley, a leading union official at BA, claimed he was sacked for gross misconduct for taking time off work before Christmas to carry out union duties.

The Unite branch secretary said his dismissal after 12 years was "politically motivated". BA said it would not comment on individual disciplinary cases.

This article is from the BBC News website. © British Broadcasting Corporation, The BBC is not responsible for the content of external internet sites.