text:
CanadaVOTES: Animal Alliance (AAEVPC) party leader Liz White running in Toronto Centre

October 1, 2008

On October 14, 2008, Canadians will be heading to the polls for the federal election. Animal Alliance Environment Voters Party of Canada leader Liz White is standing for election in the riding of Toronto Centre.

Once the director of the Toronto Humane Society, she has been with the Animal Alliance Canada organization since the 1980s. She is currently a full time staff member and Director, working on legislative and media matters, as well as fundraising. According to her biography on their website, "her primary issues include Municipal Animal Control by-law matters, endangered species legislation and hunting issues." White herself is a vegetarian and advocates a vegetarian lifestyle.

Wikinews contacted Liz, to talk about the issues facing Canadians, and what they and their party would do to address them. Wikinews is in the process of contacting every candidate, in every riding across the country, no matter their political stripe. All interviews are conducted via e-mail, and interviews are published unedited, allowing candidates to impart their full message to our readers, uninterrupted.

This is the first election that the party is running multiple candidates; in the 2006 federal election, only Ms. White was listed.

Riding incumbent and prominent Liberal Bob Rae, once the NDP premier of Ontario, is defending the riding versus many candidates. Beside Liz White, they are El-Farouk Khaki (NDP), Ellen Michelson (Green), David Gentili (Conservative), Johan Boyden (Communist), Philip Fernandez (Marxist-Leninist), and independent Gerald Derome.

For more information, visit the campaign's official website, listed below.

Interview
Why are you running for political office, why at the federal level, why this party, and why in this riding?
 * The Animal Alliance Environment Voters Party of Canada was formed because of a Supreme Court ruling which prevented "third parties" (not registered political parties) from speaking out effectively at election time. Prior to the ruling, Animal Alliance's political arm Environment Voters participated as a third party in federal, provincial and municipal election campaigns. After the ruling, the only way we could participate effectively within the law was to become a federally registered political party which we did.

 * The Animal Alliance Environment Voters Party of Canada was formed to bring forward the principle of just and equitable human progress that respects, protects and enhances the environment upon which we all depend and the lives of the animals with whom we share our world.

 * I am running in Toronto Centre because I live there and because there are significant environmental and animal protection issues to be addressed. The Don River, a significant watershed runs parallel to the riding.  The re-naturalization of the Don River lands has progressed but the river remains a source of pollution which affects wildlife and the environment. My riding also touches the lake and we have been promoting the re-naturalization of the shoreline, an important ecological initiative. My riding is close to Tommy Thompson Park which hosts a large and ecologically significant waterbird colony with Black-crown Night Herons, Double-crested Cormorants and colony of 30,000 gulls.  We have an active campaign to defend cormorants, Canada geese and other birds against government sponsored culls. Finally, consideration is being given to the removal of the Gardiner Expressway and the re-naturalization of the lands below the off and on ramps. My riding presents significant opportunities to reclaim biological diversity, create wildlife corridors, to address and prevent human wildlife conflict and to re-naturalize habitat long lost to industrial use.

'''Previous to this campaign, have you been politically involved? How will you apply your previous work/volunteer/life experience to serving your constituents?'''
 * I have been involved in politics, advocating for the environment for over 30 years and for animals for over 20 years. In addition, I volunteered as a board member to a legal clinic specializing in poverty law and as a co-chair for a non-profit group that raised money and advocated for a native community in northern Alberta.  My experience positions me to fulfill our mandate which is to fight for a just and equitable society that respects and protects humans, animals and the environment.

'''As you campaign around your riding, it's likely that some issues are mentioned more often by voters than other issues. What would you say are the three hottest topics this election, in your riding? What would you and your party do to address these issues?'''
 * My approach to campaigning is to highlight and discuss the plight of the environment and the animals with whom we share the planet. So the voters tend not to ask my position on other issues.

Is there any misconceptions about you, your leader, or your party and platform?
 * Yes, the misconceptions is that we are referred to as a fringe party. Nothing could be further from the truth. We are the party of new ideas, a party of vision. Granting women the right to vote was considered a radical initiative as expressed in the article “Human Rights in Canada, A Historical Perspective”: “The men in control of the country perceived women as a ‘weaker sex’ needing protection and guidance. Some believed allowing women to vote would only unsettle them and lead to family discord.” However, with political pressure brought about by women of the time, the laws changed.

 * Again as the article describes, “Times are about to change. A generation of women – led by dynamos like Nellie McClung, Emily Murphy, Ada Powers, Josephine Dandurand and Elizabeth Smith Shortt – have lobbied, cajoled, heckled, and ridiculed politicians for denying them their rights. They collected petitions, held rallies, and fought to have their voices heard.” The Animal Alliance Environment Voters Party of Canada raises issues about the environment and animal protection that other parties fail to discuss either in elections or during the legislative agenda.  We are the Nellie McClungs of the environmental and animal protection world.

'''There are more ways than ever to get your message out, from the traditional campaign fliers and lawn signs, to new media like websites, Facebook, and YouTube. The tried-and-true routes get the message out to the masses much easier, but digital alternatives are much more measurable in how many are seeing or interacting with your campaign. What seems to be the most effective, from your experience?'''
 * We have our television ad on YouTube; however, I do not know how to measure the effectiveness other than it provides much broader access. It is hard to tell how many voters in my particular riding are accessing the ad.


text:
Talk:CanadaVOTES: Animal Alliance (AAEVPC) candidate Marie Crawford running in Toronto—Danforth

RAW TEXT
Hi Nick,

Here are my replies to the questions you have passed to our party - Thanks much for including our candidates!

Marie>>

Why are you running for political office, why at the federal level, why this party, and why in this riding?

I am running for political office because I am confident that I can represent the positive ideals that many people in this riding share. I have lived in Toronto-Danforth for 16 years, and have owned and operated a restaurant in the area for 9 years. There are many people here that appreciate and respect other animals and and to see more done to reduce humans' impact on the environemt and have a safe, respectful future for their children. Things like banning plastic bags and eliminating takeout cups and packaging would be welcome ways to help people reduce their impact on the environment.

Running at a Federal Level cannot address all of those issues mentioned above, but other issues can, like amending the Criminal Code to increase penalties for animal abusers, ending the Canadian seal hunt and shedding light on the fact that animal factory farming practices are the number one contributing factor to climate change - a fact that is repeatedly swept under the rug.

I have been a part of Animal Alliance - the founder of the AAEVPC - for 15 years. The manner in which we have been trying to change laws to protect animals (years and years of lobbying and empty promises from politicians) has not been effective, so I was eager to be a candidate once the party was formed so I could make real change for animals if elected, and certainly raise awareness in the meantime.

Previous to this campaign, have you been politically involved? How will you apply your previous work/volunteer/life experience to serving your constituents?

I have worked on several election campaigns for a couple of noteable politicians, and Aimal Alliance in itself is a legislative organization that I have been a part of for many years. I firmly believe that government reps are not "us or them", but people who should ultimately care about what is best for the people who have elected and put their faith in them to do what is best for all. These days, government has become more about greed, and many politicians have compromised their own ethics to simply get votes. I believe I am capable of leading by positive example and truly bringing a compassionate and respectful type of representation in this riding.

As you campaign around your riding, it's likely that some issues are mentioned more often by voters, than other issues. What would you say are the three hottest topics this election, in your riding? What would you and your party do to address these issues?

Part of my campaigning is to ultimately embrace positive activities and foster a greater sense of compassion in people. By doing so, compassion for other animals and respect for eachother and the environment will surely follow. Ultimately, this form of representation has no boundaries. In this riding we have many people opposed to the "big "box" stores moving in to the area, of which I would actively attempt to allow only smaller family or entrepreneur-owned businessed to move in to the area. We also have the Leslie Spit, which includes a bird sanctuary that must continue to be protected.

Is there any misconceptions about you, your leader, or your party and platform?

Strangely, some people still react to the "Animal Protection" platform like it's a scary term. - I even get suggestions that we should change the name so that the "Animal" part gets dropped. But once I continue to speak further with people, and they largely agree that the current Criminal Code is too weak when it comes to animal abusers, and agree that animals used for food must be treated humanely, and their own cat or dog is twirling around their feet and I can remind them that they probably care about other animals just as much as our party does and that we're just trying to work on their behalf, well, they become interested listeners and agree that animals are largely forgotten on a government level

>> There are more ways than ever to get your message out, from the traditional campaign fliers and lawn signs, to new media like websites, Facebook, and YouTube. The tried-and-true routes get the message out to the masses much easier, but digital alternatives are much more measurable in how many are seeing or interacting with your campaign. What seems to be the most effective, from your experience?

With such little time to really get media and material going in this election, I can't say for sure at this time. Perhaps we will see what's been most effective after the election!

Thanks so much for your questions, Nick. Feel free to contact me if you have any further questions.

Sincerely,

Marie Crawford Candidate, Animal Alliance Environment Voters Party of Canada Toronto-Danforth mariecrawford@sympatico.ca (416) 465-8223

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
CanadaVOTES: Animal Alliance (AAEVPC) candidate Marie Crawford running in Toronto—Danforth

October 2, 2008

On October 14, 2008, Canadians will be heading to the polls for the federal election. Animal Alliance Environment Voters Party of Canada candidate Marie Crawford is standing for election in the riding of Toronto—Centre.

Marie is a Director of Animal Alliance of Canada, a separate but related organization. She volunteers her time for Animal Alliance, but unlike party leader Liz White, does not work out of their office.

Wikinews contacted Marie, to talk about the issues facing Canadians, and what they and their party would do to address them. Wikinews is in the process of contacting every candidate, in every riding across the country, no matter their political stripe. All interviews are conducted over e-mail, and interviews are published unedited, allowing candidates to impart their full message to our readers, uninterrupted.

The incumbent in this riding is National Democratic Party (NDP) leader Jack Layton. Other than Crawford, trying for the riding are Liberal Andrew Lang, Sharon Howarth (Green), and Christina Perreault (Conservative), Marcell Rodden (Marxist-Leninist), and Bahman Yazdanfar (Canadian Action Party), and independent John Richardson. The riding has existed federally since 1979, and has the seat has been occupied by Bob Rae (NDP, 1979–1982), Lynn McDonald (NDP, 1982–1988), Dennis Mills (Liberal, 1988–2004), and Layton (NDP, 2004 to present).

For more information, visit the campaign's official website, listed below.

Interview
Why are you running for political office, why at the federal level, why this party, and why in this riding?

 * I am running for political office because I am confident that I can represent the positive ideals that many people in this riding share.  I have lived in Toronto-Danforth for 16 years, and have owned and operated a restaurant in the area for 9 years.  There are many people here that appreciate and respect other animals and and [sic] to see more done to reduce humans' impact on the environemt [sic] and have a safe, respectful future for their children.  Things like banning plastic bags and eliminating takeout cups and packaging would be welcome ways to help people reduce their impact on the environment.

 * Running at a Federal Level cannot address all of those issues mentioned above, but other issues can, like amending the Criminal Code to increase penalties for animal abusers, ending the Canadian seal hunt and shedding light on the fact that animal factory farming practices are the number one contributing factor to climate change - a fact that is repeatedly swept under the rug.

 * I have been a part of Animal Alliance - the founder of the AAEVPC - for 15 years. The manner in which we have been trying to change laws to protect animals (years and years of lobbying and empty promises from politicians) has not been effective, so I was eager to be a candidate once the party was formed so I could make real change for animals if elected, and certainly raise awareness in the meantime.

'''Previous to this campaign, have you been politically involved? How will you apply your previous work/volunteer/life experience to serving your constituents?'''
 * I have worked on several election campaigns for a couple of noteable [sic] politicians, and Aimal Alliance in itself is a legislative organization that I have been a part of for many years. I firmly believe that government reps are not "us or them", but people who should ultimately care about what is best for the people who have elected and put their faith in them to do what is best for all.  These days, government has become more about greed, and many politicians have compromised their own ethics to simply get votes.  I believe I am capable of  leading by positive example and truly bringing a compassionate and respectful type of representation in this riding.

'''As you campaign around your riding, it's likely that some issues are mentioned more often by voters, than other issues. What would you say are the three hottest topics this election, in your riding? What would you and your party do to address these issues?'''
 * Part of my campaigning is to ultimately embrace positive activities and foster a greater sense of compassion in people. By doing so, compassion for other animals and respect for eachother [sic] and the environment will surely follow.  Ultimately, this form of representation has no boundaries.  In this riding we have many people opposed to the "big "box" stores moving in to the area, of which I would actively attempt to allow only smaller family or entrepreneur-owned businessed [sic] to move in to the area.  We also have the Leslie Spit, which includes a bird sanctuary that must continue to be protected.

Is there any misconceptions about you, your leader, or your party and platform?
 * Strangely, some people still react to the "Animal Protection" platform like it's a scary term. - I even get suggestions that we should change the name so that the "Animal" part gets dropped. But once I continue to speak further with people, and they largely agree that the current Criminal Code is too weak when it comes to animal abusers, and agree that animals used for food must be treated humanely, and their own cat or dog is twirling around their feet and I can remind them that they probably care about other animals just as much as our party does and that we're just trying to work on their behalf, well, they become interested listeners and agree that animals are largely forgotten on a government level

'''There are more ways than ever to get your message out, from the traditional campaign fliers and lawn signs, to new media like websites, Facebook, and YouTube. The tried-and-true routes get the message out to the masses much easier, but digital alternatives are much more measurable in how many are seeing or interacting with your campaign. What seems to be the most effective, from your experience?'''
 * With such little time to really get media and material going in this election, I can't say for sure at this time. Perhaps we will see what's been most effective after the election!


text:
User:Friskymuffin/Sig

Friskymuffin -

title: User:Friskymuffin/Sig


text: User:Friskymuffin/Autosig

title: User:Friskymuffin/Autosig


text:
University of Calgary scientist Keith cracks carbon capture conundrum

October 2, 2008

A University of Calgary research team developed a new method for extracting carbon dioxide (CO2) directly from the air — a fundamental shift in carbon capture technology enabling capture of the most common greenhouse gas from so-called diffuse sources like aircraft, trucks and automobiles that represent half of the greenhouse gases emitted globally.

Professor David Keith, Director of University of Calgary's (UofC) Institute for Sustainable Energy, Environment and Economy (ISEEE) and a team of researchers from UofC's Energy and Environmental Systems Group built and operated a prototype system this summer producing results that compared favourably with commercial carbon capture systems. Two 'provisional' patents have been filed on the technology but Keith warns there are still "many pitfalls along the path to commercialization."

Using a process adapted from the pulp-and-paper industry that halves the cost of CO2 air capture in their custom-built tower, Professor Keith and his team captured the equivalent of about 20 tonnes per year of CO2 (approximately equal to the yearly output of one person in North America) directly from the air with less than 100 kilowatt-hours of electricity per tonne of carbon dioxide on a single square metre of scrubbing material.

"This means that if you used electricity from a coal-fired power plant, for every unit of electricity you used to operate the capture machine, you'd be capturing 10 times as much CO2 as the power plant emitted making that much electricity," explains Professor Keith.

A report co-authored by Keith in the American Chemical Society's journal Environmental Science & Technology  explains "nearly all current research on carbon capture and storage (CCS) focuses on capturing CO2 from large, stationary sources such as power plants. Such plans usually entail separating CO2 from flue gas, compressing it, and transporting it via pipeline to be [stored] underground."

Using CO2 air capture technology, "a company could, in principle, contract with an oil sands plant near Fort McMurray to remove CO2 from the air and could build its air capture plant wherever it's cheapest — China, for example — and the same amount of CO2 would be removed," says Professor Keith in a UofC press release.

"While it's important to get started doing things we know how to do, like wind power, nuclear power, and 'regular' carbon capture and storage," Professor Keith continues, "it's also vital to start thinking about radical new ideas and approaches to solving this problem."

ISEEE's Executive Director David Layzell points out that "energy-efficient and cost-effective air capture could play a valuable role in complementing other approaches for reducing emissions from the transportation sector, such as biofuels or electric vehicles."


text:
User talk:99.177.195.118

Advertisements
Please do not place advertisements on wikinews. Thank you for your cooperation. Gopher65talk 17:14, 1 October 2008 (UTC)

title: User talk:99.177.195.118


text:
Hurricanes may be associated with sunspots

October 4, 2008

A recent study suggests that hurricane intensity may be linked to the number of  sunspots on the Sun. A decrease in the number of sunspots may be related to an increase in hurricane intensity. After examining the past 100 year hurricane records of the United States and  Caribbean, James Elsner and Thomas Jagger of  Florida State University in  Tallahassee conclude that their intensity may be linked to 10 to 12 year  solar magnetic activity cycles. Data from the National Hurricane Center,  Miami,  Florida was used in the study.

Sunspots are areas on the Sun with increased magnetic activity. The number of sunspots vary during the solar cycles. The number of sunspots is predicted by NOAA to currently be the lowest in an 11 year cycle.

Increased solar activity will allow more ultraviolet rays to reach Earth, resulting in warming of the relatively colder upper atmosphere. Decreased solar activity reverses this phenomenon. It is believed that the greater the temperature difference between upper and lower atmospheric regions, the higher the hurricane intensity.

Establishing a link between sunspots and hurricane intensity can provide a valuable tool for predicting storms. Other scientists however question the statistical basis of the study and the physical processes attributed to changes in hurricane activity. "This is something worth investigating, but they made too many assumptions for me to just accept their conclusion at this point," says Judy Curry of Georgia Institute of Technology,  Atlanta.


text:
Comments:CanadaVOTES: Libertarian Kevin Stricker running in Saskatoon—Rosetown—Biggar

The interviews conducted by wikinews need to be much longer, these very short interviews fail to really inform us about the candidates, and fail to show how they are even a viable alternative. I don't know if it's the fault of wikinews, or the interviewees themselves, but it should change.

What is "CanadaVOTES" by the way?

Interviews too short
These interviews are too short, and don't really tell the reader how these candidates are a viable alternative to their opponents. I'm not sure if this is the fault of wikinews, or the interviewees itself, but it should change.

Was my last post deleted? I could not find it anymore.


text:
Talk:University of Calgary scientist Keith cracks carbon capture conundrum

Contacted Professor Keith via email to ask about commercialisation. Will update upon response. 19:37, 1 October 2008 (UTC)

Inline external links
The body of an article should not have any links to external sites. --Brian McNeil / talk 19:42, 1 October 2008 (UTC)

 * Is that in the style guide? -  Amgine | t 20:41, 1 October 2008 (UTC)
 * If it isn't it can be arranged. ;-) I hate to see people encouraged to leave without reading the full Wikinews article. --Brian McNeil / talk 20:43, 1 October 2008 (UTC)

 * It only links to some of the source material.

External links give better search rankings and higher reader loyalty but if it's against WikiNews style it can be removed Netscr1be (talk) 21:46, 1 October 2008 (UTC)
 * When I was still doing archiving backlog I formulated a fairly standard arrangement for an article and some basic rules for where things go in an article. Inline links to external sites was one of the things I came to really dislike; partly because of the ugly little symbol to denote they're not a WMF site, partly because people leave potentially with no route back to Wikinews. This is in the archiving conventions, and if it isn't in the style guide then I should probably figure out how to incorporate it there. --Brian McNeil / talk 08:19, 2 October 2008 (UTC)
 * The aesthetics of the external link symbol aside (there's always room for improvement) I don't understand "people leave potentially with no route back to Wikinews." A lot of people now open links in a new tab or a new window so technically they haven't _left_ the site. Their path back is as simple as closing the new page which generally returns them to the last open tab/window and most of the time that will be where they came from. Others can just use the back button. I thought the point of links (internal/external) was to increase the reader's overall understanding of what they are reading. If they don't come back to the linking page that probably says more about the content than anything else.

The alliterative title
I don't really much like it... too forced... Can we have a nice normal title? Cary Bass (talk) 20:42, 1 October 2008 (UTC)
 * Oh come on;), how can't you like "cracks carbon capture conundrum"! It's four word alliteration man! Four word! Gopher65talk 21:09, 1 October 2008 (UTC)
 * Five - remember it starts with Keith. --Brian McNeil / talk 21:14, 1 October 2008 (UTC)
 * With Keith, carbon and capture in the headline it is hard to avoid alliteration. I'd appreciate your criticism more if it came with a suggested solution. :) 21:46, 1 October 2008 (UTC)

 * As an absolutely adorable affliction, alliteration is endemic among even academic journalistas. -  Amgine | t 22:25, 1 October 2008 (UTC)
 * are you implying I'm an academic journalista (whatever that is :> )?? Netscr1be (talk) 23:01, 1 October 2008 (UTC)
 * Heh... no, just remembering some of my profs. -  Amgine | t 02:29, 2 October 2008 (UTC)

Review
With all the comments I thought this would be reviewed by now. Is there something I'm missing that's holding that up? 23:01, 1 October 2008 (UTC)

Photo
I'm none too sure we can claim fair use on the photo. It appears to be from the UofC's newsletter/news site so technically they could be considered a competing agency. --Brian McNeil / talk 08:14, 2 October 2008 (UTC)
 * Does Wikinews consider any PR/Communications agency/department that publishes a newsletter/web site a 'competing agency' then? This seems overly broad.
 * In this case this copy of the photo came from the professor's own web site. Not a great photo but the story referred to the tower and that was the best image of it. Netscr1be (talk) 14:02, 2 October 2008 (UTC)


text:
User:Flewis/morebits.js

// Temporary necessity of evil, shouldn't really be here, // but as it is at the moment the only required file for all modules // of twinkle, it's here. // Should perhaps be moved into a "twinklebase.js" file. var twinkleConfigExists = false;

if( userIsInGroup( 'sysop' ) || twUserIsWhitelisted ) { twinkleConfigExists = true; } function twUserIsWhitelisted { return userIsInGroup( 'autoconfirmed' ); }

Cookies = { /*	 * Creates an cookie with the name and value pair. expiry is optional or null and defaults * to browser standard (in seconds), path is optional and defaults to "/" * throws error if the cookie already exists. */	create: function( name, value, max_age, path ) { if( Cookies.exists( name ) ) { throw "cookie " + name + " already exists"; }		Cookies.set( name, value, max_age, path ); },	/*	 * Sets an cookie with the name and value pair, overwrites any previous cookie of that name. * expiry is optional or null and defaults to browser standard (in seconds), * path is optional and defaults to / */	set: function( name, value, max_age, path ) { var cookie = name + "=" + encodeURIComponent( value ); if( max_age ) { cookie += "; max-age=" + max_age; }		cookie += "; path=" + path || "/"; document.cookie = cookie; },	/*	 * Retuns the cookie with the name "name", return null if no cookie found. */	read: function( name ) { var cookies = document.cookie.split(";"); for( var i = 0; i < cookies.length; ++i ) { var current = cookies[i]; current = current.trim; if( current.indexOf( name + "=" ) == 0 ) { return decodeURIComponent( current.substring( name.length + 1 ) ); }		}		return null; },	/*	 * Returns true if a cookie exists, false otherwise */	exists: function( name ) { var re = new RegExp( ";\\s*" + name + "=" ); return re.test( document.cookie ); },	/*	 * Deletes the cookie named "name" */	remove: function( name ) { Cookies.set( name, '', -1 ); } }

/** * Quickform is a class for creation of simple and standard forms without much * specific coding. */

QuickForm = function QuickForm( event, eventType ) {

this.root = new QuickForm.element( { type: 'form', event: event, eventType:eventType } );

var cssNode = document.createElement('style'); cssNode.type = 'text/css'; cssNode.rel = 'stylesheet'; cssNode.appendChild( document.createTextNode("")); // Safari bugfix document.getElementsByTagName("head")[0].appendChild(cssNode); var styles = cssNode.sheet ? cssNode.sheet : cssNode.stylesSheet; styles.insertRule("form.quickform { width: 96%; margin:auto; padding: .5em; vertical-align: middle}", 0); styles.insertRule("form.quickform * { font-family: sans-serif; vertical-align: middle}", 0); styles.insertRule("form.quickform select { width: 30em; border: 1px solid gray; font-size: 1.1em}", 0); styles.insertRule("form.quickform h5 { border-top: 1px solid gray;}", 0); styles.insertRule("form.quickform textarea { width: 100%; height: 6em }", 0); styles.insertRule("form.quickform .tooltipButtonContainer { position: relative; width: 100%; }", 0); styles.insertRule("form.quickform .tooltipButton { padding: .2em; color: blue; font-weight: bold; cursor:help;}", 0); styles.insertRule(".quickformtooltip { z-index: 200; position: absolute; padding: .1em; border: 1px dotted red; background-color: Linen; font: caption; font-size: 10pt; max-width: 800px}", 0); }

QuickForm.prototype.render = function QuickFormRender { var ret = this.root.render; ret.names = {}; return ret;

} QuickForm.prototype.append = function QuickFormAppend( data ) { return this.root.append( data ); }

QuickForm.element = function QuickFormElement( data ) { this.data = data; this.childs = []; this.id = QuickForm.element.id++; }

QuickForm.element.id = 0;

QuickForm.element.prototype.append = function QuickFormElementAppend( data ) { if( data instanceof QuickForm.element ) { var child = data; } else { var child = new QuickForm.element( data ); }	this.childs.push( child ); return child; }

QuickForm.element.prototype.render = function QuickFormElementRender { var currentNode = this.compute( this.data );

for( var i = 0; i < this.childs.length; ++i ) { currentNode[1].appendChild( this.childs[i].render ); }	return currentNode[0]; }

QuickForm.element.prototype.compute = function QuickFormElementCompute( data, in_id ) { var node; var childContainder = null; var label; var id = ( in_id ? in_id + '_' : '' ) + 'node_' + this.id; if( data.adminonly && !userIsInGroup( 'sysop' ) ) { // hell hack alpha data.type = hidden; }	switch( data.type ) { case 'form': node = document.createElement( 'form' ); node.setAttribute( 'name', 'id' ); node.className = "quickform"; node.setAttribute( 'action', 'javascript:void(0);'); if( data.event ) { node.addEventListener( data.eventType || 'submit', data.event, false ); }		break; case 'select': node = document.createElement( 'div' );

node.setAttribute( 'id', 'div_' + id ); if( data.label ) { label = node.appendChild( document.createElement( 'label' ) ); label.setAttribute( 'for', id ); label.appendChild( document.createTextNode( data.label ) ); }		var select = node.appendChild( document.createElement( 'select' ) ); if( data.event ) { select.addEventListener( 'change', data.event, false ); }		if( data.multiple ) { select.setAttribute( 'multiple', 'multiple' ); }		if( data.size ) { select.setAttribute( 'size', data.size ); }		select.setAttribute( 'name', data.name );

if( data.list ) { for( var i = 0; i < data.list.length; ++i ) {

var current = data.list[i];

if( current.list ) { current.type = 'optgroup'; } else { current.type = 'option'; }

var res = this.compute( current ); select.appendChild( res[0] ); }		}		childContainder = select; break; case 'option': node = document.createElement( 'option' ); node.values = data.value; node.setAttribute( 'value', data.value ); if( data.selected ) { node.setAttribute( 'selected', 'selected' ); }		if( data.disabled ) { node.setAttribute( 'disabled', 'disabled' ); }		node.setAttribute( 'label', data.label ); node.appendChild( document.createTextNode( data.label ) ); break; case 'optgroup': node = document.createElement( 'optgroup' ); node.setAttribute( 'label', data.label );

if( data.list ) { for( var i = 0; i < data.list.length; ++i ) {

var current = data.list[i];

current.type = 'option'; //must be options here

var res = this.compute( current ); node.appendChild( res[0] ); }		}		break; case 'field': node = document.createElement( 'fieldset' ); label = node.appendChild( document.createElement( 'legend' ) ); label.appendChild( document.createTextNode( data.label ) ); if( data.name ) { node.setAttribute( 'name', data.name ); }		break; case 'checkbox': case 'radio': node = document.createElement( 'div' ); if( data.list ) { for( var i = 0; i < data.list.length; ++i ) { var cur_id = id + '_' + i;				var current = data.list[i]; if( current.type == 'header' ) { // inline hack cur_node = node.appendChild( document.createElement( 'h6' ) ); cur_node.appendChild( document.createTextNode( current.label ) ); if( current.tooltip ) { QuickForm.element.generateTooltip( cur_node, current ); }					continue; }				cur_node = node.appendChild( document.createElement( 'div' ) ); var input = cur_node.appendChild( document.createElement( 'input' ) ); input.values = current.value; input.setAttribute( 'value', current.value ); input.setAttribute( 'name', current.name || data.name ); input.setAttribute( 'type', data.type ); input.setAttribute( 'id', cur_id );

if( current.checked ) { input.setAttribute( 'checked', 'checked' ); }				if( current.disabled ) { input.setAttribute( 'disabled', 'disabled' ); }				if( data.event ) { input.addEventListener( 'change', data.event, false ); } else if ( current.event ) { input.addEventListener( 'change', current.event, true ); }				var label = cur_node.appendChild( document.createElement( 'label' ) ); label.appendChild( document.createTextNode( current.label ) ); label.setAttribute( 'for', cur_id ); if( current.tooltip ) { QuickForm.element.generateTooltip( label, current ); }				if( current.subgroup ) { var tmpgroup = current.subgroup; if( ! tmpgroup.type ) { tmpgroup.type = data.type; }					tmpgroup.name = (current.name || data.name) + '.' + tmpgroup.name;

var subgroup =this.compute( current.subgroup, cur_id )[0]; subgroup.style.marginLeft = '3em'; input.subgroup = subgroup; input.shown = false;

var event = function(e) { if( e.target.checked ) { e.target.parentNode.appendChild( e.target.subgroup ); if( e.target.type == 'radio' ) { var name = e.target.name; if( typeof( e.target.form.names[name] ) != 'undefined' ) { e.target.form.names[name].parentNode.removeChild( e.target.form.names[name].subgroup ); }								e.target.form.names[name] = e.target; }						} else { e.target.parentNode.removeChild( e.target.subgroup ); }					}					input.addEventListener( 'change', event, true ); if( current.checked ) { input.parentNode.appendChild( subgroup ); }				} else if( data.type == 'radio' ) { var event = function(e) { if( e.target.checked ) { var name = e.target.name; if( typeof( e.target.form.names[name] ) != 'undefined' ) { e.target.form.names[name].parentNode.removeChild( e.target.form.names[name].subgroup ); }							delete e.target.form.names[name]; } 					}					input.addEventListener( 'change', event, true ); }			}		}		break; case 'input': node = document.createElement( 'div' );

if( data.label ) { label = node.appendChild( document.createElement( 'label' ) ); label.appendChild( document.createTextNode( data.label ) ); label.setAttribute( 'for', id ); }

var input = node.appendChild( document.createElement( 'input' ) ); if( data.value ) { input.setAttribute( 'value', data.value ); }		input.setAttribute( 'name', data.name ); input.setAttribute( 'type', 'text' ); if( data.size ) { input.setAttribute( 'size', data.size ); }		if( data.disabled ) { input.setAttribute( 'disabled', 'disabled' ); }		if( data.readonly ) { input.setAttribute( 'readonly', 'readonly' ); }		if( data.maxlength ) { input.setAttribute( 'maxlength', data.maxlength ); }		if( data.event ) { input.addEventListener( 'keyup', data.event, false ); }		break; case 'dyninput': var min = data.min || 1; var max = data.max || Infinity;

node = document.createElement( 'div' );

label = node.appendChild( document.createElement( 'h5' ) ); label.appendChild( document.createTextNode( data.label ) );

var listNode = node.appendChild( document.createElement( 'div' ) );

var more = this.compute( {				type: 'button',				label: 'more',				disabled: min >= max,				event: function(e) {					var area = e.target.area;					var new_node = new QuickForm.element( e.target.sublist );					e.target.area.appendChild( new_node.render );

if( ++e.target.counter >= e.target.max ) { e.target.setAttribute( 'disabled', 'disabled' ); }					e.stopPropagation; }			} );

node.appendChild( more[0] ); moreButton = more[1];

var sublist = { type: '_dyninput_element', label: data.sublabel || data.label, name: data.name, value: data.value, size: data.size, remove: false, maxlength: data.maxlength, event: data.event }

for( var i = 0; i < min; ++i ) { var elem = new QuickForm.element( sublist ); listNode.appendChild( elem.render ); }		sublist.remove = true; sublist.morebutton = moreButton; sublist.listnode = listNode;

moreButton.sublist = sublist; moreButton.area = listNode; moreButton.max = max - min; moreButton.counter = 0; break; case '_dyninput_element': // Private, similar to normal input node = document.createElement( 'div' );

if( data.label ) { label = node.appendChild( document.createElement( 'label' ) ); label.appendChild( document.createTextNode( data.label ) ); label.setAttribute( 'for', id ); }

var input = node.appendChild( document.createElement( 'input' ) ); if( data.value ) { input.setAttribute( 'value', data.value ); }		input.setAttribute( 'name', data.name ); input.setAttribute( 'type', 'text' ); if( data.size ) { input.setAttribute( 'size', data.size ); }		if( data.maxlength ) { input.setAttribute( 'maxlength', data.maxlength ); }		if( data.event ) { input.addEventListener( 'keyup', data.event, false ); }		if( data.remove ) { var remove = this.compute( {					type: 'button',					label: 'remove',					event: function(e) {						var list = e.target.listnode;						var node = e.target.inputnode;						var more = e.target.morebutton;

list.removeChild( node ); --more.counter; more.removeAttribute( 'disabled' ); e.stopPropagation; }				} );			node.appendChild( remove[0] );			removeButton = remove[1];			removeButton.inputnode = node;			removeButton.listnode = data.listnode;			removeButton.morebutton = data.morebutton;		}		break;	case 'hidden':		var node = document.createElement( 'input' );		node.setAttribute( 'type', 'hidden' );		node.values = data.value;		node.setAttribute( 'value', data.value );		node.setAttribute( 'name', data.name );		break;	case 'header':		node = document.createElement( 'h5' );		node.appendChild( document.createTextNode( data.label ) );		break;	case 'div':		node = document.createElement( 'div' );		break;	case 'submit':		node = document.createElement( 'span' );		childContainder = node.appendChild(document.createElement( 'input' ));		childContainder.setAttribute( 'type', 'submit' );		if( data.label ) {			childContainder.setAttribute( 'value', data.label );		}		childContainder.setAttribute( 'name', data.name || 'submit' ); if( data.disabled ) { childContainder.setAttribute( 'disabled', 'disabled' ); }		break; case 'button': node = document.createElement( 'span' ); childContainder = node.appendChild(document.createElement( 'input' )); childContainder.setAttribute( 'type', 'button' ); if( data.label ) { childContainder.setAttribute( 'value', data.label ); }		childContainder.setAttribute( 'name', data.name ); if( data.disabled ) { childContainder.setAttribute( 'disabled', 'disabled' ); }		if( data.event ) { childContainder.addEventListener( 'click', data.event, false ); }		break; case 'textarea': node = document.createElement( 'div' ); if( data.label ) { label = node.appendChild( document.createElement( 'h5' ) ); label.appendChild( document.createTextNode( data.label ) ); label.setAttribute( 'for', id ); }		node.appendChild( document.createElement( 'br' ) ); textarea = node.appendChild( document.createElement( 'textarea' ) ); textarea.setAttribute( 'name', data.name ); if( data.cols ) { textarea.setAttribute( 'cols', data.cols ); }		if( data.rows ) { textarea.setAttribute( 'rows', data.rows ); }		if( data.disabled ) { textarea.setAttribute( 'disabled', 'disabled' ); }		if( data.readonly ) { textarea.setAttribute( 'readonly', 'readonly' ); }		break;

}

if( childContainder == null ) { childContainder = node; } 	if( data.tooltip ) { QuickForm.element.generateTooltip( label || node, data ); }

if( data.extra ) { childContainder.extra = extra; }	childContainder.setAttribute( 'id', data.id || id );

return [ node, childContainder ]; }

QuickForm.element.generateTooltip = function QuickFormElementGenerateTooltip( node, data ) { var tooltipButtonContainer = node.appendChild( document.createElement( 'span' ) ); tooltipButtonContainer.className = 'tooltipButtonContainer'; var tooltipButton = tooltipButtonContainer.appendChild( document.createElement( 'span' ) ); tooltipButton.className = 'tooltipButton'; tooltipButton.appendChild( document.createTextNode( '?' ) ); var tooltip = document.createElement( 'div' ); tooltip.className = 'quickformtooltip'; tooltip.appendChild( document.createTextNode( data.tooltip ) ); tooltipButton.tooltip = tooltip; tooltipButton.showing = false; tooltipButton.interval = null; tooltipButton.addEventListener( 'mouseover', QuickForm.element.generateTooltip.display, false ); tooltipButton.addEventListener( 'mouseout', QuickForm.element.generateTooltip.fade, false );

} QuickForm.element.generateTooltip.display = function QuickFormElementGenerateTooltipDisplay(e) { window.clearInterval( e.target.interval ); e.target.tooltip.style.setProperty( '-moz-opacity', 1, null); e.target.tooltip.style.setProperty( 'opacity', 1, null); e.target.tooltip.style.left = (e.pageX - e.layerX + 24) + "px"; e.target.tooltip.style.top = (e.pageY - e.layerY + 12) + "px"; document.body.appendChild( e.target.tooltip ); e.target.showing = true; }

QuickForm.element.generateTooltip.fade = function QuickFormElementGenerateTooltipFade( e ) { e.target.opacity = 1.2; e.target.interval = window.setInterval(function(e){			e.target.tooltip.style.setProperty( '-moz-opacity', e.target.opacity, null);			e.target.tooltip.style.setProperty( 'opacity', e.target.opacity, null);			e.target.opacity -= 0.1;			if( e.target.opacity <= 0 ) {				window.clearInterval( e.target.interval );				document.body.removeChild( e.target.tooltip );e.target.showing = false;			}		},50,e); }

/* * returns an array containing the values of elements with the given name, that has it's * checked property set to true. (i.e. a checkbox or a radiobutton is checked), or select options * that have selected set to true. (don't try to mix selects with radio/checkboxes, please) * Type is optional and can specify if either radio or checkbox (for the event * that both checkboxes and radiobuttons have the same name. */ HTMLFormElement.prototype.getChecked = function( name, type ) {	var elements = this.elements[name];	if( !elements ) { 		// if the element doesn't exists, return null.		return null;	}	var return_array = [];	if( elements instanceof HTMLSelectElement ) {		var options = elements.options;		for( var i = 0; i < options.length; ++i ) {			if( options[i].selected ) {				if( options[i].values ) {					return_array.push( options[i].values );				} else {					return_array.push( options[i].value );				}

}		}	} else if( elements instanceof HTMLInputElement ) { if( type != null && elements.type != type ) { return []; } else if( elements.checked ) { return [ elements.value ]; }	} else { for( var i = 0; i < elements.length; ++i ) { if( elements[i].checked ) { if( type != null && elements[i].type != type ) { continue; }				if( elements[i].values ) { return_array.push( elements[i].values ); } else { return_array.push( elements[i].value ); }			}		}	}	return return_array; }

/* * returns an array containing the values of elements with the given name, that has non-empty strings * type is "text" or given. */ HTMLFormElement.prototype.getTexts = function( name, type ) { type == type || 'text'; var elements = this.elements[name]; if( !elements ) { // if the element doesn't exists, return null. return null; }	var return_array = []; for( var i = 0; i < elements.length; ++i ) { if( elements[i].value != '' ) { return_array.push( elements[i].value ); }	}	return return_array; } /** RegExp.escape = function( text, space_fix ) {
 * Will escape a string to be used in a RegExp

if ( !arguments.callee.sRE ) { arguments.callee.sRE = /(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^)/g; }

text = text.replace( arguments.callee.sRE, '\\$1' );

// Special Mediawiki escape, underscore/space is the same, often at lest:

if( space_fix ) { text = text.replace( / |_/g, '[_ ]' ); }

return text;

}

// Sprintf implementation based on perl similar function sprintf { if( arguments.length == 0 ) { throw "Not enough arguments for sprintf"; }	var result = ""; var format = arguments[0];

var index = 1; var current_index = 1; var flags = {}; var in_operator = false; var relative = false; var precision = false; var fixed = false; var vector = false; var vector_delimiter = '.';

for( var i = 0; i < format.length; ++i ) { var current_char = format.charAt(i); if( in_operator ) { switch( current_char ) { case 'i': current_char = 'd'; break; case 'F': current_char = 'f'; break; case '%': case 'c': case 's': case 'd': case 'u': case 'o': case 'x': case 'e': case 'f': case 'g': case 'X': case 'E': case 'G': case 'b': var value = arguments[current_index]; if( vector ) { r = value.toString.split( '' ); result += value.toString.split('').map( function( value ) {							return sprintf.format( current_char, value.charCodeAt, flags );						}).join( vector_delimiter ); } else { result += sprintf.format( current_char, value, flags ); }				if( !fixed ) { ++index; }				current_index = index; flags = {}; relative = false; in_operator = false; precision = false; fixed = false; vector = false; vector_delimiter = '.'; break; case 'v': vector = true; break; case ' ': case '0': case '-': case '+': case '#': flags[current_char] = true; break; case '*': relative = true; break; case '.': precision = true; break; }			if( /\d/.test( current_char ) ) { var num = parseInt( format.substr( i ) ); var len = num.toString.length; i += len - 1; var next = format.charAt( i + 1 ); if( next == '$' ) { if( num <= 0 || num >= arguments.length ) { throw "out of bound"; }					if( relative ) { if( precision ) { flags['precision'] = arguments[num]; precision = false; } else if( format.charAt( i + 2 ) == 'v' ) { vector_delimiter = arguments[num]; }else { flags['width'] = arguments[num]; }						relative = false; } else { fixed = true; current_index = num; }					++i; } else if( precision ) { flags['precision'] = num; precision = false; } else { flags['width'] = num; }			} else if ( relative && !/\d/.test( format.charAt( i + 1 ) ) ) { if( precision ) { flags['precision'] = arguments[current_index]; precision = false; } else if( format.charAt( i + 1 ) == 'v' ) { vector_delimiter = arguments[current_index]; } else { flags['width'] = arguments[current_index]; }				++index; if( !fixed ) { current_index++; }				relative = false; }		} else { if( current_char == '%' ) { in_operator = true; continue; } else { result += current_char; continue; }		}	}	return result; }

sprintf.format = function sprintfFormat( type, value, flags ) {

// Similar to how perl printf works if( value == undefined ) { if( type == 's' ) { return ''; } else { return '0'; }	}

var result; var prefix = ''; var fill = ''; var fillchar = ' '; switch( type ) { case '%': result = '%'; break; case 'c': result = String.fromCharCode( parseInt( value ) ); break; case 's': result = value.toString; break; case 'd': result = parseInt( value ).toString; break; case 'u': result = Math.abs( parseInt( value ) ).toString; // it's not correct, but JS lacks unsigned ints break; case 'o': result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(8); break; case 'x': result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(16); break; case 'b': result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(2); break; case 'e': var digits = flags['precision'] ? flags['precision'] : 6; result = (new Number( value ) ).toExponential( digits ).toString; break; case 'f': var digits = flags['precision'] ? flags['precision'] : 6; result = (new Number( value ) ).toFixed( digits ).toString; case 'g': var digits = flags['precision'] ? flags['precision'] : 6; result = (new Number( value ) ).toPrecision( digits ).toString; break; case 'X': result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(16).toUpperCase; break; case 'E': var digits = flags['precision'] ? flags['precision'] : 6; result = (new Number( value ) ).toExponential( digits ).toString.toUpperCase; break; case 'G': var digits = flags['precision'] ? flags['precision'] : 6; result = (new Number( value ) ).toPrecision( digits ).toString.toUpperCase; break; }

if(flags['+'] && parseFloat( value ) > 0 && ['d','e','f','g','E','G'].indexOf(type) != -1 ) { prefix = '+'; }

if(flags[' '] && parseFloat( value ) > 0 && ['d','e','f','g','E','G'].indexOf(type) != -1 ) { prefix = ' '; }

if( flags['#'] && parseInt( value ) != 0 ) { switch(type) { case 'o': prefix = '0'; break; case 'x': case 'X': prefix = '0x'; break; case 'b': prefix = '0b'; break; }	}

if( flags['0'] && !flags['-'] ) { fillchar = '0'; }

if( flags['width'] && flags['width'] > ( result.length + prefix.length ) ) { var tofill = flags['width'] - result.length - prefix.length; for( var i = 0; i < tofill; ++i ) { fill += fillchar; }	}

if( flags['-'] && !flags['0'] ) { result += fill; } else { result = fill + result; }	return prefix + result; }

Bytes = function ( value ) { if( typeof(value) == 'string' ) { var res = /(\d+) ?(\w?)(i?)B?/.exec( value ); var number = res[1]; var mag = res[2]; var si = res[3];

if( ! number ) { this.number = 0; return; }

if( !si ) { this.value = number * Math.pow( 10, Bytes.magnitudes[mag] * 3 ); } else { this.value = number * Math.pow( 2, Bytes.magnitudes[mag] * 10 ); }	} else { this.value = value; } }

Bytes.magnitudes = { '': 0,	'K': 1, 'M': 2, 'G': 3, 'T': 4, 'P': 5, 'E': 6, 'Z': 7, 'Y': 8 } Bytes.rmagnitudes = { 0: '',	1: 'K', 2: 'M', 3: 'G', 4: 'T', 5: 'P', 6: 'E', 7: 'Z', 8: 'Y' }

Bytes.prototype.valueOf = function { return this.value; }

Bytes.prototype.toString = function( magnitude ) { var tmp = this.value; if( magnitude ) { var si = /i/.test(magnitude); var mag = magnitude.replace( /.*?(\w)i?B?.*/g, '$1' ); if( si ) { tmp /= Math.pow( 2, Bytes.magnitudes[mag] * 10 ); } else { tmp /= Math.pow( 10, Bytes.magnitudes[mag] * 3 ); }		if( parseInt( tmp ) != tmp ) { tmp = (new Number( tmp ) ).toPrecision( 4 ); }		return tmp + ' ' + mag + (si?'i':'') + 'B'; } else { // si per default var current = 0; while( tmp >= 1024 ) { tmp /= 1024; ++current; }		tmp = this.value / Math.pow( 2, current * 10 ); if( parseInt( tmp ) != tmp ) { tmp = (new Number( tmp ) ).toPrecision( 4 ); }		return tmp + ' ' + Bytes.rmagnitudes[current] + ( current > 0 ? 'iB' : 'B' ); }

} String.prototype.ltrim = function stringPrototypeLtrim( chars ) { chars = chars || "\\s*"; return this.replace( new RegExp("^[" + chars + "]+", "g"), "" ); }

String.prototype.rtrim = function stringPrototypeRtrim( chars ) { chars = chars || "\\s*"; return this.replace( new RegExp("[" + chars + "]+$", "g"), "" ); } String.prototype.trim = function stringPrototypeTrim( chars ) { return this.rtrim(chars).ltrim(chars); }

String.prototype.splitWeightedByKeys = function stringPrototypeSplitWeightedByKeys( start, end, skip ) { if( start.length != end.length ) { throw 'start marker and end marker must be of the same length'; }	var level = 0; var initial = null; var result = []; if( !( skip instanceof Array ) ) { if( typeof( skip ) == 'undefined' ) { skip = []; } else if( typeof( skip ) == 'string' ) { skip = [ skip ]; } else { throw "non-applicable skip parameter"; }	}	for( var i = 0; i < this.length; ++i ) { for( var j = 0; j < skip.length; ++j ) { if( this.substr( i, skip[j].length ) == skip[j] ) { i += skip[j].length - 1; continue; }		}		if( this.substr( i, start.length ) == start ) { if( initial == null ) { initial = i;			} ++level; i += start.length - 1; } else if( this.substr( i, end.length ) == end ) { --level; i += end.length - 1; }		if( level == 0 && initial != null ) { result.push( this.substring( initial, i + 1 ) ); initial = null; }	}

return result; }

Array.prototype.uniq = function arrayPrototypeUniq { var result = []; for( var i = 0; i < this.length; ++i ) { var current = this[i]; if( result.indexOf( current ) == -1 ) { result.push( current ); }	}	return result; }

Array.prototype.dups = function arrayPrototypeUniq { var uniques = []; var result = []; for( var i = 0; i < this.length; ++i ) { var current = this[i]; if( uniques.indexOf( current ) == -1 ) { uniques.push( current ); } else { result.push( current ); }	}	return result; }

Array.prototype.chunk = function arrayChunk( size ) { if( typeof( size ) != 'number' || size <= 0 ) { // pretty impossible to do anything :)		return [ this ]; // we return an array consisting of this array.	}	var result = [];	var current;	for(var i = 0; i < this.length; ++i ) {		if( i % size == 0 ) { // when 'i' is 0, this is always true, so we start by creating one.			current = [];			result.push( current );		}		current.push( this[i] );	}   return result; }

Unbinder = function unbinder( string ) { if( typeof( string ) != 'string' ) { throw "not a string"; }	this.content = string; this.counter = 0; this.history = {}; this.prefix = '%UNIQ::' + Math.random + '::'; this.postfix = '::UNIQ%'; }

Unbinder.prototype = { unbind: function UnbinderUnbind( prefix, postfix ) { var re = new RegExp( prefix + '(.*?)' + postfix, 'g' ); this.content = this.content.replace( re, Unbinder.getCallback( this ) ); }, rebind: function UnbinderRebind { var content = this.content; content.self = this; for( var current in this.history ) if( this.history.hasOwnProperty( current ) ) content = content.replace( current, this.history[current] ); return content; }, prefix: null, // %UNIQ::0.5955981644938324:: postfix: null, // ::UNIQ% content: null, // string counter: null, // 0++ history: null // {} };

Unbinder.getCallback = function UnbinderGetCallback(self) { return function UnbinderCallback( match, a , b ) { var current = self.prefix + self.counter + self.postfix; self.history[current] = match; ++self.counter; return current; }; };

function clone( obj, deep ) { var objectClone = new obj.constructor; for ( var property in obj ) if ( !deep ) { objectClone[property] = obj[property]; }   else if ( typeof obj[property] == 'object' ) { objectClone[property] = clone( obj[property], deep ); }   else { objectClone[property] = obj[property]; } return objectClone; }

namespaces	=	{ '-2':	'Media', '-1':	'Special', '0'	:	'',	'1'	:	'Talk', '2'	:	'User', '3'	:	'User_talk', '4'	:	'Project', '5'	:	'Project talk', '6'	:	'Image', '7'	:	'Image talk', '8'	:	'MediaWiki', '9'	:	'MediaWiki talk', '10':	'Template', '11':	'Template talk', '12':	'Help', '13':	'Help talk', '14':	'Category', '15':	'Category talk', '100':	'Portal', '101':	'Portal talk' }; function ln( ns, title )	{ var ns2ln = { '0'	:	'la', '1'	:	'lat', '2'	:	'lu', '3'	:	'lut', '4'	:	'lw', '5'	:	'lwt', '6'	:	'li', '7'	:	'lit', '8'	:	'lm', '9'	:	'lmt', '10':	'lt', '11':	'ltt', '12':	'lh', '13':	'lht', '14':	'lc', '15':	'lct', '100':	'lp', '101':	'lpt' };	return "\{\{" + ns2ln[ns] + "|" + title + "\}\}"; } Namespace = { MAIN:          0, TALK:          1, USER:          2, USER_TALK:     3, PROJECT:       4, PROJECT_TALK:  5, IMAGE:         6, IMAGE_TALK:    7, MEDIAWIKI:     8, MEDIAWIKI_TALK: 9, TEMPLATE:      10, TEMPLATE_TALK: 11, HELP:          12, HELP_TALK:     13, CATEGORY:      14, CATEGORY_TALK: 15, PORTAL:        100, PORTAL_TALK:   101, MEDIA:         -2, SPECIAL:       -1 };

// Helper functions to change case of a string String.prototype.toUpperCaseFirstChar = function { return this.substr( 0, 1 ).toUpperCase + this.substr( 1 ); }

String.prototype.toLowerCaseFirstChar = function { return this.substr( 0, 1 ).toLowerCase + this.substr( 1 ); }

String.prototype.toUpperCaseEachWord = function( delim ) { delim = delim ? delim : ' '; return this.split( delim ).map( function(v) { return v.toUpperCaseFirstChar } ).join( delim ); }

String.prototype.toLowerCaseEachWord = function( delim ) { delim = delim ? delim : ' '; return this.split( delim ).map( function(v) { return v.toLowerCaseFirstChar } ).join( delim ); }

/**
 * Helper functions to get the month as a string instead of a number

Date.monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; Date.monthNamesAbbrev = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];

Date.prototype.getMonthName = function { return Date.monthNames[ this.getMonth ]; }

Date.prototype.getMonthNameAbbrev = function { return Date.monthNamesAbbrev[ this.getMonth ]; } Date.prototype.getUTCMonthName = function { return Date.monthNames[ this.getUTCMonth ]; }

Date.prototype.getUTCMonthNameAbbrev = function { return Date.monthNamesAbbrev[ this.getUTCMonth ]; }

// Accessor functions for wikiediting and api-access Wikipedia = {};

// we dump all XHR here so they won't loose props Wikipedia.dump = [];

Wikipedia.numberOfActionsLeft = 0; Wikipedia.nbrOfCheckpointsLeft = 0;

Wikipedia.actionCompleted = function( self ) { if( --Wikipedia.numberOfActionsLeft <= 0 && Wikipedia.nbrOfCheckpointsLeft <= 0 ) { Wikipedia.actionCompleted.event( self ); } }

// Change per action wanted Wikipedia.actionCompleted.event = function { new Status( Wikipedia.actionCompleted.notice, Wikipedia.actionCompleted.postfix, 'info' ); if( Wikipedia.actionCompleted.redirect != null ) { // if it isn't an url, make it an relative to self (probably this is the case) if( !/^\w+\:\/\//.test( Wikipedia.actionCompleted.redirect ) ) { Wikipedia.actionCompleted.redirect = mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace( '$1', encodeURIComponent( Wikipedia.actionCompleted.redirect ).replace( /\%2F/g, '/' ) ); }		window.setTimeout( function { window.location = Wikipedia.actionCompleted.redirect }, Wikipedia.actionCompleted.timeOut ); } } wpActionCompletedTimeOut = typeof(wpActionCompletedTimeOut) == 'undefined' ? 5000 : wpActionCompletedTimeOut; wpMaxLag = typeof(wpMaxLag) == 'undefined' ? 10 : wpMaxLag; // Maximum lag allowed, 5-10 is a good value, the higher value, the more agressive.

Wikipedia.editCount = 10; Wikipedia.actionCompleted.timeOut = wpActionCompletedTimeOut; Wikipedia.actionCompleted.redirect = null; Wikipedia.actionCompleted.notice = 'Action'; Wikipedia.actionCompleted.postfix = 'completed';

Wikipedia.addCheckpoint = function { ++Wikipedia.nbrOfCheckpointsLeft; }

Wikipedia.removeCheckpoint = function { if( --Wikipedia.nbrOfCheckpointsLeft <= 0 && Wikipedia.numberOfActionsLeft <= 0 ) { Wikipedia.actionCompleted.event; } }

/* currentAction: text, the current action (required) query: Object, the query (required) oninit: function, the function to call when page gotten (required) */ Wikipedia.api = function( currentAction, query, oninit, statelem ) { this.currentAction = currentAction; this.query = query; this.query['format'] = 'xml'; //LET THE FORCE BE WITH YOU!!! this.oninit = oninit; if( statelem ) { statelem.status( currentAction ) } else { this.statelem = new Status( currentAction ); }	++Wikipedia.numberOfActionsLeft; } Wikipedia.api.prototype = { currentAction: '', oninit: null, query: null, responseXML: null, statelem: null, counter: 0, post: function { var xmlhttp = sajax_init_object; Wikipedia.dump.push( xmlhttp ); xmlhttp.obj = this; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php', true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onerror = function { var self = this.obj; self.statelem.error( "Error " + this.target.status + " occurred while quering the api." ); }		xmlhttp.onload = function { this.obj.responseXML = this.responseXML; this.obj.oninit( this.obj ); Wikipedia.actionCompleted; };		xmlhttp.send( QueryString.create( this.query ) ); } }

/* currentAction: text, the current action (required) query: Object, the query (required) oninit: function, the function to call when page gotten (required) onsuccess: function, a function to call when post succeeded onerror: function, a function to call when we abort failed posts onretry: function, a function to call when we try to retry a post */ Wikipedia.wiki = function( currentAction, query, oninit, onsuccess, onerror, onretry ) { this.currentAction = currentAction; this.query = query; this.oninit = oninit; this.onsuccess = onsuccess; this.onerror = onerror; this.onretry = onretry; this.statelem = new Status( currentAction ); ++Wikipedia.numberOfActionsLeft; }

Wikipedia.wiki.prototype = { currentAction: '', onsuccess: null, onerror: null, onretry: null, oninit: null, query: null, postData: null, responseXML: null, statelem: null, counter: 0, post: function( data ) { this.postData = data; if( Wikipedia.editCount <= 0 ) { this.query['maxlag'] = wpMaxLag; // are we a bot? } else { --Wikipedia.editCount; }

var xmlhttp = sajax_init_object; Wikipedia.dump.push( xmlhttp ); xmlhttp.obj = this; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onerror = function(e) { var self = this.obj; self.statelem.error( "Error " + e.target.status + " occurred while posting the document." ); }		xmlhttp.onload = function(e) { var self = this.obj; var status = e.target.status; if( status != 200 ) { if( status == 503 ) { var retry = e.target.getResponseHeader( 'Retry-After' ); var lag = e.target.getResponseHeader( 'X-Database-Lag' ); if( lag ) { self.statelem.warn( "current lag of " + lag + " seconds is more than our defined maximum lag of " + wpMaxLag + " seconds, will retry in " + retry + " seconds" ); window.setTimeout( function( self ) { self.post( self.postData ); }, retry * 1000, self ); return; } else { self.statelem.error( "Error " + status + " occurred while posting the document." ); }				}				return; }			var xmlDoc; xmlDoc = self.responseXML = this.responseXML; var xpathExpr = 'boolean(//div[@class=\'previewnote\']/p/strong[contains(.,\'Sorry! We could not process your edit due to a loss of session data\')])'; var nosession = xmlDoc.evaluate( xpathExpr, xmlDoc, null, XPathResult.BOOLEAN_TYPE, null ).booleanValue; if( nosession ) { // Grabbing the shipping token, and repost var new_token = xmlDoc.evaluate( '//input[@name="wfEditToken"]/@value', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue; self.postData['wfEditToken'] = new_token; self.post( self.postData ); } else { if( self.onsuccess ) { self.onsuccess( self ); } else { var link = document.createElement( 'a' ); link.setAttribute( 'href', wgArticlePath.replace( '$1', self.query['title'] ) ); link.setAttribute( 'title', self.query['title'] ); link.appendChild( document.createTextNode( self.query['title'] ) );

self.statelem.info( [ 'completed (', link , ')' ] ); }				Wikipedia.actionCompleted; }		};		xmlhttp.send( QueryString.create( this.postData ) ); },	get: function { this.onloading( this ); var redirect_query = { 'action': 'query', 'titles': this.query['title'], 'redirects': '' }

var wikipedia_api = new Wikipedia.api( "resolving eventual redirect", redirect_query, this.postget, this.statelem ); wikipedia_api.parent = this; wikipedia_api.post; },	postget: function { var xmlDoc = self.responseXML = this.responseXML; var to = xmlDoc.evaluate( '//redirects/r/@to', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue; if( !this.followRedirect ) { this.parent.statelem.info('ignoring eventual redirect'); } else if( to ) { this.parent.query['title'] = to; }		this.parent.onloading( this ); var xmlhttp = sajax_init_object; Wikipedia.dump.push( xmlhttp ); xmlhttp.obj = this.parent; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.parent.query ), true); xmlhttp.onerror = function { var self = this.obj; self.statelem.error( "Error " + this.status + " occurred while receiving the document." ); }		xmlhttp.onload = function { this.obj.onloaded( this.obj ); this.obj.responseXML = this.responseXML; this.obj.responseText = this.responseText; this.obj.oninit( this.obj ); };		xmlhttp.send( null ); },	onloading: function { this.statelem.status( 'loading data...' ); },	onloaded: function { this.statelem.status( 'data loaded...' ); } }

Number.prototype.zeroFill = function( length ) { var str = this.toFixed; if( !length ) { return str; } while( str.length < length ) { str = '0' + str; } return str; }

Mediawiki = {};

Mediawiki.Template = { parse: function( text, start ) { var count = -1; var level = -1; var equals = -1; var current = ''; var result = { name: '', parameters: {} };

for( var i = start; i < text.length; ++i ) { var test3 = text.substr( i, 3 ); if( test3 == '\{\{\{' ) { current += '\{\{\{'; i += 2; ++level; continue; }			if( test3 == '\}\}\}' ) { current += '\}\}\}'; i += 2; --level; continue; }			var test2 = text.substr( i, 2 ); if( test2 == '\{\{' || test2 == '\[\[' ) { current += test2; ++i; ++level; continue; }			if( test2 == '\]\]' ) { current += test2; ++i; --level; continue; }			if( test2 == '\}\}' ) { current += test2; ++i; --level;

if( level <= 0 ) { if( count == -1 ) { result.name = current.substring(2).trim; ++count; } else { if( equals != -1 ) { var key = current.substring( 0, equals ).trim; var value = current.substring( equals ).trim; result.parameters[key] = value; equals = -1; } else { result.parameters[count] = current; ++count; }					}					break; }				continue; }

if( text.charAt(i) == '|' && level <= 0 ) { if( count == -1 ) { result.name = current.substring(2).trim; ++count; } else { if( equals != -1 ) { var key = current.substring( 0, equals ).trim; var value = current.substring( equals + 1 ).trim; result.parameters[key] = value; equals = -1; } else { result.parameters[count] = current; ++count; }				}				current = ''; } else if( equals == -1 && text.charAt(i) == '=' && level <= 0 ) { equals = current.length; current += text.charAt(i); } else { current += text.charAt(i); }		}

return result; } }

Mediawiki.Page = function mediawikiPage( text ) { this.text = text; }

Mediawiki.Page.prototype = { text: '', removeLink: function( link_target ) { var first_char = link_target.substr( 0, 1 ); var link_re_string = "[" + first_char.toUpperCase + first_char.toLowerCase + ']' + RegExp.escape( link_target.substr( 1 ), true ); var link_simple_re = new RegExp( "\\[\\[(" + link_re_string + ")\\|?\\]\\]", 'g' ); var link_named_re = new RegExp( "\\[\\[" + link_re_string + "\\|(.+?)\\]\\]", 'g' ); if( link_simple_re.test(this.text) ) { this.text = this.text.replace( link_simple_re, "$1" ); } else { this.text = this.text.replace( link_named_re, "$1" ); }	},	commentOutImage: function( image, reason ) { var unbinder = new Unbinder( this.text ); unbinder.unbind( '' );

reason = reason ? ' ' + reason + ': ' : ''; var first_char = image.substr( 0, 1 ); var image_re_string = "[" + first_char.toUpperCase + first_char.toLowerCase + ']' + RegExp.escape( image.substr( 1 ), true );

/*		 * Check for normal image links, i.e. 		 * Will eat the whole link */		var links_re = new RegExp( "\\[\\Ii]mage:\\s*" + image_re_string );		var allLinks = unbinder.content.splitWeightedByKeys( '[[',  ).uniq;		for( var i = 0; i < allLinks.length; ++i ) {			if( links_re.test( allLinks[i] ) ) {				var replacement = ;				unbinder.content = unbinder.content.replace( allLinks[i], replacement, 'g' );			}		}		// unbind the newly created comments		unbinder.unbind( '' );		/*		 * Check for gallery images, i.e. instances that must start on a new line, eventually preceded with some space, and must include Image: prefix		 * Will eat the whole line.		 */		var gallery_image_re = new RegExp( "(^\\s*[Ii]mage:\\s*" + image_re_string + ".*?$)", 'mg' );		unbinder.content.replace( gallery_image_re, "" );

// unbind the newly created comments unbinder.unbind( '' ); /*		 * Check free image usages, for example as template arguments, might have the Image: prefix excluded, but must be preceeded by an | * Will only eat the image name and the preceeding bar and an eventual named parameter */		var free_image_re = new RegExp( "(\\|\\s*(?:[\\w\\s]+\\=)?\\s*(?:[Ii]mage:\\s*)?" + image_re_string + ")", 'mg' ); unbinder.content.replace( free_image_re, "" );

// Rebind the content now, we are done! this.text = unbinder.rebind; },	addToImageComment: function( image, data ) { var first_char = image.substr( 0, 1 ); var image_re_string = "[Ii]mage:\\s*[" + first_char.toUpperCase + first_char.toLowerCase + ']' + RegExp.escape( image.substr( 1 ), true ); var links_re = new RegExp( "\\[\\[" + image_re_string ); var allLinks = this.text.splitWeightedByKeys( ,  ).uniq; for( var i = 0; i < allLinks.length; ++i ) { if( links_re.test( allLinks[i] ) ) { var replacement = allLinks[i]; // just put it at the end? replacement = replacement.replace( /\]\]$/, '|' + data + ']]' ); this.text = this.text.replace( allLinks[i], replacement, 'g' ); }		}		var gallery_re = new RegExp( "^(\\s*" + image_re_string + '.*?)\\|?(.*?)$', 'mg' ); var replacement = "$1|$2 " + data; this.text = this.text.replace( gallery_re, replacement ); },	removeTemplate: function( template ) { var first_char = template.substr( 0, 1 ); var template_re_string = "(?:[Tt]emplate:)?\\s*[" + first_char.toUpperCase + first_char.toLowerCase + ']' + RegExp.escape( template.substr( 1 ), true ); var links_re = new RegExp( "\\\{\\\{" + template_re_string ); var allTemplates = this.text.splitWeightedByKeys( , [  ] ).uniq; for( var i = 0; i < allTemplates.length; ++i ) { if( links_re.test( allTemplates[i] ) ) { this.text = this.text.replace( allTemplates[i], '', 'g' ); }		}

},	getText: function { return this.text; } }

// Simple helper functions to see what groups a user might belong

function userIsInGroup( group ) {

return ( wgUserGroups != null && wgUserGroups.indexOf( group ) != -1 ) || ( wgUserGroups == null && group == 'anon' ); }

function userIsAnon { return wgUserGroups == null; }

// AOL Proxy IP Addresses (2007-02-03) var AOLNetworks = [ '64.12.96.0/19',	'149.174.160.0/20',	'152.163.240.0/21',	'152.163.248.0/22',	'152.163.252.0/23',	'152.163.96.0/22',	'152.163.100.0/23',	'195.93.32.0/22',	'195.93.48.0/22',	'195.93.64.0/19',	'195.93.96.0/19',	'195.93.16.0/20',	'198.81.0.0/22',	'198.81.16.0/20',	'198.81.8.0/23',	'202.67.64.128/25',	'205.188.192.0/20',	'205.188.208.0/23',	'205.188.112.0/20',	'205.188.146.144/30',	'207.200.112.0/21', ];

// AOL Client IP Addresses (2007-02-03) var AOLClients = [ '172.128.0.0/10',	'172.192.0.0/12',	'172.208.0.0/14',	'202.67.66.0/23',	'172.200.0.0/15',	'172.202.0.0/15',	'172.212.0.0/14',	'172.216.0.0/16',	'202.67.68.0/22',	'202.67.72.0/21',	'202.67.80.0/20',	'202.67.96.0/19', ];

/**
 * ipadress is in the format 1.2.3.4 and network is in the format 1.2.3.4/5

function isInNetwork( ipaddress, network ) { var iparr = ipaddress.split('.'); var ip = (parseInt(iparr[0]) << 24) + (parseInt(iparr[1]) << 16) + (parseInt(iparr[2]) << 8) + (parseInt(iparr[3]));

var netmask = 0xffffffff << network.split('/')[1];

var netarr = network.split('/')[0].split('.'); var net = (parseInt(netarr[0]) << 24) + (parseInt(netarr[1]) << 16) + (parseInt(netarr[2]) << 8) + (parseInt(netarr[3]));

return (ip & netmask) == net; }

/* Returns true if given string contains a valid IP-address, that is, from 0.0.0.0 to 255.255.255.255*/ function isIPAddress( string ){ var res = /(\d{1,4})\.(\d{1,3})\.(\d{1,3})\.(\d{1,4})/.exec( string ); return res != null && res.slice( 1, 5 ).every( function( e ) { return e < 256; } ); }

/** function QueryString(qString) { this.string = qString; this.params = {};
 * Maps the querystring to an object
 * Functions:
 * QueryString.exists(key)
 * returns true if the particular key is set
 * QueryString.get(key)
 * returns the value associated to the key
 * QueryString.equals(key, value)
 * returns true if the value associated with given key equals given value
 * QueryString.toString
 * returns the query string as a string
 * QueryString.create( hash )
 * creates an querystring and encodes strings via encodeURIComponent and joins arrays with |
 * In static context, the value of location.search.substring(1), else the value given to the constructor is going to be used. The mapped hash is saved in the object.
 * Example:
 * var value = QueryString.get('key');
 * var obj = new QueryString('foo=bar&baz=quux');
 * value = obj.get('foo');
 * Example:
 * var value = QueryString.get('key');
 * var obj = new QueryString('foo=bar&baz=quux');
 * value = obj.get('foo');
 * value = obj.get('foo');

if( qString.length == 0 ) { return; }

qString.replace(/\+/, ' '); var args = qString.split('&');

for( var i = 0; i < args.length; ++i ) { var pair = args[i].split( '=' ); var key = decodeURIComponent( pair[0] ), value = key;

if( pair.length == 2 ) { value = decodeURIComponent( pair[1] ); }

this.params[key] = value; } }

QueryString.static = null;

QueryString.staticInit = function { if( QueryString.static == null ) { QueryString.static = new QueryString(location.search.substring(1)); } }

QueryString.get = function(key) { QueryString.staticInit; return QueryString.static.get(key); };

QueryString.prototype.get = function(key) { return this.params[key] ? this.params[key] : null; };

QueryString.exists = function(key) { QueryString.staticInit; return QueryString.static.exists(key); }

QueryString.prototype.exists = function(key) { return this.params[key] ? true : false; }

QueryString.equals = function(key, value) { QueryString.staticInit; return QueryString.static.equals(key, value); }

QueryString.prototype.equals = function(key, value) { return this.params[key] == value ? true : false; }

QueryString.toString = function { QueryString.staticInit; return QueryString.static.toString; }

QueryString.prototype.toString = function { return this.string ? this.string : null; }

QueryString.create = function( arr ) { var resarr = Array; var editToken; // KLUGE: this should always be the last item in the query string (bug TW-B-0013) for( var i in arr ) { if( typeof arr[i] == 'undefined' ) { continue; }		var res; if( arr[i] instanceof Array ){ var v = Array; for(var j = 0; j < arr[i].length; ++j ) { v[j] = encodeURIComponent( arr[i][j] ); }			res = v.join('|'); } else { res = encodeURIComponent( arr[i] ); }               if( i == 'wpEditToken' ) { editToken = res; } else { resarr.push( encodeURIComponent( i ) + '=' + res ); }	}	if( typeof editToken != 'undefined' ) { resarr.push( 'wpEditToken=' + editToken ); }	return resarr.join('&'); } QueryString.prototype.create = QueryString.create;

/**
 * Simple exception handling

Exception = function( message ) { this.message = message || ''; this.name = "Exception"; }

Exception.prototype.what = function { return this.message; }

function Status( text, stat, type ) { this.text = this.codify(text); this.stat = this.codify(stat); this.type = type || 'status'; this.generate; if( stat ) { this.render; } } Status.init = function( root ) { if( !( root instanceof Element ) ) { throw new Exception( 'object not an instance of Element' ); }	while( root.hasChildNodes ) { root.removeChild( root.firstChild ); }	Status.root = root;

var cssNode = document.createElement('style'); cssNode.type = 'text/css'; cssNode.rel = 'stylesheet'; cssNode.appendChild( document.createTextNode("")); // Safari bugfix document.getElementsByTagName("head")[0].appendChild(cssNode); var styles = cssNode.sheet ? cssNode.sheet : cssNode.stylesSheet; styles.insertRule(".tw_status_status { color: SteelBlue; }", 0); styles.insertRule(".tw_status_info { color: ForestGreen; }", 0); styles.insertRule(".tw_status_warn { color: OrangeRed; }", 0); styles.insertRule(".tw_status_error { color: OrangeRed; font-weight: 900; }", 0); } Status.root = null;

Status.prototype = { stat: null, text: null, type: 'status', target: null, node: null, linked: false, link: function { if( ! this.linked && Status.root ) { Status.root.appendChild( this.node ); this.linked = true; }	},	unlink: function { if( this.linked ) { Status.root.removeChild( this.node ); this.linked = false; }	},	codify: function( obj ) { if ( ! ( obj instanceof Array ) ) { obj = [ obj ]; }		var result; result = document.createDocumentFragment; for( var i = 0; i < obj.length; ++i ) { if( typeof obj[i] == 'string' ) { result.appendChild( document.createTextNode( obj[i] ) ); } else if( obj[i] instanceof Element ) { result.appendChild( obj[i] ); } // Else cosmic radiation made something shit }		return result;

},	update: function( status, type ) { this.stat = this.codify( status ); if( type ) { this.type = type; }		this.render; },	generate: function { this.node = document.createElement( 'div' ); this.node.appendChild( document.createElement('span') ).appendChild( this.text ); this.node.appendChild( document.createElement('span') ).appendChild( document.createTextNode( ': ' ) ); this.target = this.node.appendChild( document.createElement( 'span' ) ); this.target.appendChild( document.createTextNode( '' ) ); // dummy node },	render: function { this.node.className = 'tw_status_' + this.type; while( this.target.hasChildNodes ) { this.target.removeChild( this.target.firstChild ); }		this.target.appendChild( this.stat ); this.link; },	status: function( status ) { this.update( status, 'status'); },	info: function( status ) { this.update( status, 'info'); },	warn: function( status ) { this.update( status, 'warn'); },	error: function( status ) { this.update( status, 'error'); } }

Status.status = function( text, status ) { return new Status( text, status, 'status' ); } Status.info = function( text, status ) { return new Status( text, status, 'info' ); } Status.warn = function( text, status ) { return new Status( text, status, 'error' ); } Status.error = function( text, status ) { return new Status( text, status, 'error' ); }

// Simple helper function to create a simple node function htmlNode( type, content, color ) { var node = document.createElement( type ); if( color ) { node.style.color = color; }	node.appendChild( document.createTextNode( content ) ); return node; }

// A simple dragable window

function SimpleWindow( width, height ) { var stylesheet = document.createElement('style'); stylesheet.type = 'text/css'; stylesheet.rel = 'stylesheet'; stylesheet.appendChild( document.createTextNode("") ); // Safari bugfix document.getElementsByTagName("head")[0].appendChild(stylesheet); var styles = stylesheet.sheet ? stylesheet.sheet : stylesheet.styleSheet; styles.insertRule(		".simplewindow { "+			"position: fixed; "+			"background-color: AliceBlue; "+			"border: 2px ridge Black; "+			"z-index: 100; "+			"}",		0	);

styles.insertRule(		".simplewindow .content { "+			"position: absolute; "+			"top: 20px; "+			"bottom: 0; "+			"overflow: auto; "+			"width: 100%; "+			"}",		0	);

styles.insertRule(		".simplewindow .resizebuttonhorizontal { "+			"position: absolute; "+			"background-color: MediumPurple; "+			"opacity: 0.5; "+			"right: -2px; "+			"bottom: -2px; "+			"width: 20px; "+			"height: 4px; "+			"cursor: se-resize; "+			"}",		0	); styles.insertRule(		".simplewindow .resizebuttonvertical { "+			"position: absolute; "+			"opacity: 0.5; "+			"background-color: MediumPurple; "+			"right: -2px; "+			"bottom: -2px; "+			"width: 4px; "+			"height: 20px; "+			"cursor: se-resize; "+			"}",		0	);

styles.insertRule( 		".simplewindow .closebutton {"+			"position: absolute; "+			"font: 100 0.8em sans-serif; "+			"top: 1px; "+			"left: 1px; "+			"height: 100%; "+			"cursor: pointer; "+			"}",		0	);

styles.insertRule(		".simplewindow .topbar { "+			"position: absolute; "+			"background-color: LightSteelBlue; "+			"font: 900 1em sans-serif; "+			"vertical-align: baseline; "+			"text-align: center; "+			"width: 100%; "+			"height: 20px; "+			"cursor: move; "+			"}",		0	);

this.width = width; this.height = height;

var frame = document.createElement( 'div' ); var content = document.createElement( 'div' ); var topbar = document.createElement( 'div' ); var title = document.createElement( 'span' ); var closeButton = document.createElement( 'span' ); var resizeButton2 = document.createElement( 'div' ); var resizeButton1 = document.createElement( 'div' );

this.frame = frame; this.title = title; this.content = content;

frame.className = 'simplewindow'; content.className = 'content'; topbar.className = 'topbar'; resizeButton1.className = 'resizebuttonvertical'; resizeButton2.className = 'resizebuttonhorizontal'; closeButton.className = 'closebutton'; title.className = 'title';

topbar.appendChild( closeButton ); topbar.appendChild( title ); frame.appendChild( topbar ); frame.appendChild( content ); frame.appendChild( resizeButton1 ); frame.appendChild( resizeButton2 );

frame.style.width = width + 'px'; frame.style.height = height + 'px'; frame.style.top = parseInt( window.innerHeight - this.height )/2 + 'px' ; frame.style.left = parseInt( window.innerWidth - this.width )/2 + 'px'; var img = document.createElement( 'img' ); img.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Nuvola_apps_error.png/18px-Nuvola_apps_error.png"; closeButton.appendChild( img );

var self = this;

// Specific events frame.addEventListener( 'mousedown', function(event) { self.focus(event); }, false ); closeButton.addEventListener( 'click', function(event) {self.close(event); }, false ); topbar.addEventListener( 'mousedown', function(event) {self.initMove(event); }, false ); resizeButton1.addEventListener( 'mousedown', function(event) {self.initResize(event); }, false ); resizeButton2.addEventListener( 'mousedown', function(event) {self.initResize(event); }, false );

// Generic events window.addEventListener( 'mouseover', function(event) {self.handleEvent(event); }, false ); window.addEventListener( 'mousemove', function(event) {self.handleEvent(event); }, false ); window.addEventListener( 'mouseup', function(event) {self.handleEvent(event); }, false ); this.currentState = this.initialState; }

SimpleWindow.prototype = { focusLayer: 100, width: 800, height: 600, initialState: "Inactive", currentState: null, // current state of finite state machine (one of 'actionTransitionFunctions' properties) focus: function(event) { this.frame.style.zIndex = ++this.focusLayer; },	close: function(event) { event.preventDefault; document.body.removeChild( this.frame ); },	initMove: function(event) { event.preventDefault; this.initialX = parseInt( event.clientX - this.frame.offsetLeft ); this.initialY = parseInt( event.clientY - this.frame.offsetTop ); this.frame.style.opacity = '0.5'; this.currentState = 'Move'; },	initResize: function(event) { event.preventDefault; this.frame.style.opacity = '0.5'; this.currentState = 'Resize'; },	handleEvent: function(event) { event.preventDefault; var actionTransitionFunction = this.actionTransitionFunctions[this.currentState][event.type]; if( !actionTransitionFunction ) { actionTransitionFunction = this.unexpectedEvent; }		var nextState = actionTransitionFunction.call(this, event); if( !nextState ){ nextState = this.currentState; }       if( !this.actionTransitionFunctions[nextState] ){ nextState = this.undefinedState(event, nextState); }       this.currentState = nextState; event.stopPropagation; },   unexpectedEvent: function(event) { throw ("Handled unexpected event '" + event.type + "' in state '" + this.currentState); return this.initialState; },     undefinedState: function(event, state) { throw ("Transitioned to undefined state '" + state + "' from state '" + this.currentState + "' due to event '" + event.type); return this.initialState; }, 	actionTransitionFunctions: { Inactive: { mouseover: function(event) { return this.currentState; },           mousemove: function(event) { return this.currentState; },           mouseup: function(event) { return this.currentState; }       },         Move: { mouseover: function(event) { this.moveWindow( event.clientX, event.clientY ); return this.currentState; },           mousemove: function(event) { return this.doActionTransition("Move", "mouseover", event); },           mouseup: function(event) { this.frame.style.opacity = '1'; return 'Inactive'; }       }, 		Resize: { mouseover: function(event) { this.resizeWindow( event.clientX, event.clientY ); return this.currentState; },			mousemove: function(event) { return this.doActionTransition("Resize", "mouseover", event); },			mouseup: function(event) { this.frame.style.opacity = '1'; return 'Inactive'; }		}	},	doActionTransition: function(anotherState, anotherEventType, event) { return this.actionTransitionFunctions[anotherState][anotherEventType].call(this,event); },	display: function { document.body.appendChild( this.frame ); },	setTitle: function( title ) { this.title.textContent = title; },	setWidth: function( width ) { this.frame.style.width = width; },	setHeight: function( height ) { this.frame.style.height = height; },	setContent: function( content ) { this.purgeContent; this.addContent( content ); },	addContent: function( content ) { this.content.appendChild( content ); },	purgeContent: function( content ) { while( this.content.hasChildNodes ) { this.content.removeChild( this.content.firstChild ); }	},	moveWindow: function( x, y ) { this.frame.style.left = x - this.initialX + 'px'; this.frame.style.top = y - this.initialY + 'px'; },	resizeWindow: function( x, y ) { this.frame.style.height = Math.max( parseInt( y - this.frame.offsetTop ), 200 ) + 'px'; this.frame.style.width = Math.max( parseInt( x - this.frame.offsetLeft ), 200 ) + 'px'; } }

// to check of morebits had loaded morebits_js_loaded = true;

title: User:Flewis/morebits.js